commit 2a9b2dc40ba0a95f4cc590287bf44c88dc381bd7
parent 25b9ad89d69c69bdec64724c8c79e72331ee9bdb
Author: vaplv <vaplv@free.fr>
Date: Fri, 21 Feb 2020 15:53:26 +0100
Merge branch 'release_2.0'
Diffstat:
| D | COPYING.LESSER | | | 165 | ------------------------------------------------------------------------------- |
| M | README.md | | | 29 | +++++++++++++++++++++++++---- |
| M | cmake/CMakeLists.txt | | | 15 | +++++++++------ |
| M | src/aw.c | | | 81 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------- |
| M | src/aw.h | | | 144 | +++++++++++++++++++++++++------------------------------------------------------ |
| M | src/aw_c.h | | | 66 | ++++++++++++++++-------------------------------------------------- |
| M | src/aw_mtl.c | | | 939 | +++++++++++++++++++++++++++++++++++++++++++++---------------------------------- |
| M | src/aw_obj.c | | | 847 | ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
| A | src/test_aw.c | | | 63 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | src/test_aw_mtl.c | | | 326 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
| M | src/test_aw_obj.c | | | 402 | +++++++++++++++++++++++++++++++++++++++---------------------------------------- |
11 files changed, 1620 insertions(+), 1457 deletions(-)
diff --git a/COPYING.LESSER b/COPYING.LESSER
@@ -1,165 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
diff --git a/README.md b/README.md
@@ -28,6 +28,27 @@ can be edited, built, tested and installed as any CMake project.
## Release notes
+### Version 2.0
+
+Full review and refactoring of the code.
+
+- The named groups, the maps and the materials become pod data structures
+ without any init/release/copy function. Their name is now exposed as a
+ regular `const char*` rather than stored in a `struct str` data structure.
+- All floating point data are encoded in double precision rather than in single
+ precision.
+- The `struct aw_obj_vertex` data structure stores only the index of the vertex
+ attributes. Their values are retrieved by the new `aw_obj_get_vertex_data`
+ function.
+- Add an optional stream name parameter to the `aw_<obj|mtl>_load_stream`
+ functions: it allows the user to define the name of the stream to load, a
+ name that is internally used by the logger to print messages regarding the
+ stream.
+- Rename the `get` functions.
+- Rely on RSys to parse the input files and to perform text conversions.
+- Add support of the `map_bump` keyword as an alias of the `bump` keyword in
+ the mtl fileformat.
+
### Version 1.3.1
- Update the version of the RSys dependency to 0.6: replace the deprecated
@@ -41,7 +62,7 @@ can be edited, built, tested and installed as any CMake project.
## License
-AW is Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr). It is a free
-software released under the [OSI](https://opensource.org)-approved LGPL v3+
-license. You are welcome to redistribute it under certain conditions; refer to
-the COPYING file for details.
+Copyright (C) 2014-2017, 2020 Vincent Forest (vaplv@free.fr). AW is free
+software released under GPL v3+ license: GNU GPL version 3 or later. You are
+welcome to redistribute it under certain conditions; refer to the COPYING file
+for details.
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr)
+# Copyright (C) 2014-2017, 2020 Vincent Forest (vaplv@free.fr)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@ set(AW_SOURCE_DIR ${PROJECT_SOURCE_DIR}/../src)
# Dependencies
################################################################################
find_package(RCMake 0.4 REQUIRED)
-find_package(RSys 0.6 REQUIRED)
+find_package(RSys 0.9 REQUIRED)
set(CMAKE_MODULE_PATH ${RCMAKE_SOURCE_DIR})
include(rcmake)
@@ -36,14 +36,14 @@ rcmake_append_runtime_dirs(_runtime_dirs RSys)
################################################################################
# Define targets
################################################################################
-set(VERSION_MAJOR 1)
-set(VERSION_MINOR 3)
-set(VERSION_PATCH 1)
+set(VERSION_MAJOR 2)
+set(VERSION_MINOR 0)
+set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(AW_FILES_SRC aw_c.h aw.c aw_obj.c aw_mtl.c)
set(AW_FILES_INC aw.h)
-set(AW_FILES_DOC COPYING COPYING.LESSER README.md)
+set(AW_FILES_DOC COPYING README.md)
rcmake_prepend_path(AW_FILES_SRC ${AW_SOURCE_DIR})
rcmake_prepend_path(AW_FILES_INC ${AW_SOURCE_DIR})
rcmake_prepend_path(AW_FILES_DOC ${PROJECT_SOURCE_DIR}/../)
@@ -76,6 +76,9 @@ if(NOT NO_TEST)
target_link_libraries(test_aw_mtl aw)
add_test(test_aw_mtl test_aw_mtl)
rcmake_set_test_runtime_dirs(test_aw_mtl _runtime_dirs)
+
+ add_executable(test_aw ${AW_SOURCE_DIR}/test_aw.c)
+ target_link_libraries(test_aw aw)
endif(NOT NO_TEST)
################################################################################
diff --git a/src/aw.c b/src/aw.c
@@ -1,8 +1,8 @@
-/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr)
+/* Copyright (C) 2014-2017, 2020 Vincent Forest (vaplv@free.fr)
*
* This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -16,43 +16,86 @@
#define _POSIX_C_SOURCE 200112L /* strtok_r support */
#include "aw_c.h"
+#include <rsys/cstr.h>
+#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
#include <string.h>
/*******************************************************************************
+ * Helper functions
+ ******************************************************************************/
+static void
+print_info(const char* msg, void* ctx)
+{
+ fprintf(stderr, "%s%s", ctx ? (const char*)ctx : "info: ", msg);
+}
+
+static void
+print_err(const char* msg, void* ctx)
+{
+ fprintf(stderr, "%s%s", ctx ? (const char*)ctx : "error: ", msg);
+}
+
+static void
+print_warn(const char* msg, void* ctx)
+{
+ fprintf(stderr, "%s%s", ctx ? (const char*)ctx : "warning: ", msg);
+}
+
+/*******************************************************************************
* Local functions
******************************************************************************/
res_T
-parse_floatX
- (float* f,
+parse_doubleX
+ (double* dblX,
const unsigned int count_min,
const unsigned int count_max,
- const float range_min,
- const float range_max,
- const float default_value,
- char** tk_ctxt)
+ const double range_min,
+ const double range_max,
+ const double default_value,
+ char** tk_ctx)
{
size_t i;
- ASSERT(f && count_min <= count_max && range_min <= range_max && tk_ctxt);
+ ASSERT(dblX && count_min <= count_max && range_min <= range_max && tk_ctx);
ASSERT(default_value >= range_min && default_value <= range_max);
FOR_EACH(i, 0, count_max) {
- char* real;
- res_T res;
- if(NULL == (real = strtok_r(NULL, " ", tk_ctxt)))
- break;
- res = string_to_float(real, f + i);
- if(res != RES_OK)
- return res;
- if(f[i] < range_min || f[i] > range_max)
+ char* real = strtok_r(NULL, " \t", tk_ctx);
+ res_T res = RES_OK;
+
+ if(!real) break;
+
+ res = cstr_to_double(real, dblX + i);
+ if(res != RES_OK) return res;
+
+ if(dblX[i] < range_min || dblX[i] > range_max)
return RES_BAD_ARG;
}
if(i < count_min)
return RES_BAD_ARG;
FOR_EACH(i, i, count_max)
- f[i] = default_value;
+ dblX[i] = default_value;
+
+ return RES_OK;
+}
+res_T
+setup_default_logger
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ const char* prefix_info, /* May be NULL */
+ const char* prefix_error, /* May be NULL */
+ const char* prefix_warning) /* May be NULL */
+{
+ res_T res = RES_OK;
+ ASSERT(logger);
+ res = logger_init(allocator, logger);
+ if(res != RES_OK) return res;
+ logger_set_stream(logger, LOG_OUTPUT, print_info, (void*)prefix_info);
+ logger_set_stream(logger, LOG_ERROR, print_err, (void*)prefix_error);
+ logger_set_stream(logger, LOG_WARNING, print_warn, (void*)prefix_warning);
return RES_OK;
}
+
diff --git a/src/aw.h b/src/aw.h
@@ -1,8 +1,8 @@
-/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr)
+/* Copyright (C) 2014-2017, 2020 Vincent Forest (vaplv@free.fr)
*
* This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -73,49 +73,55 @@ struct aw_obj_face {
};
struct aw_obj_named_group {
- struct str name;
- size_t face_id; /* Index of the first group face */
+ const char* name;
+ size_t face_id;
size_t faces_count;
};
struct aw_obj_smooth_group {
- char is_smoothed;
size_t face_id; /* Index of the first smooth group face */
size_t faces_count;
+ char is_smoothed;
};
struct aw_obj_vertex {
- float position[4];
- float normal[3];
- float texcoord[3];
+ size_t position_id;
+ size_t texcoord_id;
+ size_t normal_id;
+};
+
+struct aw_obj_vertex_data {
+ double position[4];
+ double normal[3];
+ double texcoord[3];
};
struct aw_color {
- float value[3];
+ double value[3];
enum aw_color_space color_space;
};
struct aw_map {
- struct str filename; /* str_len == 0 <=> Not defined */
+ const char* filename; /* NULL <=> Not defined */
int options_mask;
- float image_bias; /* Scalar to add to the image pixels */
- float image_scale; /* Scalar to multiply to the image pixels */
- float texcoord_bias[3];
- float texcoord_scale[3];
- float texcoord_turbulence[3];
+ double image_bias; /* Scalar to add to the image pixels */
+ double image_scale; /* Scalar to multiply to the image pixels */
+ double texcoord_bias[3];
+ double texcoord_scale[3];
+ double texcoord_turbulence[3];
size_t resolution; /* image size = resolution x resolution */
enum aw_map_channel scalar; /* Channel used to create a scalar texture */
- float bump_multiplier; /* Only available on bump maps */
+ double bump_multiplier; /* Only available on bump maps */
};
struct aw_material {
- struct str name;
+ const char* name;
struct aw_color ambient;
struct aw_color diffuse;
struct aw_color specular;
struct aw_color transmission;
- float specular_exponent;
- float refraction_index;
+ double specular_exponent;
+ double refraction_index;
size_t illumination_model; /* In [0, 10] */
struct aw_map ambient_map;
struct aw_map diffuse_map;
@@ -157,7 +163,8 @@ aw_obj_load
AW_API res_T
aw_obj_load_stream
(struct aw_obj* obj,
- FILE* stream);
+ FILE* stream,
+ const char* stream_name); /* May be NULL <=> default name, i.e. "stream" */
AW_API res_T
aw_obj_clear
@@ -169,46 +176,52 @@ aw_obj_purge
(struct aw_obj* obj);
AW_API res_T
-aw_obj_desc_get
- (struct aw_obj* obj,
+aw_obj_get_desc
+ (const struct aw_obj* obj,
struct aw_obj_desc* desc);
AW_API res_T
-aw_obj_face_get
+aw_obj_get_face
(const struct aw_obj* obj,
const size_t face_id,
struct aw_obj_face* face);
AW_API res_T
-aw_obj_group_get
+aw_obj_get_group
(const struct aw_obj* obj,
const size_t group_id,
struct aw_obj_named_group* group);
AW_API res_T
-aw_obj_smooth_group_get
+aw_obj_get_smooth_group
(const struct aw_obj* obj,
const size_t smooth_group_id,
struct aw_obj_smooth_group* smooth_group);
AW_API res_T
-aw_obj_mtl_get
+aw_obj_get_mtl
(const struct aw_obj* obj,
const size_t mtl_id,
struct aw_obj_named_group* mtl);
AW_API res_T
-aw_obj_mtllib_get
+aw_obj_get_mtllib
(const struct aw_obj* obj,
const size_t mtllib_id,
const char** mtllib);
AW_API res_T
-aw_obj_vertex_get
+aw_obj_get_vertex
(const struct aw_obj* obj,
const size_t vertex_id,
struct aw_obj_vertex* vertex);
+AW_API res_T
+aw_obj_get_vertex_data
+ (const struct aw_obj* obj,
+ const struct aw_obj_vertex* vertex,
+ struct aw_obj_vertex_data* vertex_data);
+
/*******************************************************************************
* Mtl functions
******************************************************************************/
@@ -235,7 +248,8 @@ aw_mtl_load
AW_API res_T
aw_mtl_load_stream
(struct aw_mtl* mtl,
- FILE* stream);
+ FILE* stream,
+ const char* stream_name); /* May be NULL <=> default name, i.e. "stream" */
AW_API res_T
aw_mtl_clear
@@ -247,83 +261,17 @@ aw_mtl_purge
(struct aw_mtl* mtl);
AW_API res_T
-aw_mtl_materials_count_get
+aw_mtl_get_materials_count
(struct aw_mtl* mtl,
size_t* materials_count);
/* The filled material must be released by the aw_material_release function */
AW_API res_T
-aw_mtl_material_get
+aw_mtl_get_material
(struct aw_mtl* mtl,
const size_t imaterial,
struct aw_material* material);
-/*******************************************************************************
- * Obj group functions
- ******************************************************************************/
-AW_API res_T
-aw_obj_named_group_init
- (struct mem_allocator* allocator,
- struct aw_obj_named_group* grp);
-
-AW_API res_T
-aw_obj_named_group_release
- (struct aw_obj_named_group* grp);
-
-AW_API res_T
-aw_obj_named_group_copy
- (struct aw_obj_named_group* dst,
- const struct aw_obj_named_group* src);
-
-AW_API res_T
-aw_obj_named_group_copy_and_release
- (struct aw_obj_named_group* dst,
- struct aw_obj_named_group* src);
-
-/*******************************************************************************
- * Map functions
- ******************************************************************************/
-AW_API res_T
-aw_map_init
- (struct mem_allocator* allocator,
- struct aw_map* map);
-
-AW_API res_T
-aw_map_release
- (struct aw_map* map);
-
-AW_API res_T
-aw_map_copy
- (struct aw_map* dst,
- const struct aw_map* src);
-
-AW_API res_T
-aw_map_copy_and_release
- (struct aw_map* dst,
- struct aw_map* src);
-
-/*******************************************************************************
- * Material functions
- ******************************************************************************/
-AW_API res_T
-aw_material_init
- (struct mem_allocator* allocator,
- struct aw_material* material);
-
-AW_API res_T
-aw_material_release
- (struct aw_material* material);
-
-AW_API res_T
-aw_material_copy
- (struct aw_material* dst,
- const struct aw_material* src);
-
-AW_API res_T
-aw_material_copy_and_release
- (struct aw_material* dst,
- struct aw_material* src);
-
END_DECLS
#endif /* AW_H */
diff --git a/src/aw_c.h b/src/aw_c.h
@@ -1,8 +1,8 @@
-/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr)
+/* Copyright (C) 2014-2017, 2020 Vincent Forest (vaplv@free.fr)
*
* This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -18,57 +18,23 @@
#include "aw.h"
-static FINLINE res_T
-string_to_float(const char* str, float* f)
-{
- char* ptr = NULL;
- ASSERT(f);
- if(!str)
- return RES_BAD_ARG;
- *f = (float)strtod(str, &ptr);
- if(ptr == str || *ptr != '\0')
- return RES_BAD_ARG;
- return RES_OK;
-}
-
-static FINLINE res_T
-string_to_long(const char* str, long* i)
-{
- char* ptr = NULL;
- ASSERT(i);
- if(!str)
- return RES_BAD_ARG;
- *i = strtol(str, &ptr, 10);
- if(ptr == str || *ptr != '\0')
- return RES_BAD_ARG;
- return RES_OK;
-}
-
-static FINLINE res_T
-string_to_size_t(const char* str, size_t* i)
-{
- long l;
- res_T res;
- ASSERT(i);
-
- res = string_to_long(str, &l);
- if(res != RES_OK)
- return res;
- if(l < 0)
- return RES_BAD_ARG;
- *i = (size_t)l;
- return RES_OK;
-}
-
extern LOCAL_SYM res_T
-parse_floatX
- (float* f,
+parse_doubleX
+ (double* dblX,
const unsigned int count_min,
const unsigned int count_max,
- const float range_min,
- const float range_max,
- const float default_value,
+ const double range_min,
+ const double range_max,
+ const double default_value,
char** tk_ctxt);
+extern LOCAL_SYM res_T
+setup_default_logger
+ (struct mem_allocator* allocator,
+ struct logger* logger,
+ const char* prefix_info, /* May be NULL */
+ const char* prefix_error, /* May be NULL */
+ const char* prefix_warning); /* May be NULL */
+
#endif /* AW_C_H */
diff --git a/src/aw_mtl.c b/src/aw_mtl.c
@@ -1,8 +1,8 @@
-/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr)
+/* Copyright (C) 2014-2017, 2020 Vincent Forest (vaplv@free.fr)
*
* This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,13 +17,13 @@
#include "aw_c.h"
-#include <rsys/clock_time.h>
-#include <rsys/dynamic_array_char.h>
-#include <rsys/float3.h>
+#include <rsys/cstr.h>
+#include <rsys/double3.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
#include <rsys/ref_count.h>
#include <rsys/str.h>
+#include <rsys/text_reader.h>
#include <float.h>
@@ -32,6 +32,10 @@
#pragma warning(disable:4706) /* Assignment within a condition */
#endif
+static const char* MSG_PREFIX_INFO = "load-mtl:info: ";
+static const char* MSG_PREFIX_ERROR = "load-mtl:error: ";
+static const char* MSG_PREFIX_WARNING = "load-mtl:warning: ";
+
enum map_type {
MAP_COMMON = BIT(0),
MAP_SCALAR = BIT(1),
@@ -39,19 +43,196 @@ enum map_type {
};
/*******************************************************************************
- * Definition of the aw_mtl opaque data structure
+ * Map data structure
+ ******************************************************************************/
+struct map {
+ struct str filename; /* str_len == 0 <=> Not defined */
+ int options_mask;
+ double image_bias; /* Scalar to add to the image pixels */
+ double image_scale; /* Scalar to multiply to the image pixels */
+ double texcoord_bias[3];
+ double texcoord_scale[3];
+ double texcoord_turbulence[3];
+ size_t resolution; /* image size = resolution x resolution */
+ enum aw_map_channel scalar; /* Channel used to create a scalar texture */
+ double bump_multiplier; /* Only available on bump maps */
+};
+
+static INLINE void
+map_init(struct mem_allocator* allocator, struct map* map)
+{
+ ASSERT(map);
+ str_init(allocator, &map->filename);
+ map->options_mask = 0;
+ map->image_bias = 0.f;
+ map->image_scale = 1.f;
+ d3_splat(map->texcoord_bias, 0.f);
+ d3_splat(map->texcoord_scale, 1.f);
+ d3_splat(map->texcoord_turbulence, 0.f);
+ map->resolution = 0;
+ map->scalar = AW_MAP_CHANNEL_LUMINANCE;
+ map->bump_multiplier = 1.0f;
+}
+
+static INLINE void
+map_release(struct map* map)
+{
+ ASSERT(map);
+ str_release(&map->filename);
+}
+
+static INLINE void
+map_copy_pod(struct map* dst, const struct map* src)
+{
+ ASSERT(dst && src);
+ dst->options_mask = src->options_mask;
+ dst->image_bias = src->image_bias;
+ dst->image_scale = src->image_scale;
+ d3_set(dst->texcoord_bias, src->texcoord_bias);
+ d3_set(dst->texcoord_scale, src->texcoord_scale);
+ d3_set(dst->texcoord_turbulence, src->texcoord_turbulence);
+ dst->resolution = src->resolution;
+ dst->scalar = src->scalar;
+ dst->bump_multiplier = src->bump_multiplier;
+}
+
+static INLINE res_T
+map_copy(struct map* dst, const struct map* src)
+{
+ map_copy_pod(dst, src);
+ return str_copy(&dst->filename, &src->filename);
+}
+
+static INLINE res_T
+map_copy_and_release(struct map* dst, struct map* src)
+{
+ map_copy_pod(dst, src);
+ return str_copy_and_release(&dst->filename, &src->filename);
+}
+
+static INLINE void
+map_to_aw_map(const struct map* map, struct aw_map* aw_map)
+{
+ ASSERT(map && aw_map);
+ aw_map->filename = str_is_empty(&map->filename) ? NULL : str_cget(&map->filename);
+ aw_map->options_mask = map->options_mask;
+ aw_map->image_bias = map->image_bias;
+ aw_map->image_scale = map->image_scale;
+ d3_set(aw_map->texcoord_bias, map->texcoord_bias);
+ d3_set(aw_map->texcoord_scale, map->texcoord_scale);
+ d3_set(aw_map->texcoord_turbulence, map->texcoord_turbulence);
+ aw_map->resolution = map->resolution;
+ aw_map->scalar = map->scalar;
+ aw_map->bump_multiplier = map->bump_multiplier;
+}
+
+/*******************************************************************************
+ * Material API
******************************************************************************/
+struct material {
+ struct str name;
+ struct aw_color ambient;
+ struct aw_color diffuse;
+ struct aw_color specular;
+ struct aw_color transmission;
+ double specular_exponent;
+ double refraction_index;
+ size_t illumination_model; /* In [0, 10] */
+ struct map ambient_map;
+ struct map diffuse_map;
+ struct map specular_map;
+ struct map specular_exponent_map; /* Scalar texture */
+ struct map bump_map; /* Scalar texture with valid bump multiplier */
+};
+
+static INLINE void
+material_init(struct mem_allocator* allocator, struct material* mtl)
+{
+ ASSERT(mtl);
+ memset(mtl, 0, sizeof(struct aw_material));
+ str_init(allocator, &mtl->name);
+ map_init(allocator, &mtl->ambient_map);
+ map_init(allocator, &mtl->diffuse_map);
+ map_init(allocator, &mtl->specular_map);
+ map_init(allocator, &mtl->specular_exponent_map);
+ map_init(allocator, &mtl->bump_map);
+}
+
+static INLINE void
+material_release(struct material* mtl)
+{
+ ASSERT(mtl);
+ str_release(&mtl->name);
+ map_release(&mtl->ambient_map);
+ map_release(&mtl->diffuse_map);
+ map_release(&mtl->specular_map);
+ map_release(&mtl->specular_exponent_map);
+ map_release(&mtl->bump_map);
+}
+
+static INLINE void
+material_copy_pod(struct material* dst, const struct material* src)
+{
+ ASSERT(dst && src);
+ dst->ambient = src->ambient;
+ dst->diffuse = src->diffuse;
+ dst->specular = src->specular;
+ dst->transmission = src->transmission;
+ dst->specular_exponent = src->specular_exponent;
+ dst->refraction_index = src->refraction_index;
+ dst->illumination_model = src->illumination_model;
+}
+
+static INLINE res_T
+material_copy(struct material* dst, const struct material* src)
+{
+ res_T res = RES_OK;
+ ASSERT(dst && src);
+ material_copy_pod(dst, src);
+ #define CALL(Func) if(RES_OK != (res = Func)) return res
+ CALL(str_copy(&dst->name, &src->name));
+ CALL(map_copy(&dst->ambient_map, &src->ambient_map));
+ CALL(map_copy(&dst->diffuse_map, &src->diffuse_map));
+ CALL(map_copy(&dst->specular_map, &src->specular_map));
+ CALL(map_copy(&dst->specular_exponent_map, &src->specular_exponent_map));
+ CALL(map_copy(&dst->bump_map, &src->bump_map));
+ #undef CALL
+ return RES_OK;
+}
+
+static INLINE res_T
+material_copy_and_release(struct material* dst, struct material* src)
+{
+ res_T res = RES_OK;
+ ASSERT(dst && src);
+ material_copy_pod(dst, src);
+ #define CALL(Func) if(RES_OK != (res = Func)) return res
+ CALL(str_copy_and_release(&dst->name, &src->name));
+ CALL(map_copy_and_release(&dst->ambient_map, &src->ambient_map));
+ CALL(map_copy_and_release(&dst->diffuse_map, &src->diffuse_map));
+ CALL(map_copy_and_release(&dst->specular_map, &src->specular_map));
+ CALL(map_copy_and_release
+ (&dst->specular_exponent_map, &src->specular_exponent_map));
+ CALL(map_copy_and_release(&dst->bump_map, &src->bump_map));
+ #undef CALL
+ return RES_OK;
+}
+
/* Generate the darray_mtl data structure */
#define DARRAY_NAME material
-#define DARRAY_DATA struct aw_material
-#define DARRAY_FUNCTOR_INIT aw_material_init
-#define DARRAY_FUNCTOR_RELEASE aw_material_release
-#define DARRAY_FUNCTOR_COPY aw_material_copy
+#define DARRAY_DATA struct material
+#define DARRAY_FUNCTOR_INIT material_init
+#define DARRAY_FUNCTOR_RELEASE material_release
+#define DARRAY_FUNCTOR_COPY material_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE material_copy_and_release
#include <rsys/dynamic_array.h>
+/*******************************************************************************
+ * Definition of the aw_mtl opaque data structure
+ ******************************************************************************/
struct aw_mtl {
struct darray_material materials;
- struct aw_material* newmtl; /* Pointer toward the current material */
+ struct material* newmtl; /* Pointer toward the current material */
const char* filename; /* Currently parsed file. Use in error messages */
size_t iline; /* Currently parsed line index. Use in error messages */
@@ -59,117 +240,160 @@ struct aw_mtl {
ref_T ref;
struct mem_allocator* allocator;
struct logger* logger;
+ struct logger logger__; /* Default logger */
int verbose;
};
/*******************************************************************************
* Helper functions
******************************************************************************/
-static INLINE res_T
-parse_name(struct str* name, char* tk, char** tk_ctxt)
+static INLINE void
+log_msg
+ (const struct aw_mtl* mtl,
+ const enum log_type stream,
+ const char* msg,
+ va_list vargs)
{
- res_T res = RES_OK;
- ASSERT(tk_ctxt && name);
-
- if(!tk) {
- res = RES_BAD_ARG;
- goto error;
+ ASSERT(mtl && msg);
+ if(mtl->verbose) {
+ res_T res; (void)res;
+ res = logger_vprint(mtl->logger, stream, msg, vargs);
+ ASSERT(res == RES_OK);
}
- str_clear(name);
- do {
- res = str_append(name, tk);
- if(res != RES_OK) goto error;
- } while((tk = strtok_r(NULL, " \t", tk_ctxt)));
+}
-exit:
- return res;
-error:
- str_clear(name);
- goto exit;
+static INLINE void
+log_err(const struct aw_mtl* mtl, const char* msg, ...)
+{
+ va_list vargs_list;
+ ASSERT(mtl && msg);
+
+ va_start(vargs_list, msg);
+ log_msg(mtl, LOG_ERROR, msg, vargs_list);
+ va_end(vargs_list);
+}
+
+static INLINE void
+log_warn(const struct aw_mtl* mtl, const char* msg, ...)
+{
+ va_list vargs_list;
+ ASSERT(mtl && msg);
+
+ va_start(vargs_list, msg);
+ log_msg(mtl, LOG_WARNING, msg, vargs_list);
+ va_end(vargs_list);
}
static res_T
-parse_newmtl(struct aw_mtl* mtl, char** word_tk)
+parse_newmtl(struct aw_mtl* mtl, char** tk_ctx)
{
- char* word;
+ struct material* newmtl = NULL;
+ char* tk = NULL;
size_t nmtls;
- res_T res;
- ASSERT(mtl && word_tk);
+ res_T res = RES_OK;
+ ASSERT(mtl && tk_ctx);
- word = strtok_r(NULL, "\n", word_tk);
- if(!word)
- return RES_BAD_ARG;
+ tk = strtok_r(NULL, " \t", tk_ctx); /* Blanks are prohibited in mtl name */
+ if(!tk) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
nmtls = darray_material_size_get(&mtl->materials);
+
+ /* Allocate the new material */
res = darray_material_resize(&mtl->materials, nmtls + 1);
- if(res != RES_OK)
- return res;
+ if(res != RES_OK) goto error;
- mtl->newmtl = darray_material_data_get(&mtl->materials) + nmtls;
- res = parse_name(&mtl->newmtl->name, word, word_tk);
- if(res != RES_OK) {
- darray_material_pop_back(&mtl->materials);
- mtl->newmtl = NULL;
- return res;
- }
+ /* Fetch the new material */
+ newmtl = darray_material_data_get(&mtl->materials) + nmtls;
+
+ /* Setup the material name */
+ res = str_set(&newmtl->name, tk);
+ if(res != RES_OK) goto error;
+
+ /* Set the new material as the material to parse */
+ mtl->newmtl = newmtl;
+
+exit:
return RES_OK;
+error:
+ if(newmtl) darray_material_pop_back(&mtl->materials);
+ goto exit;
}
static res_T
-parse_color(struct aw_mtl* mtl, struct aw_color* col, char** word_tk)
+parse_color(struct aw_mtl* mtl, struct aw_color* col, char** tk_ctx)
{
- char* word;
+ char* tk = NULL;
res_T res = RES_OK;
- ASSERT(mtl && col && word_tk);
+ ASSERT(mtl && col && tk_ctx);
- word = strtok_r(NULL, " \t", word_tk);
- if(!word)
- return RES_BAD_ARG;
+ tk = strtok_r(NULL, " \t", tk_ctx);
+ if(!tk) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
- if(!strcmp(word, "spectral")) {
- if(mtl->verbose) {
- logger_print
- (mtl->logger, LOG_ERROR, "spectral colors are not supported\n");
- }
- return RES_BAD_ARG;
+ if(!strcmp(tk, "spectral")) {
+ log_err(mtl, "spectral colors are not supported\n");
+ res = RES_BAD_ARG;
+ goto error;
}
- col->color_space = strcmp(word, "xyz") == 0 ? AW_COLOR_XYZ : AW_COLOR_RGB;
- if(col->color_space == AW_COLOR_XYZ
- && !(word = strtok_r(NULL, " \t", word_tk)))
- return RES_BAD_ARG;
+ if(strcmp(tk, "xyz")) {
+ col->color_space = AW_COLOR_RGB;
+ } else {
+ col->color_space = AW_COLOR_XYZ;
+ tk = strtok_r(NULL, " \t", tk_ctx);
+ if(!tk) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ }
- if(RES_OK != (res = string_to_float(word, &col->value[0])))
- return res;
+ res = cstr_to_double(tk, &col->value[0]);
+ if(res != RES_OK) goto error;
/* If only the first component is defined the second and third components are
* assumed to be equal to the first one */
- word = strtok_r(NULL, " \t", word_tk);
- if(!word) {
- col->value[1] = col->value[2] = col->value[0];
+ tk = strtok_r(NULL, " \t", tk_ctx);
+ if(!tk) {
+ col->value[1] = col->value[0];
+ col->value[2] = col->value[0];
} else {
- if(RES_OK != (res = string_to_float(word, &col->value[1])))
- return res;
- word = strtok_r(NULL, " \t", word_tk);
- if(RES_OK != (res = string_to_float(word, &col->value[2])))
- return res;
+ res = cstr_to_double(tk, &col->value[1]);
+ if(res != RES_OK) goto error;
+
+ tk = strtok_r(NULL, " \t", tk_ctx);
+ if(!tk) { res = RES_BAD_ARG; goto error; }
+
+ res = cstr_to_double(tk, &col->value[2]);
+ if(res == RES_OK) goto error;
}
- return RES_OK;
+
+exit:
+ return res;
+error:
+ goto exit;
}
static INLINE res_T
parse_size_t
- (size_t* s, const size_t range_min, const size_t range_max, char** word_tk)
+ (size_t* s, const size_t range_min, const size_t range_max, char** tk_ctx)
{
- char* word;
+ unsigned long ul;
+ char* tk = NULL;
res_T res = RES_OK;
- ASSERT(s && word_tk && range_min < range_max);
+ ASSERT(s && tk_ctx && range_min < range_max);
- word = strtok_r(NULL, "\n", word_tk);
- if(RES_OK != (res = string_to_size_t(word, s)))
- return res;
- if(range_min > *s || range_max < *s)
- return RES_BAD_ARG;
+ tk = strtok_r(NULL, "\n", tk_ctx);
+ if(!tk) return res;
+
+ res = cstr_to_ulong(tk, &ul);
+ if(res != RES_OK) return res;
+ if((unsigned long)range_min > ul || (unsigned long)range_max < ul) return res;
+ *s = ul;
return RES_OK;
}
@@ -177,40 +401,44 @@ static res_T
parse_bool_option
(int* options_mask,
const enum aw_map_flag option,
- char** tk_ctxt)
+ char** tk_ctx)
{
- char* word;
- ASSERT(options_mask && tk_ctxt);
- word = strtok_r(NULL, " \t", tk_ctxt);
- if(!word)
- return RES_BAD_ARG;
- if(strcmp(word, "on") == 0) {
+ char* tk;
+ ASSERT(options_mask && tk_ctx);
+
+ tk = strtok_r(NULL, " \t", tk_ctx);
+ if(!tk) return RES_BAD_ARG;
+
+ if(!strcmp(tk, "on")) {
*options_mask |= (int)option;
- } else if(strcmp(word, "off") != 0) {
+ } else if(!strcmp(tk, "off")) {
+ *options_mask &= ~((int)option);
+ } else {
return RES_BAD_ARG;
}
return RES_OK;
}
static FINLINE res_T
-parse_imfchan_option(enum aw_map_channel* channel, char** tk_ctxt)
+parse_imfchan_option(enum aw_map_channel* channel, char** tk_ctx)
{
- char* word;
- ASSERT(channel && tk_ctxt);
- word = strtok_r(NULL, " \t", tk_ctxt);
- if(!word)
- return RES_BAD_ARG;
- if(!strcmp(word, "r")) {
+ char* tk = NULL;
+ ASSERT(channel && tk_ctx);
+
+ tk = strtok_r(NULL, " \t", tk_ctx);
+ if(!tk) return RES_BAD_ARG;
+
+ if(!strcmp(tk, "r")) {
*channel = AW_MAP_CHANNEL_RED;
- } else if(!strcmp(word, "g")) {
+ } else if(!strcmp(tk, "g")) {
*channel = AW_MAP_CHANNEL_GREEN;
- } else if(!strcmp(word, "b")) {
+ } else if(!strcmp(tk, "b")) {
*channel = AW_MAP_CHANNEL_BLUE;
- } else if(!strcmp(word, "m")) {
+ } else if(!strcmp(tk, "m")) {
*channel = AW_MAP_CHANNEL_MATTE;
- } else if(!strcmp(word, "l")) {
+ } else if(!strcmp(tk, "l")) {
*channel = AW_MAP_CHANNEL_LUMINANCE;
- } else if(!strcmp(word, "z")) {
+ } else if(!strcmp(tk, "z")) {
*channel = AW_MAP_CHANNEL_DEPTH;
} else {
return RES_BAD_ARG;
@@ -219,166 +447,182 @@ parse_imfchan_option(enum aw_map_channel* channel, char** tk_ctxt)
}
static res_T
-parse_map
- (struct aw_map* map,
- const enum map_type type,
- char** tk_ctxt)
-{
- char* word;
- ASSERT(map && tk_ctxt);
-
- word = strtok_r(NULL, " \t", tk_ctxt);
- while(word) {
- res_T res;
-
- if(!strcmp(word, "-blendu")) {
- res = parse_bool_option(&map->options_mask, AW_MAP_BLEND_U, tk_ctxt);
- } else if(!strcmp(word, "-blendv")) {
- res = parse_bool_option(&map->options_mask, AW_MAP_BLEND_V, tk_ctxt);
- } else if(!strcmp(word, "-cc")) {
+parse_map(struct map* map, const enum map_type type, char** tk_ctx)
+{
+ char* tk = NULL;
+ res_T res = RES_OK;
+ ASSERT(map && tk_ctx);
+
+ for(;;) {
+ tk = strtok_r(NULL, " \t", tk_ctx);
+ if(!tk) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!strcmp(tk, "-blendu")) {
+ res = parse_bool_option(&map->options_mask, AW_MAP_BLEND_U, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(tk, "-blendv")) {
+ res = parse_bool_option(&map->options_mask, AW_MAP_BLEND_V, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(tk, "-cc")) {
res = parse_bool_option
- (&map->options_mask, AW_MAP_COLOR_CORRECTION, tk_ctxt);
- } else if(!strcmp(word, "-clamp")) {
- res = parse_bool_option(&map->options_mask, AW_MAP_CLAMP, tk_ctxt);
- } else if(!strcmp(word, "-imfchan") && (type & MAP_SCALAR)) {
- res = parse_imfchan_option(&map->scalar, tk_ctxt);
- } else if(!strcmp(word, "-mm")) { /* Image bias and scale */
- res = parse_floatX
- (&map->image_bias, 1, 1, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt);
- if(res == RES_OK) {
- res = parse_floatX
- (&map->image_scale, 1, 1, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt);
+ (&map->options_mask, AW_MAP_COLOR_CORRECTION, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(tk, "-clamp")) {
+ res = parse_bool_option(&map->options_mask, AW_MAP_CLAMP, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(tk, "-imfchan") && (type & MAP_SCALAR)) {
+ res = parse_imfchan_option(&map->scalar, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(tk, "-mm")) { /* Image bias and scale */
+ res = parse_doubleX
+ (&map->image_bias, 1, 1, -DBL_MAX, DBL_MAX, 0.f, tk_ctx);
+ if(res != RES_OK) goto error;
+ res = parse_doubleX
+ (&map->image_scale, 1, 1, -DBL_MAX, DBL_MAX, 0.f, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(tk, "-o")) { /* Texcoord offset */
+ res = parse_doubleX
+ (map->texcoord_bias, 1, 3, -DBL_MAX, DBL_MAX, 0.f, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(tk, "-s")) { /* Texcoord scale */
+ res = parse_doubleX
+ (map->texcoord_scale, 1, 3, -DBL_MAX, DBL_MAX, 1.f, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(tk, "-t")) { /* Texcoord turbulence */
+ res = parse_doubleX
+ (map->texcoord_turbulence, 1, 3, -DBL_MAX, DBL_MAX, 0.f, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(tk, "-texres")) { /* Texture resolution */
+ res = parse_size_t(&map->resolution, 1, SIZE_MAX, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else if(!strcmp(tk, "-bm") && (type == MAP_BUMP)) {/* Bump multiplier */
+ res = parse_doubleX
+ (&map->bump_multiplier, 1, 1, -DBL_MAX, DBL_MAX, 0.f, tk_ctx);
+ if(res != RES_OK) goto error;
+ } else { /* Map filename */
+ res = str_set(&map->filename, tk);
+ if(res != RES_OK) goto error;
+ tk = strtok_r(NULL, "", tk_ctx);
+ if(tk) {
+ res = str_append_char(&map->filename, ' ');
+ if(res != RES_OK) goto error;
+ res = str_append(&map->filename, strtok_r(NULL, "", tk_ctx));
+ if(res != RES_OK) goto error;
}
- } else if(!strcmp(word, "-o")) { /* Texcoord offset */
- res = parse_floatX
- (map->texcoord_bias, 1, 3, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt);
- } else if(!strcmp(word, "-s")) { /* Texcoord scale */
- res = parse_floatX
- (map->texcoord_scale, 1, 3, -FLT_MAX, FLT_MAX, 1.f, tk_ctxt);
- } else if(!strcmp(word, "-t")) { /* Texcoord turbulence */
- res = parse_floatX
- (map->texcoord_turbulence, 1, 3,-FLT_MAX, FLT_MAX, 0.f, tk_ctxt);
- } else if(!strcmp(word, "-texres")) { /* Texture resolution */
- res = parse_size_t(&map->resolution, 1, SIZE_MAX, tk_ctxt);
- } else if(!strcmp(word, "-bm") && (type == MAP_BUMP)) {/* Bump multiplier */
- res = parse_floatX
- (&map->bump_multiplier, 1, 1, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt);
- } else {
- res = parse_name(&map->filename, word, tk_ctxt);
+ break; /* The map is fully parsed */
}
- if(res != RES_OK)
- return res;
- word = strtok_r(NULL, " \t", tk_ctxt);
}
- return RES_OK;
+
+exit:
+ return res;
+error:
+ goto exit;
}
static res_T
-parse_mtl_line(struct aw_mtl* mtl, char* line)
+parse_mtl_line(struct aw_mtl* mtl, struct txtrdr* txtrdr)
{
+ char* tk = NULL;
+ char* tk_ctx = NULL;
res_T res = RES_OK;
- char* word, *word_tk;
- ASSERT(mtl && line);
-
- word = strtok_r(line, " \t", &word_tk);
- if(word) {
- if(word[0] == '#') { /* Comment */
- goto exit;
- } else if(!strcmp(word, "newmtl")) { /* Material name declaration */
- res = parse_newmtl(mtl, &word_tk);
- } else if(mtl->newmtl == NULL) {
- res = RES_BAD_ARG;
- } else if(!strcmp(word, "Ka")) { /* Ambient reflectivity */
- res = parse_color(mtl, &mtl->newmtl->ambient, &word_tk);
- } else if(!strcmp(word, "Kd")) { /* Diffuse reflectivity */
- res = parse_color(mtl, &mtl->newmtl->diffuse, &word_tk);
- } else if(!strcmp(word, "Ks")) { /* Specular reflectivity */
- res = parse_color(mtl, &mtl->newmtl->specular, &word_tk);
- } else if(!strcmp(word, "Tf")) { /* Transimission filter */
- res = parse_color(mtl, &mtl->newmtl->transmission, &word_tk);
- } else if(!strcmp(word, "Ns")) { /* Specular exponent */
- res = parse_floatX
- (&mtl->newmtl->specular_exponent, 1, 1, 0.f, FLT_MAX, 0.f, &word_tk);
- } else if(!strcmp(word, "Ni")) { /* Refraction index */
- res = parse_floatX
- (&mtl->newmtl->refraction_index, 1, 1, 0.001f, 10.f, 0.001f,&word_tk);
- } else if(!strcmp(word, "illum")) { /* Illumination model */
- res = parse_size_t(&mtl->newmtl->illumination_model, 0, 10, &word_tk);
- } else if(!strcmp(word, "map_Ka")) { /* Ambient texture */
- res = parse_map(&mtl->newmtl->ambient_map, MAP_COMMON, &word_tk);
- } else if(!strcmp(word, "map_Kd")) { /* Diffuse texture */
- res = parse_map(&mtl->newmtl->diffuse_map, MAP_COMMON, &word_tk);
- } else if(!strcmp(word, "map_Ks")) { /* Specular texture */
- res = parse_map(&mtl->newmtl->specular_map, MAP_COMMON, &word_tk);
- } else if(!strcmp(word, "map_Ns")) { /* Specular exponent texture */
- res = parse_map
- (&mtl->newmtl->specular_exponent_map, MAP_SCALAR, &word_tk);
- } else if(!strcmp(word, "bump")) { /* Bump map */
- res = parse_map(&mtl->newmtl->bump_map, MAP_BUMP, &word_tk);
- } else {
- res = RES_OK;
- if(mtl->verbose) {
- logger_print(mtl->logger, LOG_WARNING,
- "%s:%lu: warning: ignored or malformed directive %s\n",
- mtl->filename, (unsigned long)mtl->iline, word);
- }
- while((word = strtok_r(NULL, " \t", &word_tk))); /* Skip spaces */
- }
- if(res != RES_OK)
- goto error;
- if((word = strtok_r(NULL, " ", &word_tk))) {
- if(mtl->verbose) {
- logger_print(mtl->logger, LOG_ERROR, "%s:%lu: unexpected directive %s\n",
- mtl->filename, (unsigned long)mtl->iline, word);
- }
- res = RES_BAD_ARG;
- goto error;
- }
+ ASSERT(mtl && txtrdr);
+
+ tk = strtok_r(txtrdr_get_line(txtrdr), " \t", &tk_ctx);
+ ASSERT(tk); /* A line should exist since it was parsed by txtrdr */
+
+ if(!strcmp(tk, "newmtl")) { /* Material name declaration */
+ res = parse_newmtl(mtl, &tk_ctx);
+ } else if(mtl->newmtl == NULL) {
+ res = RES_BAD_ARG;
+ } else if(!strcmp(tk, "Ka")) { /* Ambient reflectivity */
+ res = parse_color(mtl, &mtl->newmtl->ambient, &tk_ctx);
+ } else if(!strcmp(tk, "Kd")) { /* Diffuse reflectivity */
+ res = parse_color(mtl, &mtl->newmtl->diffuse, &tk_ctx);
+ } else if(!strcmp(tk, "Ks")) { /* Specular reflectivity */
+ res = parse_color(mtl, &mtl->newmtl->specular, &tk_ctx);
+ } else if(!strcmp(tk, "Tf")) { /* Transimission filter */
+ res = parse_color(mtl, &mtl->newmtl->transmission, &tk_ctx);
+ } else if(!strcmp(tk, "Ns")) { /* Specular exponent */
+ res = parse_doubleX
+ (&mtl->newmtl->specular_exponent, 1, 1, 0, DBL_MAX, 0, &tk_ctx);
+ } else if(!strcmp(tk, "Ni")) { /* Refraction index */
+ res = parse_doubleX
+ (&mtl->newmtl->refraction_index, 1, 1, 0.001, 10, 0.001, &tk_ctx);
+ } else if(!strcmp(tk, "illum")) { /* Illumination model */
+ res = parse_size_t(&mtl->newmtl->illumination_model, 0, 10, &tk_ctx);
+ } else if(!strcmp(tk, "map_Ka")) { /* Ambient texture */
+ res = parse_map(&mtl->newmtl->ambient_map, MAP_COMMON, &tk_ctx);
+ } else if(!strcmp(tk, "map_Kd")) { /* Diffuse texture */
+ res = parse_map(&mtl->newmtl->diffuse_map, MAP_COMMON, &tk_ctx);
+ } else if(!strcmp(tk, "map_Ks")) { /* Specular texture */
+ res = parse_map(&mtl->newmtl->specular_map, MAP_COMMON, &tk_ctx);
+ } else if(!strcmp(tk, "map_Ns")) { /* Specular exponent texture */
+ res = parse_map
+ (&mtl->newmtl->specular_exponent_map, MAP_SCALAR, &tk_ctx);
+ } else if(!strcmp(tk, "bump") || !strcmp(tk, "map_bump")) { /* Bump map */
+ res = parse_map(&mtl->newmtl->bump_map, MAP_BUMP, &tk_ctx);
+ } else {
+ log_warn(mtl,
+ "%s:%lu: warning: ignored or malformed directive `%s'\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk);
+ strtok_r(NULL, "", &tk_ctx); /* Discard remaining text */
}
+ if(res != RES_OK) {
+ log_err(mtl, "%s:%lu: parsing failed.\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk);
+ goto error;
+ }
+
+ tk = strtok_r(NULL, "", &tk_ctx);
+ if(tk) {
+ log_err(mtl, "%s:%lu: unexpected text `%s'.\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
exit:
return res;
error:
- if(mtl->verbose) {
- logger_print(mtl->logger, LOG_ERROR, "%s:%lu: error: parsing failed\n",
- mtl->filename, (unsigned long)mtl->iline);
- }
goto exit;
}
-static void
-mtl_clear(struct aw_mtl* mtl)
+static res_T
+load_stream(struct aw_mtl* mtl, FILE* stream, const char* stream_name)
{
- ASSERT(mtl);
- darray_material_clear(&mtl->materials);
- mtl->newmtl = NULL;
-}
+ struct txtrdr* txtrdr = NULL;
+ res_T res = RES_OK;
+ ASSERT(mtl && stream && stream_name);
-static FINLINE void
-map_copy_pod__(struct aw_map* dst, const struct aw_map* src)
-{
- ASSERT(dst && src);
- dst->options_mask = src->options_mask;
- dst->image_bias = src->image_bias;
- dst->image_scale = src->image_scale;
- f3_set(dst->texcoord_bias, src->texcoord_bias);
- f3_set(dst->texcoord_scale, src->texcoord_scale);
- f3_set(dst->texcoord_turbulence, src->texcoord_turbulence);
- dst->resolution = src->resolution;
- dst->scalar = src->scalar;
- dst->bump_multiplier = src->bump_multiplier;
-}
+ res = txtrdr_stream(mtl->allocator, stream, stream_name, '#', &txtrdr);
+ if(res != RES_OK) {
+ log_err(mtl, "Could not create the text reader.\n");
+ goto error;
+ }
-static FINLINE void
-material_copy_pod__(struct aw_material* dst, const struct aw_material* src)
-{
- ASSERT(dst && src);
- dst->ambient = src->ambient;
- dst->diffuse = src->diffuse;
- dst->specular = src->specular;
- dst->transmission = src->transmission;
- dst->specular_exponent = src->specular_exponent;
- dst->refraction_index = src->refraction_index;
- dst->illumination_model = src->illumination_model;
+ for(;;) {
+ res = txtrdr_read_line(txtrdr);
+ if(res != RES_OK) {
+ log_err(mtl, "%s: could not read the line `%lu'.\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr));
+ goto error;
+ }
+
+ if(!txtrdr_get_cline(txtrdr)) break; /* No more parsed line */
+
+ res = parse_mtl_line(mtl, txtrdr);
+ if(res != RES_OK) goto error;
+ }
+
+exit:
+ if(txtrdr) txtrdr_ref_put(txtrdr);
+ return res;
+error:
+ AW(mtl_clear(mtl));
+ goto exit;
}
static void
@@ -387,6 +631,7 @@ mtl_release(ref_T* ref)
struct aw_mtl* mtl = CONTAINER_OF(ref, struct aw_mtl, ref);
ASSERT(ref);
darray_material_release(&mtl->materials);
+ if(mtl->logger == &mtl->logger__) logger_release(&mtl->logger__);
MEM_RM(mtl->allocator, mtl);
}
@@ -416,13 +661,20 @@ aw_mtl_create
}
ref_init(&mtl->ref);
mtl->allocator = allocator;
- mtl->logger = logger ? logger : LOGGER_DEFAULT;
mtl->verbose = verbose;
darray_material_init(allocator, &mtl->materials);
+ if(logger) {
+ mtl->logger = logger;
+ } else {
+ res = setup_default_logger(mtl->allocator, &mtl->logger__,
+ MSG_PREFIX_INFO, MSG_PREFIX_ERROR, MSG_PREFIX_WARNING);
+ if(res != RES_OK) goto error;
+ mtl->logger = &mtl->logger__;
+ }
+
exit:
- if(mtl_out)
- *mtl_out = mtl;
+ if(mtl_out) *mtl_out = mtl;
return res;
error:
if(mtl) {
@@ -451,80 +703,47 @@ aw_mtl_ref_put(struct aw_mtl* mtl)
res_T
aw_mtl_load(struct aw_mtl* mtl, const char* filename)
{
- FILE* file;
+ FILE* file = NULL;
res_T res = RES_OK;
- if(!mtl || !filename)
- return RES_BAD_ARG;
+ if(!mtl || !filename) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
- mtl->filename = filename;
file = fopen(filename, "r");
if(!file) {
- if(mtl->verbose)
- logger_print(mtl->logger, LOG_ERROR, "Error opening `%s'\n", filename);
- return RES_IO_ERR;
+ log_err(mtl, "Error opening `%s'\n", filename);
+ res = RES_IO_ERR;
+ goto error;
}
- res = aw_mtl_load_stream(mtl, file);
- mtl->filename = NULL;
- fclose(file);
+ res = load_stream(mtl, file, filename);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(file) fclose(file);
return res;
+error:
+ goto exit;
}
res_T
-aw_mtl_load_stream(struct aw_mtl* mtl, FILE* stream)
+aw_mtl_load_stream(struct aw_mtl* mtl, FILE* stream, const char* stream_name)
{
- char* line;
- struct darray_char buf;
- const unsigned buf_chunk = 256;
res_T res = RES_OK;
- /* Avoid zealous "may be used uninitialized" warning of GCC 4.9.2 */
- memset(&buf, 0, sizeof(buf));
-
if(!mtl || !stream) {
res = RES_BAD_ARG;
goto error;
}
- darray_char_init(mtl->allocator, &buf);
-
- res = darray_char_resize(&buf, buf_chunk);
- if(res != RES_OK)
- goto error;
- if(!mtl->filename)
- mtl->filename = "stream";
- mtl->iline = 1;
- mtl_clear(mtl);
- while((line = fgets
- (darray_char_data_get(&buf), (int)darray_char_size_get(&buf), stream))) {
- size_t last_char;
-
- while(!strrchr(line,'\n')) { /* Ensure that the whole line was read */
- res = darray_char_resize(&buf, darray_char_size_get(&buf) + buf_chunk);
- if(res != RES_OK)
- goto error;
- line = darray_char_data_get(&buf);
- if(!fgets(line + strlen(line), (int)buf_chunk, stream)) /* EOF */
- break;
- }
- /* Remove the newline character(s) */
- last_char = strlen(line);
- while(last_char-- && (line[last_char]=='\n' || line[last_char]=='\r'));
- line[last_char + 1] = '\0';
-
- if(RES_OK != (res = parse_mtl_line(mtl, line)))
- goto error;
- ++mtl->iline;
- }
+ res = load_stream(mtl, stream, stream_name ? stream_name : "stream");
+ if(res != RES_OK) goto error;
exit:
- if(mtl && stream)
- darray_char_release(&buf);
return res;
error:
- if(mtl)
- mtl_clear(mtl);
goto exit;
}
@@ -547,7 +766,7 @@ aw_mtl_purge(struct aw_mtl* mtl)
}
res_T
-aw_mtl_materials_count_get(struct aw_mtl* mtl, size_t* nmtls)
+aw_mtl_get_materials_count(struct aw_mtl* mtl, size_t* nmtls)
{
if(!mtl || !nmtls)
return RES_BAD_ARG;
@@ -556,122 +775,30 @@ aw_mtl_materials_count_get(struct aw_mtl* mtl, size_t* nmtls)
}
res_T
-aw_mtl_material_get
+aw_mtl_get_material
(struct aw_mtl* mtl,
const size_t imaterial,
struct aw_material* material)
{
- const struct aw_material* mtr;
+ const struct material* mat = NULL;
+
if(!mtl || !material || imaterial>=darray_material_size_get(&mtl->materials))
return RES_BAD_ARG;
- mtr = darray_material_cdata_get(&mtl->materials) + imaterial;
- return aw_material_copy(material, mtr);
-}
-
-res_T
-aw_map_init(struct mem_allocator* allocator, struct aw_map* map)
-{
- if(!map) return RES_BAD_ARG;
- str_init(allocator, &map->filename);
- map->options_mask = 0;
- map->image_bias = 0.f;
- map->image_scale = 1.f;
- f3_splat(map->texcoord_bias, 0.f);
- f3_splat(map->texcoord_scale, 1.f);
- f3_splat(map->texcoord_turbulence, 0.f);
- map->resolution = 0;
- map->scalar = AW_MAP_CHANNEL_LUMINANCE;
- map->bump_multiplier = 1.0f;
- return RES_OK;
-}
-
-res_T
-aw_map_release(struct aw_map* map)
-{
- if(!map) return RES_BAD_ARG;
- str_release(&map->filename);
- return RES_OK;
-}
-res_T
-aw_map_copy(struct aw_map* dst, const struct aw_map* src)
-{
- if(!dst || !src) return RES_BAD_ARG;
- if(dst == src) return RES_OK;
- map_copy_pod__(dst, src);
- return str_copy(&dst->filename, &src->filename);
-}
-
-res_T
-aw_map_copy_and_release(struct aw_map* dst, struct aw_map* src)
-{
- if(!dst || !src) return RES_BAD_ARG;
- if(dst == src) return RES_OK;
- map_copy_pod__(dst, src);
- return str_copy_and_release(&dst->filename, &src->filename);
-}
-
-res_T
-aw_material_init(struct mem_allocator* allocator, struct aw_material* mtl)
-{
- if(!mtl) return RES_BAD_ARG;
- memset(mtl, 0, sizeof(struct aw_material));
- str_init(allocator, &mtl->name);
- AW(map_init(allocator, &mtl->ambient_map));
- AW(map_init(allocator, &mtl->diffuse_map));
- AW(map_init(allocator, &mtl->specular_map));
- AW(map_init(allocator, &mtl->specular_exponent_map));
- AW(map_init(allocator, &mtl->bump_map));
- return RES_OK;
-}
-
-res_T
-aw_material_release(struct aw_material* mtl)
-{
- if(!mtl) return RES_BAD_ARG;
- str_release(&mtl->name);
- AW(map_release(&mtl->ambient_map));
- AW(map_release(&mtl->diffuse_map));
- AW(map_release(&mtl->specular_map));
- AW(map_release(&mtl->specular_exponent_map));
- AW(map_release(&mtl->bump_map));
- return RES_OK;
-}
-
-res_T
-aw_material_copy(struct aw_material* dst, const struct aw_material* src)
-{
- res_T res;
- if(!dst || !src) return RES_BAD_ARG;
- if(dst == src) return RES_OK;
- material_copy_pod__(dst, src);
- #define CALL(Func) if(RES_OK != (res = Func)) return res
- CALL(str_copy(&dst->name, &src->name));
- CALL(aw_map_copy(&dst->ambient_map, &src->ambient_map));
- CALL(aw_map_copy(&dst->diffuse_map, &src->diffuse_map));
- CALL(aw_map_copy(&dst->specular_map, &src->specular_map));
- CALL(aw_map_copy(&dst->specular_exponent_map, &src->specular_exponent_map));
- CALL(aw_map_copy(&dst->bump_map, &src->bump_map));
- #undef CALL
- return RES_OK;
-}
-
-res_T
-aw_material_copy_and_release(struct aw_material* dst, struct aw_material* src)
-{
- res_T res;
- if(!dst || !src) return RES_BAD_ARG;
- if(dst == src) return RES_OK;
- material_copy_pod__(dst, src);
- #define CALL(Func) if(RES_OK != (res = Func)) return res
- CALL(str_copy_and_release(&dst->name, &src->name));
- CALL(aw_map_copy_and_release(&dst->ambient_map, &src->ambient_map));
- CALL(aw_map_copy_and_release(&dst->diffuse_map, &src->diffuse_map));
- CALL(aw_map_copy_and_release(&dst->specular_map, &src->specular_map));
- CALL(aw_map_copy_and_release
- (&dst->specular_exponent_map, &src->specular_exponent_map));
- CALL(aw_map_copy_and_release(&dst->bump_map, &src->bump_map));
- #undef CALL
+ mat = darray_material_cdata_get(&mtl->materials) + imaterial;
+ material->name = str_cget(&mat->name);
+ material->ambient = mat->ambient;
+ material->diffuse = mat->diffuse;
+ material->specular = mat->specular;
+ material->transmission = mat->transmission;
+ material->specular_exponent = mat->specular_exponent;
+ material->refraction_index = mat->refraction_index;
+ material->illumination_model = mat->illumination_model;
+ map_to_aw_map(&mat->ambient_map, &material->ambient_map);
+ map_to_aw_map(&mat->diffuse_map, &material->diffuse_map);
+ map_to_aw_map(&mat->specular_map, &material->specular_map);
+ map_to_aw_map(&mat->specular_exponent_map, &material->specular_exponent_map);
+ map_to_aw_map(&mat->bump_map, &material->bump_map);
return RES_OK;
}
diff --git a/src/aw_obj.c b/src/aw_obj.c
@@ -1,8 +1,8 @@
-/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr)
+/* Copyright (C) 2014-2017, 2020 Vincent Forest (vaplv@free.fr)
*
* This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -17,33 +17,29 @@
#include "aw_c.h"
-#include <rsys/clock_time.h>
-#include <rsys/dynamic_array_char.h>
-#include <rsys/dynamic_array_float.h>
-#include <rsys/float3.h>
-#include <rsys/float4.h>
+#include <rsys/cstr.h>
+#include <rsys/dynamic_array_double.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
#include <rsys/ref_count.h>
#include <rsys/str.h>
+#include <rsys/text_reader.h>
-#include <float.h>
+#include <float.h> /* DBL_MAX & DBL_MIN definition */
+#include <stdarg.h>
#ifdef COMPILER_CL
#pragma warning(push)
#pragma warning(disable:4706) /* Assignment within a condition */
#endif
-struct vertex {
- size_t iposition;
- size_t inormal;
- size_t itexcoord;
-};
-static const struct vertex VERTEX_NULL = { AW_ID_NONE, AW_ID_NONE, AW_ID_NONE };
+static const char* MSG_PREFIX_INFO = "load-obj:info: ";
+static const char* MSG_PREFIX_ERROR = "load-obj:error: ";
+static const char* MSG_PREFIX_WARNING = "load-obj:warning: ";
/* Generate the darray_vertex data structure */
#define DARRAY_NAME vertex
-#define DARRAY_DATA struct vertex
+#define DARRAY_DATA struct aw_obj_vertex
#include <rsys/dynamic_array.h>
/* Generate the darray_face data structure */
@@ -51,13 +47,56 @@ static const struct vertex VERTEX_NULL = { AW_ID_NONE, AW_ID_NONE, AW_ID_NONE };
#define DARRAY_DATA struct aw_obj_face
#include <rsys/dynamic_array.h>
+static const struct aw_obj_vertex VERTEX_NULL = {
+ AW_ID_NONE, AW_ID_NONE, AW_ID_NONE
+};
+
+struct named_group {
+ struct str name;
+ size_t face_id; /* Index of the first group face */
+ size_t faces_count;
+};
+
+static INLINE void
+named_group_init(struct mem_allocator* allocator, struct named_group* grp)
+{
+ str_init(allocator, &grp->name);
+}
+
+static INLINE void
+named_group_release(struct named_group* grp)
+{
+ ASSERT(grp);
+ str_release(&grp->name);
+}
+
+static INLINE res_T
+named_group_copy(struct named_group* dst, const struct named_group* src)
+{
+ ASSERT(dst && src);
+ if(dst == src) return RES_OK;
+ dst->face_id = src->face_id;
+ dst->faces_count = src->faces_count;
+ return str_copy(&dst->name, &src->name);
+}
+
+static INLINE res_T
+named_group_copy_and_release(struct named_group* dst, struct named_group* src)
+{
+ ASSERT(dst && src);
+ if(dst == src) return RES_OK;
+ dst->face_id = src->face_id;
+ dst->faces_count = src->faces_count;
+ return str_copy_and_release(&dst->name, &src->name);
+}
+
/* Generate the darray_named_group data structure */
#define DARRAY_NAME named_group
-#define DARRAY_DATA struct aw_obj_named_group
-#define DARRAY_FUNCTOR_INIT aw_obj_named_group_init
-#define DARRAY_FUNCTOR_RELEASE aw_obj_named_group_release
-#define DARRAY_FUNCTOR_COPY aw_obj_named_group_copy
-#define DARRAY_FUNCTOR_COPY_AND_RELEASE aw_obj_named_group_copy_and_release
+#define DARRAY_DATA struct named_group
+#define DARRAY_FUNCTOR_INIT named_group_init
+#define DARRAY_FUNCTOR_RELEASE named_group_release
+#define DARRAY_FUNCTOR_COPY named_group_copy
+#define DARRAY_FUNCTOR_COPY_AND_RELEASE named_group_copy_and_release
#include <rsys/dynamic_array.h>
/* Generate the darray_smooth_group data structure */
@@ -75,9 +114,9 @@ static const struct vertex VERTEX_NULL = { AW_ID_NONE, AW_ID_NONE, AW_ID_NONE };
#include <rsys/dynamic_array.h>
struct aw_obj {
- struct darray_float positions; /* float4 */
- struct darray_float normals; /* float3 */
- struct darray_float texcoords; /* float3 */
+ struct darray_double positions; /* double4 */
+ struct darray_double normals; /* double3 */
+ struct darray_double texcoords; /* double3 */
struct darray_vertex vertices;
struct darray_face faces;
struct darray_named_group groups;
@@ -87,90 +126,141 @@ struct aw_obj {
size_t igroups_active; /* Index toward the first active group */
- const char* filename; /* Currently parsed file. Use in messages */
- size_t iline; /* Currently parsed line index. Use in messages */
-
ref_T ref;
struct mem_allocator* allocator;
struct logger* logger;
+ struct logger logger__; /* Default logger */
int verbose;
};
/*******************************************************************************
* Helper functions
******************************************************************************/
-static FINLINE void
+static INLINE void
+log_msg
+ (const struct aw_obj* obj,
+ const enum log_type stream,
+ const char* msg,
+ va_list vargs)
+{
+ ASSERT(obj && msg);
+ if(obj->verbose) {
+ res_T res; (void)res;
+ res = logger_vprint(obj->logger, stream, msg, vargs);
+ ASSERT(res == RES_OK);
+ }
+}
+
+static INLINE void
+log_err(const struct aw_obj* obj, const char* msg, ...)
+{
+ va_list vargs_list;
+ ASSERT(obj && msg);
+
+ va_start(vargs_list, msg);
+ log_msg(obj, LOG_ERROR, msg, vargs_list);
+ va_end(vargs_list);
+}
+
+static INLINE void
+log_warn(const struct aw_obj* obj, const char* msg, ...)
+{
+ va_list vargs_list;
+ ASSERT(obj && msg);
+
+ va_start(vargs_list, msg);
+ log_msg(obj, LOG_WARNING, msg, vargs_list);
+ va_end(vargs_list);
+}
+
+static INLINE void
flush_groups(struct aw_obj* obj)
{
size_t nfaces, ngrps;
ASSERT(obj);
- if(0 == (nfaces = darray_face_size_get(&obj->faces)))
- return;
- if(0 == (ngrps = darray_named_group_size_get(&obj->groups)))
- return;
- if(obj->igroups_active >= ngrps)
- return;
+
+ nfaces = darray_face_size_get(&obj->faces);
+ if(!nfaces) return; /* No face to flush */
+
+ ngrps = darray_named_group_size_get(&obj->groups);
+ if(!ngrps) return; /* No group */
+
+ /* There should be an active group to flush if ngrps is not null */
+ ASSERT(obj->igroups_active < ngrps);
+
+ /* Setup the number of faces of each active group */
FOR_EACH(obj->igroups_active, obj->igroups_active, ngrps) {
- struct aw_obj_named_group* grp;
+ struct named_group* grp;
grp = darray_named_group_data_get(&obj->groups) + obj->igroups_active;
ASSERT(grp->face_id <= nfaces);
grp->faces_count = nfaces - grp->face_id;
}
}
-static FINLINE void
+static INLINE void
flush_usemtl(struct aw_obj* obj)
{
- struct aw_obj_named_group* mtl;
+ struct named_group* mtl;
size_t nfaces, ngrps;
ASSERT(obj);
- if(0 == (nfaces = darray_face_size_get(&obj->faces)))
- return;
- if(0 == (ngrps = darray_named_group_size_get(&obj->usemtls)))
- return;
+
+ nfaces = darray_face_size_get(&obj->faces);
+ if(!nfaces) return; /* No face to flush */
+
+ ngrps = darray_named_group_size_get(&obj->usemtls);
+ if(!ngrps) return; /* No group */
+
+ /* Setup the number of faces of the current mtl */
mtl = darray_named_group_data_get(&obj->usemtls) + (ngrps - 1);
ASSERT(mtl->face_id <= nfaces);
mtl->faces_count = nfaces - mtl->face_id;
}
-static FINLINE void
+static INLINE void
flush_smooth_group(struct aw_obj* obj)
{
struct aw_obj_smooth_group* grp;
size_t nfaces, ngrps;
ASSERT(obj);
- if(0 == (nfaces = darray_face_size_get(&obj->faces)))
- return;
- if(0 == (ngrps = darray_smooth_group_size_get(&obj->smooth_groups)))
- return;
+
+ nfaces = darray_face_size_get(&obj->faces);
+ if(!nfaces) return; /* No face to flush */
+
+ ngrps = darray_smooth_group_size_get(&obj->smooth_groups);
+ if(!ngrps) return; /* No smooth group */
+
+ /* Setup the number of faces of the current smoothed group */
grp = darray_smooth_group_data_get(&obj->smooth_groups) + (ngrps - 1);
ASSERT(grp->face_id <= nfaces);
grp->faces_count = nfaces - grp->face_id;
}
static res_T
-parse_floatX_in_darray
- (struct darray_float* darray,
+parse_doubleX_in_darray
+ (struct darray_double* darray,
const unsigned int count_min,
const unsigned int count_max,
- const float default_value,
- char** tk_ctxt)
+ const double default_value,
+ char** tk_ctx)
{
- res_T res;
+ res_T res = RES_OK;
size_t i;
ASSERT(darray);
- i = darray_float_size_get(darray);
- res = darray_float_resize(darray, i + count_max);
- if(res != RES_OK)
- return res;
+ i = darray_double_size_get(darray);
+
+ res = darray_double_resize(darray, i + count_max);
+ if(res != RES_OK) goto error;
- res = parse_floatX
- (darray_float_data_get(darray) + i,
- count_min, count_max, -FLT_MAX, FLT_MAX, default_value, tk_ctxt);
- if(res != RES_OK)
- darray_float_resize(darray, i);
+ res = parse_doubleX(darray_double_data_get(darray) + i, count_min, count_max,
+ -DBL_MAX, DBL_MAX, default_value, tk_ctx);
+ if(res != RES_OK) goto error;
+
+exit:
return res;
+error:
+ darray_double_resize(darray, i);
+ goto exit;
}
static res_T
@@ -182,7 +272,7 @@ string_to_vertex_id
long id_long;
res_T res;
- res = string_to_long(str, &id_long);
+ res = cstr_to_long(str, &id_long);
if(res != RES_OK) return res;
if(id_long > 0) {
@@ -201,252 +291,349 @@ string_to_vertex_id
}
static res_T
-parse_face(struct aw_obj* obj, char** word_tk)
+parse_face_vertex
+ (struct aw_obj* obj,
+ struct aw_obj_face* face,
+ char* str)
{
- struct aw_obj_face face;
- char* word;
+ struct aw_obj_vertex vert = VERTEX_NULL;
+ char* tk1 = NULL;
+ char* tk2 = NULL;
+ char* tk3 = NULL;
+ char* tk_ctx = NULL;
+ size_t npositions = 0;
+ size_t nnormals = 0;
+ size_t ntexcoords = 0;
res_T res = RES_OK;
- ASSERT(obj && word_tk);
+ ASSERT(obj && face && str);
+
+ npositions = darray_double_size_get(&obj->positions) / 4;
+ nnormals = darray_double_size_get(&obj->normals) / 3;
+ ntexcoords = darray_double_size_get(&obj->texcoords) / 3;
+
#define CALL(Func) if(RES_OK != (res = Func)) goto error
+ /* Parse the position */
+ tk1 = strtok_r(str, "/", &tk_ctx);
+ ASSERT(tk1);
+ CALL(string_to_vertex_id(tk1, npositions, &vert.position_id));
+
+ tk2 = strtok_r(NULL, "/", &tk_ctx);
+ if(tk2) {
+ tk1 += strlen(tk1);
+ if(tk2 > tk1 + 3) { /* Unexpected N `/' separators with N > 2 */
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(tk2 == tk1 + 2) { /* `//' separator => No tex */
+ /* Parse the normal */
+ CALL(string_to_vertex_id(tk2, nnormals, &vert.normal_id));
+ } else {
+ /* Parse the texcoords and */
+ CALL(string_to_vertex_id(tk2, ntexcoords, &vert.texcoord_id));
+
+ tk3 = strtok_r(NULL, "", &tk_ctx);
+ if(tk3) {
+ /* Parse the normal */
+ CALL(string_to_vertex_id(tk3, nnormals, &vert.normal_id));
+ }
+ }
+ }
+
+ /* Register the vertex */
+ CALL(darray_vertex_push_back(&obj->vertices, &vert));
+ ++face->vertices_count;
+
+ #undef CALL
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_face(struct aw_obj* obj, char** tk_ctx)
+{
+ struct aw_obj_face face;
+ char* tk = NULL;
+ res_T res = RES_OK;
+ ASSERT(obj && tk_ctx);
+
face.vertex_id = darray_vertex_size_get(&obj->vertices);
face.vertices_count = 0;
face.group_id = darray_named_group_size_get(&obj->groups) - 1;
face.smooth_group_id = darray_smooth_group_size_get(&obj->smooth_groups) - 1;
face.mtl_id = darray_named_group_size_get(&obj->usemtls) - 1;
- while((word = strtok_r(NULL, " \t", word_tk))) {
- char* id, *id_tk, *id_pos;
- struct vertex vert = VERTEX_NULL;
- const size_t positions_count = darray_float_size_get(&obj->positions) / 4;
- const size_t normals_count = darray_float_size_get(&obj->normals) / 3;
- const size_t texcoords_count = darray_float_size_get(&obj->texcoords) / 3;
-
- /* position index */
- id_pos = strtok_r(word, "/", &id_tk);
- CALL(string_to_vertex_id(id_pos, positions_count, &vert.iposition));
- if((id = strtok_r(NULL, "/", &id_tk))) {
- id_pos += strlen(id_pos);
- if(id > id_pos + 3) /* Unexpected N `/' separators with N > 2 */
- goto error;
- if(id == id_pos + 2) { /* `//' separator => No tex */
- /* normal index */
- CALL(string_to_vertex_id(id, normals_count, &vert.inormal));
- } else {
- /* texcoord index */
- CALL(string_to_vertex_id(id, texcoords_count, &vert.itexcoord));
- /* normal index */
- if((id = strtok_r(NULL, "/", &id_tk))) {
- CALL(string_to_vertex_id(id, normals_count, &vert.inormal));
- }
- }
- }
- CALL(darray_vertex_push_back(&obj->vertices, &vert));
- ++face.vertices_count;
+ while((tk = strtok_r(NULL, " \t", tk_ctx))) {
+ res = parse_face_vertex(obj, &face, tk);
+ if(res != RES_OK) goto error;
}
- CALL(darray_face_push_back(&obj->faces, &face));
- #undef CALL
+ /* Register the face */
+ res = darray_face_push_back(&obj->faces, &face);
+ if(res != RES_OK) goto error;
+
exit:
return res;
error:
- FOR_EACH_REVERSE(face.vertices_count, face.vertices_count, 0)
- darray_vertex_pop_back(&obj->vertices);
+ /* Release the registered faces */
+ CHK(darray_vertex_resize(&obj->vertices, face.vertex_id) == RES_OK);
goto exit;
}
static res_T
-parse_group(struct aw_obj* obj, char** word_tk)
+parse_group(struct aw_obj* obj, char** tk_ctx)
{
- char* word;
- size_t ngrps = 0, igrp = 0;
+ char* tk;
+ size_t ngrps = 0;
+ size_t igrp = 0;
res_T res = RES_OK;
- ASSERT(obj && word_tk);
+ ASSERT(obj && tk_ctx);
flush_groups(obj);
- word = strtok_r(NULL, " \t", word_tk);
ngrps = igrp = darray_named_group_size_get(&obj->groups);
- obj->igroups_active = ngrps;
+ obj->igroups_active = igrp;
+
+ tk = strtok_r(NULL, " \t", tk_ctx); /* May be NULL */
+
do {
- struct aw_obj_named_group* grp = NULL;
+ struct named_group* grp = NULL;
+
+ /* Allocate a group */
res = darray_named_group_resize(&obj->groups, igrp + 1);
- if(res != RES_OK)
- goto error;
- grp = darray_named_group_data_get(&obj->groups) + ngrps;
+ if(res != RES_OK) goto error;
+
+ /* Fetch the group */
+ grp = darray_named_group_data_get(&obj->groups) + igrp;
++igrp;
- res = str_set(&grp->name, word ? word : "default");
- if(res != RES_OK)
- goto error;
+
+ /* Setup the group name */
+ res = str_set(&grp->name, tk ? tk : "default");
+ if(res != RES_OK) goto error;
+
+ /* Initialize the group face indices */
grp->face_id = darray_face_size_get(&obj->faces);
grp->faces_count = 0;
- } while((word = strtok_r(NULL, " \t", word_tk)));
+ } while((tk = strtok_r(NULL, " \t", tk_ctx)));
exit:
return res;
error:
- if(igrp != ngrps)
- CHK(darray_named_group_resize(&obj->groups, ngrps) == RES_OK);
+ /* Release the created groups */
+ CHK(darray_named_group_resize(&obj->groups, ngrps) == RES_OK);
goto exit;
}
static res_T
-parse_smooth_group(struct aw_obj* obj, char** word_tk)
+parse_smooth_group(struct aw_obj* obj, char** tk_ctx)
{
- char* word;
struct aw_obj_smooth_group grp;
+ char* tk = NULL;
res_T res;
- size_t i;
- ASSERT(obj && word_tk);
+ ASSERT(obj && tk_ctx);
flush_smooth_group(obj);
- word = strtok_r(NULL, " \t", word_tk);
- if(!strcmp(word, "off")) {
+ tk = strtok_r(NULL, " \t", tk_ctx);
+ if(!tk) return RES_BAD_ARG;
+
+ if(!strcmp(tk, "off")) {
grp.is_smoothed = 0;
- } else if(!strcmp(word, "on")) {
+ } else if(!strcmp(tk, "on")) {
grp.is_smoothed = 1;
} else {
- res = string_to_size_t(word, &i);
- if(res != RES_OK)
- return res;
+ int i;
+ res = cstr_to_int(tk, &i);
+ if(res != RES_OK) return res;
grp.is_smoothed = i != 0;
}
+
+ /* Initialize the smoot group face indices */
grp.face_id = darray_face_size_get(&obj->faces);
grp.faces_count = 0;
+ /* Register the smooth group */
res = darray_smooth_group_push_back(&obj->smooth_groups, &grp);
- if(res != RES_OK)
- return res;
+ if(res != RES_OK) return res;
return RES_OK;
}
static res_T
-parse_mtllib(struct aw_obj* obj, char** word_tk)
+parse_mtllib(struct aw_obj* obj, char** tk_ctx)
{
- char* word;
+ char* tk = NULL;
size_t imtllib = 0;
size_t nmtllibs = 0;
res_T res = RES_OK;
- ASSERT(obj && word_tk);
+ ASSERT(obj && tk_ctx);
- word = strtok_r(NULL, " \t", word_tk);
- if(!word) {
+ nmtllibs = imtllib = darray_mtllib_size_get(&obj->mtllibs);
+
+ tk = strtok_r(NULL, " \t", tk_ctx);
+ if(!tk) {
res = RES_BAD_ARG;
goto error;
}
- nmtllibs = imtllib = darray_mtllib_size_get(&obj->mtllibs);
+
do {
- struct str* str;
+ struct str* str = NULL;
+
+ /* Allocate the mtllib path */
res = darray_mtllib_resize(&obj->mtllibs, imtllib + 1);
- if(res != RES_OK)
- goto error;
+ if(res != RES_OK) goto error;
+
+ /* Fetc the mtllib path */
str = darray_mtllib_data_get(&obj->mtllibs) + imtllib;
++imtllib;
- res = str_set(str, word);
- if(res != RES_OK)
- goto error;
- } while((word = strtok_r(NULL, " \t", word_tk)));
+
+ /* Setup the mtllib name */
+ res = str_set(str, tk);
+ if(res != RES_OK) goto error;
+
+ } while((tk = strtok_r(NULL, " \t", tk_ctx)));
exit:
return res;
error:
- if(imtllib != nmtllibs)
- CHK(darray_mtllib_resize(&obj->mtllibs, nmtllibs) == RES_OK);
+ CHK(darray_mtllib_resize(&obj->mtllibs, nmtllibs) == RES_OK);
goto exit;
}
static res_T
-parse_usemtl(struct aw_obj* obj, char** word_tk)
+parse_usemtl(struct aw_obj* obj, char** tk_ctx)
{
- char* word;
- struct aw_obj_named_group* mtl = NULL;
+ char* tk = NULL;
+ struct named_group* mtl = NULL;
size_t nmtls;
res_T res = RES_OK;
- ASSERT(obj && word_tk);
+ ASSERT(obj && tk_ctx);
flush_usemtl(obj);
- word= strtok_r(NULL, " \t", word_tk);
- if(!word_tk) {
+ tk = strtok_r(NULL, " \t", tk_ctx); /* Blanks are prohibited in mtl name */
+ if(!tk) {
res = RES_BAD_ARG;
goto error;
}
nmtls = darray_named_group_size_get(&obj->usemtls);
+
+ /* Allocate the material */
res = darray_named_group_resize(&obj->usemtls, nmtls + 1);
- if(res != RES_OK)
- goto error;
+ if(res != RES_OK) goto error;
+
+ /* Fetch the material */
mtl = darray_named_group_data_get(&obj->usemtls) + nmtls;
- res = str_set(&mtl->name, word);
- if(res != RES_OK)
- goto error;
+
+ /* Setup the material name */
+ res = str_set(&mtl->name, tk);
+ if(res != RES_OK) goto error;
+
+ /* Initialize the material face indices */
mtl->face_id = darray_face_size_get(&obj->faces);
mtl->faces_count = 0;
exit:
return res;
error:
- if(mtl)
- darray_named_group_pop_back(&obj->usemtls);
+ if(mtl) darray_named_group_pop_back(&obj->usemtls);
goto exit;
}
static res_T
-parse_obj_line(struct aw_obj* obj, char* line)
+parse_obj_line(struct aw_obj* obj, struct txtrdr* txtrdr)
{
- char* word, *word_tk;
+ char* tk = NULL;
+ char* tk_ctx = NULL;
res_T res = RES_OK;
- ASSERT(obj && line);
-
- word = strtok_r(line, " \t", &word_tk);
- if(word) {
- if(word[0] == '#') { /* Comment */
- goto exit;
- } else if(!strcmp(word, "v")) { /* Vertex position */
- res = parse_floatX_in_darray(&obj->positions, 3, 4, 1.f, &word_tk);
- } else if(!strcmp(word, "vn")) { /* Vertex normal */
- res = parse_floatX_in_darray(&obj->normals, 3, 3, 0.f, &word_tk);
- } else if(!strcmp(word, "vt")) { /* Vertex texture coordinates */
- res = parse_floatX_in_darray(&obj->texcoords, 1, 3, 0.f, &word_tk);
- } else if(!strcmp(word, "f") || !strcmp(word, "fo")) { /* face element */
- res = parse_face(obj, &word_tk);
- } else if(!strcmp(word, "g")) { /* Grouping */
- res = parse_group(obj, &word_tk);
- } else if(!strcmp(word, "s")) { /* Smooth group */
- res = parse_smooth_group(obj, &word_tk);
- } else if(!strcmp(word, "mtllib")) { /* Mtl library */
- res = parse_mtllib(obj, &word_tk);
- } else if(!strcmp(word, "usemtl")) { /* Use the mtl library */
- res = parse_usemtl(obj, &word_tk);
- } else {
- res = RES_OK;
- if(obj->verbose) {
- logger_print(obj->logger, LOG_WARNING,
- "%s:%lu: warning: ignored or malformed directive %s\n",
- obj->filename, (unsigned long)obj->iline, word);
- }
- while((word = strtok_r(NULL, " \t", &word_tk))); /* Skip the line */
- }
- if(res != RES_OK)
- goto error;
- if((word = strtok_r(NULL, " ", &word_tk))) {
- if(obj->verbose) {
- logger_print(obj->logger, LOG_ERROR, "%s:%lu: unexpected directive %s\n",
- obj->filename, (unsigned long)obj->iline, word);
- }
- res = RES_BAD_ARG;
+ ASSERT(obj && txtrdr);
+
+ tk = strtok_r(txtrdr_get_line(txtrdr), " \t", &tk_ctx);
+ ASSERT(tk); /* A line should exist since it was parsed by txtrdr */
+
+ if(!strcmp(tk, "v")) { /* Vertex position */
+ res = parse_doubleX_in_darray(&obj->positions, 3, 4, 1.f, &tk_ctx);
+ } else if(!strcmp(tk, "vn")) { /* Vertex normal */
+ res = parse_doubleX_in_darray(&obj->normals, 3, 3, 0.f, &tk_ctx);
+ } else if(!strcmp(tk, "vt")) { /* Vertex texture coordinates */
+ res = parse_doubleX_in_darray(&obj->texcoords, 1, 3, 0.f, &tk_ctx);
+ } else if(!strcmp(tk, "f") || !strcmp(tk, "fo")) { /* face element */
+ res = parse_face(obj, &tk_ctx);
+ } else if(!strcmp(tk, "g")) { /* Grouping */
+ res = parse_group(obj, &tk_ctx);
+ } else if(!strcmp(tk, "s")) { /* Smooth group */
+ res = parse_smooth_group(obj, &tk_ctx);
+ } else if(!strcmp(tk, "mtllib")) { /* Mtl library */
+ res = parse_mtllib(obj, &tk_ctx);
+ } else if(!strcmp(tk, "usemtl")) { /* Use the mtl library */
+ res = parse_usemtl(obj, &tk_ctx);
+ } else {
+ log_warn(obj,
+ "%s:%lu: warning: ignored or malformed directive `%s'.\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk);
+ strtok_r(NULL, "", &tk_ctx); /* Discard remaining text */
+ }
+ if(res != RES_OK) {
+ log_err(obj, "%s:%lu: parsing failed.\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr));
+ goto error;
+ }
+
+ tk = strtok_r(NULL, "", &tk_ctx);
+ if(tk) {
+ log_err(obj, "%s:%lu: unexpected text `%s'.\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr), tk);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+load_stream(struct aw_obj* obj, FILE* stream, const char* stream_name)
+{
+ struct txtrdr* txtrdr = NULL;
+ res_T res = RES_OK;
+ ASSERT(obj && stream && stream_name);
+
+ AW(obj_clear(obj));
+
+ res = txtrdr_stream(obj->allocator, stream, stream_name, '#', &txtrdr);
+ if(res != RES_OK) {
+ log_err(obj, "Could not create the text reader.\n");
+ goto error;
+ }
+
+ for(;;) {
+ res = txtrdr_read_line(txtrdr);
+ if(res != RES_OK) {
+ log_err(obj, "%s: could not read the line `%lu'.\n",
+ txtrdr_get_name(txtrdr), (unsigned long)txtrdr_get_line_num(txtrdr));
goto error;
}
+
+ if(!txtrdr_get_cline(txtrdr)) break; /* No more parsed line */
+
+ res = parse_obj_line(obj, txtrdr);
+ if(res != RES_OK) goto error;
}
+
+ flush_groups(obj);
+ flush_smooth_group(obj);
+ flush_usemtl(obj);
exit:
+ if(txtrdr) txtrdr_ref_put(txtrdr);
return res;
error:
- if(obj->verbose) {
- logger_print(obj->logger, LOG_ERROR, "%s:%lu: error: parsing failed\n",
- obj->filename, (unsigned long)obj->iline);
- }
+ AW(obj_clear(obj));
goto exit;
}
@@ -455,15 +642,16 @@ obj_release(ref_T* ref)
{
struct aw_obj* obj = CONTAINER_OF(ref, struct aw_obj, ref);
ASSERT(ref);
- darray_float_release(&obj->positions);
- darray_float_release(&obj->normals);
- darray_float_release(&obj->texcoords);
+ darray_double_release(&obj->positions);
+ darray_double_release(&obj->normals);
+ darray_double_release(&obj->texcoords);
darray_vertex_release(&obj->vertices);
darray_face_release(&obj->faces);
darray_named_group_release(&obj->groups);
darray_named_group_release(&obj->usemtls);
darray_smooth_group_release(&obj->smooth_groups);
darray_mtllib_release(&obj->mtllibs);
+ if(obj->logger == &obj->logger__) logger_release(&obj->logger__);
MEM_RM(obj->allocator, obj);
}
@@ -493,11 +681,10 @@ aw_obj_create
}
ref_init(&obj->ref);
obj->allocator = allocator;
- obj->logger = logger ? logger : LOGGER_DEFAULT;
obj->verbose = verbose;
- darray_float_init(mem_allocator, &obj->positions);
- darray_float_init(mem_allocator, &obj->normals);
- darray_float_init(mem_allocator, &obj->texcoords);
+ darray_double_init(mem_allocator, &obj->positions);
+ darray_double_init(mem_allocator, &obj->normals);
+ darray_double_init(mem_allocator, &obj->texcoords);
darray_vertex_init(mem_allocator, &obj->vertices);
darray_face_init(mem_allocator, &obj->faces);
darray_named_group_init(mem_allocator, &obj->groups);
@@ -505,6 +692,15 @@ aw_obj_create
darray_smooth_group_init(mem_allocator, &obj->smooth_groups);
darray_mtllib_init(mem_allocator, &obj->mtllibs);
+ if(logger) {
+ obj->logger = logger;
+ } else {
+ res = setup_default_logger(obj->allocator, &obj->logger__,
+ MSG_PREFIX_INFO, MSG_PREFIX_ERROR, MSG_PREFIX_WARNING);
+ if(res != RES_OK) goto error;
+ obj->logger = &obj->logger__;
+ }
+
exit:
if(obj_out)
*obj_out = obj;
@@ -536,82 +732,47 @@ aw_obj_ref_put(struct aw_obj* obj)
res_T
aw_obj_load(struct aw_obj* obj, const char* filename)
{
- FILE* file;
+ FILE* fp = NULL;
res_T res = RES_OK;
- if(!obj || !filename)
- return RES_BAD_ARG;
+ if(!obj || !filename) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
- obj->filename = filename;
- file = fopen(filename, "r");
- if(!file) {
- if(obj->verbose)
- logger_print(obj->logger, LOG_ERROR, "Error opening `%s'\n", filename);
- return RES_IO_ERR;
+ fp = fopen(filename, "r");
+ if(!fp) {
+ log_err(obj, "Error opening `%s'.\n", filename);
+ res = RES_IO_ERR;
+ goto error;
}
- res = aw_obj_load_stream(obj, file);
- obj->filename = NULL;
- fclose(file);
+
+ res = load_stream(obj, fp, filename);
+ if(res != RES_OK) goto error;
+
+exit:
+ if(fp) fclose(fp);
return res;
+error:
+ goto exit;
}
res_T
-aw_obj_load_stream(struct aw_obj* obj, FILE* stream)
+aw_obj_load_stream(struct aw_obj* obj, FILE* stream, const char* stream_name)
{
- char* line;
- struct darray_char buf;
- const unsigned buf_chunk = 256;
res_T res = RES_OK;
- /* Avoid zealous "may be used uninitialized" warning of GCC 4.9.2 */
- memset(&buf, 0, sizeof(buf));
-
if(!obj || !stream) {
res = RES_BAD_ARG;
goto error;
}
- darray_char_init(obj->allocator, &buf);
- res = darray_char_resize(&buf, buf_chunk);
- if(res != RES_OK)
- goto error;
+ res = load_stream(obj, stream, stream_name ? stream_name : "stream");
+ if(res != RES_OK) goto error;
- if(!obj->filename)
- obj->filename = "stream";
- obj->iline = 1;
- AW(obj_clear(obj));
- while((line = fgets
- (darray_char_data_get(&buf), (int)darray_char_size_get(&buf), stream))) {
- size_t last_char;
-
- while(!strrchr(line,'\n')) { /* Ensure that the whole line was read */
- res = darray_char_resize(&buf, darray_char_size_get(&buf) + buf_chunk);
- if(res != RES_OK)
- goto error;
-
- line = darray_char_data_get(&buf);
- if(!fgets(line + strlen(line), (int)buf_chunk, stream)) /* EOF */
- break;
- }
-
- /* Remove the newline character(s) */
- last_char = strlen(line);
- while(last_char-- && (line[last_char]=='\n' || line[last_char]=='\r'));
- line[last_char + 1] = '\0';
-
- if(RES_OK != (res = parse_obj_line(obj, line)))
- goto error;
- ++obj->iline;
- }
- flush_groups(obj);
- flush_smooth_group(obj);
- flush_usemtl(obj);
exit:
- if(obj && stream)
- darray_char_release(&buf);
return res;
error:
- if(obj) AW(obj_clear(obj));
goto exit;
}
@@ -619,9 +780,9 @@ res_T
aw_obj_clear(struct aw_obj* obj)
{
if(!obj) return RES_BAD_ARG;
- darray_float_clear(&obj->positions);
- darray_float_clear(&obj->normals);
- darray_float_clear(&obj->texcoords);
+ darray_double_clear(&obj->positions);
+ darray_double_clear(&obj->normals);
+ darray_double_clear(&obj->texcoords);
darray_vertex_clear(&obj->vertices);
darray_face_clear(&obj->faces);
darray_named_group_clear(&obj->groups);
@@ -636,9 +797,9 @@ res_T
aw_obj_purge(struct aw_obj* obj)
{
if(!obj) return RES_BAD_ARG;
- darray_float_purge(&obj->positions);
- darray_float_purge(&obj->normals);
- darray_float_purge(&obj->texcoords);
+ darray_double_purge(&obj->positions);
+ darray_double_purge(&obj->normals);
+ darray_double_purge(&obj->texcoords);
darray_vertex_purge(&obj->vertices);
darray_face_purge(&obj->faces);
darray_named_group_purge(&obj->groups);
@@ -650,7 +811,7 @@ aw_obj_purge(struct aw_obj* obj)
}
res_T
-aw_obj_desc_get(struct aw_obj* obj, struct aw_obj_desc* desc)
+aw_obj_get_desc(const struct aw_obj* obj, struct aw_obj_desc* desc)
{
if(!obj || !desc)
return RES_BAD_ARG;
@@ -663,8 +824,10 @@ aw_obj_desc_get(struct aw_obj* obj, struct aw_obj_desc* desc)
}
res_T
-aw_obj_face_get
- (const struct aw_obj* obj, const size_t iface, struct aw_obj_face* face)
+aw_obj_get_face
+ (const struct aw_obj* obj,
+ const size_t iface,
+ struct aw_obj_face* face)
{
if(!obj || !face || iface >= darray_face_size_get(&obj->faces))
return RES_BAD_ARG;
@@ -673,20 +836,23 @@ aw_obj_face_get
}
res_T
-aw_obj_group_get
+aw_obj_get_group
(const struct aw_obj* obj,
const size_t igroup,
struct aw_obj_named_group* grp)
{
- const struct aw_obj_named_group* src;
+ const struct named_group* src = NULL;
if(!obj || !grp || igroup >= darray_named_group_size_get(&obj->groups))
return RES_BAD_ARG;
src = darray_named_group_cdata_get(&obj->groups) + igroup;
- return aw_obj_named_group_copy(grp, src);
+ grp->name = str_cget(&src->name);
+ grp->face_id = src->face_id;
+ grp->faces_count = src->faces_count;
+ return RES_OK;
}
res_T
-aw_obj_smooth_group_get
+aw_obj_get_smooth_group
(const struct aw_obj* obj,
const size_t ismooth_group,
struct aw_obj_smooth_group* group)
@@ -699,21 +865,26 @@ aw_obj_smooth_group_get
}
res_T
-aw_obj_mtl_get
+aw_obj_get_mtl
(const struct aw_obj* obj,
const size_t imtl,
struct aw_obj_named_group* mtl)
{
- const struct aw_obj_named_group* src;
+ const struct named_group* src;
if(!obj || !mtl || imtl >= darray_named_group_size_get(&obj->usemtls))
return RES_BAD_ARG;
src = darray_named_group_cdata_get(&obj->usemtls) + imtl;
- return aw_obj_named_group_copy(mtl, src);
+ mtl->name = str_cget(&src->name);
+ mtl->face_id = src->face_id;
+ mtl->faces_count = src->faces_count;
+ return RES_OK;
}
res_T
-aw_obj_mtllib_get
- (const struct aw_obj* obj, const size_t imtllib, const char** mtllib)
+aw_obj_get_mtllib
+ (const struct aw_obj* obj,
+ const size_t imtllib,
+ const char** mtllib)
{
const struct str* str;
if(!obj || !mtllib || imtllib >= darray_mtllib_size_get(&obj->mtllibs))
@@ -724,76 +895,82 @@ aw_obj_mtllib_get
}
res_T
-aw_obj_vertex_get
- (const struct aw_obj* obj, const size_t ivertex, struct aw_obj_vertex* vertex)
+aw_obj_get_vertex
+ (const struct aw_obj* obj,
+ const size_t ivertex,
+ struct aw_obj_vertex* vertex)
{
- const struct vertex* vert;
- const float* data;
if(!obj || !vertex || ivertex >= darray_vertex_size_get(&obj->vertices))
return RES_BAD_ARG;
- vert = darray_vertex_cdata_get(&obj->vertices) + ivertex;
+ *vertex = darray_vertex_cdata_get(&obj->vertices)[ivertex];
+ return RES_OK;
+}
+
+res_T
+aw_obj_get_vertex_data
+ (const struct aw_obj* obj,
+ const struct aw_obj_vertex* vertex,
+ struct aw_obj_vertex_data* vertex_data)
+{
+ const double* data;
+ res_T res = RES_OK;
+
+ if(!obj || !vertex || !vertex_data) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(vertex->position_id >= darray_double_size_get(&obj->positions) / 4) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(vertex->texcoord_id != VERTEX_NULL.texcoord_id
+ && vertex->texcoord_id >= darray_double_size_get(&obj->texcoords) / 3) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(vertex->normal_id != VERTEX_NULL.normal_id
+ && vertex->normal_id >= darray_double_size_get(&obj->normals) / 3) {
+ res = RES_BAD_ARG;
+ goto error;
+ }
/* Fetch vertex position */
- ASSERT(vert->iposition != VERTEX_NULL.iposition);
- data = darray_float_cdata_get(&obj->positions) + vert->iposition * 4;
- f4_set(vertex->position, data);
+ data = darray_double_cdata_get(&obj->positions) + vertex->position_id * 4;
+ vertex_data->position[0] = data[0];
+ vertex_data->position[1] = data[1];
+ vertex_data->position[2] = data[2];
+ vertex_data->position[3] = data[3];
+
/* Setup vertex texcoord */
- if(vert->itexcoord == VERTEX_NULL.itexcoord) {
- f3_splat(vertex->texcoord, 0.f);
+ if(vertex->texcoord_id == VERTEX_NULL.texcoord_id) {
+ vertex_data->texcoord[0] = 0;
+ vertex_data->texcoord[1] = 0;
+ vertex_data->texcoord[2] = 0;
} else {
- data = darray_float_cdata_get(&obj->texcoords) + vert->itexcoord * 3;
- f3_set(vertex->texcoord, data);
+ data = darray_double_cdata_get(&obj->texcoords) + vertex->texcoord_id * 3;
+ vertex_data->texcoord[0] = data[0];
+ vertex_data->texcoord[1] = data[1];
+ vertex_data->texcoord[2] = data[2];
}
/* Setup vertex normal */
- if(vert->inormal == VERTEX_NULL.inormal) {
- f3_splat(vertex->normal, 0.f);
+ if(vertex->normal_id == VERTEX_NULL.normal_id) {
+ vertex_data->normal[0] = 0;
+ vertex_data->normal[1] = 0;
+ vertex_data->normal[2] = 0;
} else {
- data = darray_float_cdata_get(&obj->normals) + vert->inormal * 3;
- f3_set(vertex->normal, data);
+ data = darray_double_cdata_get(&obj->normals) + vertex->normal_id * 3;
+ vertex_data->normal[0] = data[0];
+ vertex_data->normal[1] = data[1];
+ vertex_data->normal[2] = data[2];
}
- return RES_OK;
-}
-
-res_T
-aw_obj_named_group_init
- (struct mem_allocator* allocator, struct aw_obj_named_group* grp)
-{
- if(!grp) return RES_BAD_ARG;
- str_init(allocator, &grp->name);
- return RES_OK;
-}
-
-res_T
-aw_obj_named_group_release(struct aw_obj_named_group* grp)
-{
- if(!grp) return RES_BAD_ARG;
- str_release(&grp->name);
- return RES_OK;
-}
-
-res_T
-aw_obj_named_group_copy
- (struct aw_obj_named_group* dst,
- const struct aw_obj_named_group* src)
-{
- if(!dst || !src) return RES_BAD_ARG;
- if(dst == src) return RES_OK;
- dst->face_id = src->face_id;
- dst->faces_count = src->faces_count;
- return str_copy(&dst->name, &src->name);
-}
-res_T
-aw_obj_named_group_copy_and_release
- (struct aw_obj_named_group* dst, struct aw_obj_named_group* src)
-{
- if(!dst || !src) return RES_BAD_ARG;
- if(dst == src) return RES_OK;
- dst->face_id = src->face_id;
- dst->faces_count = src->faces_count;
- return str_copy_and_release(&dst->name, &src->name);
+exit:
+ return res;
+error:
+ goto exit;
}
#ifdef COMPILER_CL
#pragma warning(pop)
#endif
+
diff --git a/src/test_aw.c b/src/test_aw.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2014-2017, 2020 Vincent Forest (vaplv@free.fr)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "aw.h"
+
+#include <rsys/clock_time.h>
+#include <rsys/mem_allocator.h>
+
+int
+main(int argc, char** argv)
+{
+ struct aw_obj* obj = NULL;
+ struct aw_mtl* mtl = NULL;
+ struct time t0, t1;
+ struct aw_obj_desc desc;
+ char buf[128];
+ size_t i;
+
+ if(argc < 2) {
+ fprintf(stderr, "Usage: %s OBJ-FILENAME\n", argv[0]);
+ return -1;
+ }
+
+ CHK(aw_obj_create(NULL, &mem_default_allocator, 1, &obj) == RES_OK);
+ CHK(aw_mtl_create(NULL, &mem_default_allocator, 1, &mtl) == RES_OK);
+
+ time_current(&t0);
+ CHK(aw_obj_load(obj, argv[1]) == RES_OK);
+ CHK(aw_obj_get_desc(obj, &desc) == RES_OK);
+ FOR_EACH(i, 0, desc.mtllibs_count) {
+ const char* mtllib = NULL;
+ CHK(aw_obj_get_mtllib(obj, i, &mtllib) == RES_OK);
+ aw_mtl_load(mtl, mtllib);
+ }
+ time_current(&t1);
+ time_sub(&t0, &t1, &t0);
+ time_dump(&t0, TIME_MIN|TIME_SEC|TIME_MSEC, NULL, buf, sizeof(buf));
+
+ fprintf(stdout, "load `%s' in %s\n", argv[1], buf);
+ fprintf(stdout, "faces count = %lu\n", (unsigned long)desc.faces_count);
+ fprintf(stdout, "groups count = %lu\n", (unsigned long)desc.groups_count);
+ fprintf(stdout, "usemtls count = %lu\n", (unsigned long)desc.usemtls_count);
+ fprintf(stdout, "mtllibs count = %lu\n", (unsigned long)desc.mtllibs_count);
+
+ CHK(aw_obj_ref_put(obj) == RES_OK);
+ CHK(aw_mtl_ref_put(mtl) == RES_OK);
+
+ CHK(MEM_ALLOCATED_SIZE(&mem_default_allocator) == 0);
+ CHK(mem_allocated_size() == 0);
+ return 0;
+}
diff --git a/src/test_aw_mtl.c b/src/test_aw_mtl.c
@@ -1,8 +1,8 @@
-/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr)
+/* Copyright (C) 2014-2017, 2020 Vincent Forest (vaplv@free.fr)
*
* This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -15,7 +15,7 @@
#include "aw.h"
-#include <rsys/float3.h>
+#include <rsys/double3.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
@@ -50,8 +50,8 @@ test_common(struct aw_mtl* mtl)
"bump -s 1 1 1 -o 0 0 0 -bm 1 sand.mpb";
FILE* file;
size_t nmtls;
- float tmp[3];
- struct aw_material mtr;
+ double tmp[3];
+ struct aw_material mat;
CHK(mtl != NULL);
@@ -66,101 +66,92 @@ test_common(struct aw_mtl* mtl)
CHK(aw_mtl_load(mtl, "none.mtl") == RES_IO_ERR);
CHK(aw_mtl_load(mtl, "test_mtl_common.mtl") == RES_OK);
- CHK(aw_mtl_materials_count_get(NULL, NULL) == RES_BAD_ARG);
- CHK(aw_mtl_materials_count_get(mtl, NULL) == RES_BAD_ARG);
- CHK(aw_mtl_materials_count_get(NULL, &nmtls) == RES_BAD_ARG);
- CHK(aw_mtl_materials_count_get(mtl, &nmtls) == RES_OK);
+ CHK(aw_mtl_get_materials_count(NULL, NULL) == RES_BAD_ARG);
+ CHK(aw_mtl_get_materials_count(mtl, NULL) == RES_BAD_ARG);
+ CHK(aw_mtl_get_materials_count(NULL, &nmtls) == RES_BAD_ARG);
+ CHK(aw_mtl_get_materials_count(mtl, &nmtls) == RES_OK);
CHK(nmtls == 1);
CHK(aw_mtl_clear(NULL) == RES_BAD_ARG);
CHK(aw_mtl_clear(mtl) == RES_OK);
- CHK(aw_mtl_materials_count_get(mtl, &nmtls) == RES_OK);
+ CHK(aw_mtl_get_materials_count(mtl, &nmtls) == RES_OK);
CHK(nmtls == 0);
CHK(aw_mtl_load(mtl, "test_mtl_common.mtl") == RES_OK);
- CHK(aw_material_init(NULL, NULL) == RES_BAD_ARG);
- CHK(aw_material_init(NULL, &mtr) == RES_OK);
- CHK(aw_mtl_material_get(NULL, SIZE_MAX, NULL) == RES_BAD_ARG);
- CHK(aw_mtl_material_get(mtl, SIZE_MAX, NULL) == RES_BAD_ARG);
- CHK(aw_mtl_material_get(NULL, 0, NULL) == RES_BAD_ARG);
- CHK(aw_mtl_material_get(mtl, 0, NULL) == RES_BAD_ARG);
- CHK(aw_mtl_material_get(NULL, SIZE_MAX, &mtr) == RES_BAD_ARG);
- CHK(aw_mtl_material_get(mtl, SIZE_MAX, &mtr) == RES_BAD_ARG);
- CHK(aw_mtl_material_get(NULL, 0, &mtr) == RES_BAD_ARG);
- CHK(aw_mtl_material_get(mtl, 0, &mtr) == RES_OK);
-
- CHK(strcmp(str_cget(&mtr.name), "my_mtl") == 0);
- CHK(mtr.ambient.color_space == AW_COLOR_RGB);
- f3(tmp, 0.0435f, 0.0436f, 0.0437f);
- CHK(f3_eq(mtr.ambient.value, tmp) == 1);
-
- CHK(mtr.diffuse.color_space == AW_COLOR_RGB);
- f3(tmp, 0.1086f, 0.1087f, 0.1088f);
- CHK(f3_eq(mtr.diffuse.value, tmp) == 1);
-
- CHK(mtr.specular.color_space == AW_COLOR_RGB);
- f3_splat(tmp, 0.f);
- CHK(f3_eq(mtr.specular.value, tmp) == 1);
-
- CHK(mtr.transmission.color_space == AW_COLOR_XYZ);
- f3(tmp, 0.987f, 0.988f, 0.989f);
- CHK(f3_eq(mtr.transmission.value, tmp) == 1);
-
- CHK(mtr.specular_exponent == 10.f);
- CHK(mtr.refraction_index == (float)1.19713f);
- CHK(mtr.illumination_model == 6);
-
- CHK(strcmp(str_cget(&mtr.ambient_map.filename), "chrome.mpc") == 0);
- CHK(mtr.ambient_map.options_mask == 0);
- CHK(mtr.ambient_map.image_bias == 0.f);
- CHK(mtr.ambient_map.image_scale == 1.f);
- CHK(f3_eq(mtr.ambient_map.texcoord_bias, f3_splat(tmp, 0.f)) == 1);
- CHK(f3_eq(mtr.ambient_map.texcoord_scale, f3_splat(tmp, 1.f)) == 1);
- CHK(f3_eq(mtr.ambient_map.texcoord_turbulence, f3_splat(tmp, 0.f)) == 1);
-
- CHK(strcmp(str_cget(&mtr.diffuse_map.filename), "chrome.mpc") == 0);
- CHK(mtr.diffuse_map.options_mask == 0);
- CHK(mtr.diffuse_map.image_bias == 0.f);
- CHK(mtr.diffuse_map.image_scale == 1.f);
- CHK(f3_eq(mtr.diffuse_map.texcoord_bias, f3_splat(tmp, 0.f)) == 1);
- CHK(f3_eq(mtr.diffuse_map.texcoord_scale, f3_splat(tmp, 1.f)) == 1);
- CHK(f3_eq(mtr.diffuse_map.texcoord_turbulence, f3_splat(tmp, 0.f)) == 1);
-
- CHK(strcmp(str_cget(&mtr.specular_map.filename), "chrome.mpc") == 0);
- CHK(mtr.specular_map.options_mask == 0);
- CHK(mtr.specular_map.image_bias == 0.f);
- CHK(mtr.specular_map.image_scale == 1.f);
- CHK(f3_eq(mtr.specular_map.texcoord_bias, f3_splat(tmp, 0.f)) == 1);
- CHK(f3_eq(mtr.specular_map.texcoord_scale, f3_splat(tmp, 1.f)) == 1);
- CHK(f3_eq(mtr.specular_map.texcoord_turbulence, f3_splat(tmp, 0.f)) == 1);
-
- CHK(strcmp(str_cget(&mtr.specular_exponent_map.filename), "wisp.mps") == 0);
- CHK(mtr.specular_exponent_map.options_mask == 0);
- CHK(mtr.specular_exponent_map.image_bias == 0.f);
- CHK(mtr.specular_exponent_map.image_scale == 1.f);
- CHK(f3_eq(mtr.specular_exponent_map.texcoord_scale, f3_splat(tmp, 1.f)) == 1);
- CHK(f3_eq(mtr.specular_exponent_map.texcoord_bias, f3_splat(tmp, 0.f)) == 1);
- CHK(f3_eq(mtr.specular_exponent_map.texcoord_turbulence, tmp) == 1);
- CHK(mtr.specular_exponent_map.scalar == AW_MAP_CHANNEL_LUMINANCE);
-
- CHK(strcmp(str_cget(&mtr.bump_map.filename), "sand.mpb") == 0);
- CHK(mtr.bump_map.options_mask == 0);
- CHK(mtr.bump_map.image_bias == 0.f);
- CHK(mtr.bump_map.image_scale == 1.f);
- CHK(f3_eq(mtr.bump_map.texcoord_scale, f3_splat(tmp, 1.f)) == 1);
- CHK(f3_eq(mtr.bump_map.texcoord_bias, f3_splat(tmp, 0.f)) == 1);
- CHK(f3_eq(mtr.bump_map.texcoord_turbulence, tmp) == 1);
- CHK(mtr.bump_map.scalar == AW_MAP_CHANNEL_LUMINANCE);
- CHK(mtr.bump_map.bump_multiplier == 1.f);
-
- CHK(aw_material_release(NULL) == RES_BAD_ARG);
- CHK(aw_material_release(&mtr) == RES_OK);
+ CHK(aw_mtl_get_material(NULL, 0, &mat) == RES_BAD_ARG);
+ CHK(aw_mtl_get_material(mtl, SIZE_MAX, &mat) == RES_BAD_ARG);
+ CHK(aw_mtl_get_material(mtl, 0, NULL) == RES_BAD_ARG);
+ CHK(aw_mtl_get_material(mtl, 0, &mat) == RES_OK);
+
+ CHK(!strcmp(mat.name, "my_mtl"));
+ CHK(mat.ambient.color_space == AW_COLOR_RGB);
+ d3(tmp, 0.0435, 0.0436, 0.0437);
+ CHK(d3_eq(mat.ambient.value, tmp));
+
+ CHK(mat.diffuse.color_space == AW_COLOR_RGB);
+ d3(tmp, 0.1086, 0.1087, 0.1088);
+ CHK(d3_eq(mat.diffuse.value, tmp));
+
+ CHK(mat.specular.color_space == AW_COLOR_RGB);
+ d3_splat(tmp, 0);
+ CHK(d3_eq(mat.specular.value, tmp));
+
+ CHK(mat.transmission.color_space == AW_COLOR_XYZ);
+ d3(tmp, 0.987, 0.988, 0.989);
+ CHK(d3_eq(mat.transmission.value, tmp));
+
+ CHK(mat.specular_exponent == 10.0);
+ CHK(mat.refraction_index == 1.19713);
+ CHK(mat.illumination_model == 6);
+
+ CHK(!strcmp(mat.ambient_map.filename, "chrome.mpc"));
+ CHK(mat.ambient_map.options_mask == 0);
+ CHK(mat.ambient_map.image_bias == 0.f);
+ CHK(mat.ambient_map.image_scale == 1.f);
+ CHK(d3_eq(mat.ambient_map.texcoord_bias, d3_splat(tmp, 0.0)));
+ CHK(d3_eq(mat.ambient_map.texcoord_scale, d3_splat(tmp, 1.0)));
+ CHK(d3_eq(mat.ambient_map.texcoord_turbulence, d3_splat(tmp, 0.0)));
+
+ CHK(!strcmp(mat.diffuse_map.filename, "chrome.mpc"));
+ CHK(mat.diffuse_map.options_mask == 0);
+ CHK(mat.diffuse_map.image_bias == 0.f);
+ CHK(mat.diffuse_map.image_scale == 1.f);
+ CHK(d3_eq(mat.diffuse_map.texcoord_bias, d3_splat(tmp, 0.0)));
+ CHK(d3_eq(mat.diffuse_map.texcoord_scale, d3_splat(tmp, 1.0)));
+ CHK(d3_eq(mat.diffuse_map.texcoord_turbulence, d3_splat(tmp, 0.0)));
+
+ CHK(!strcmp(mat.specular_map.filename, "chrome.mpc"));
+ CHK(mat.specular_map.options_mask == 0);
+ CHK(mat.specular_map.image_bias == 0.0);
+ CHK(mat.specular_map.image_scale == 1.0);
+ CHK(d3_eq(mat.specular_map.texcoord_bias, d3_splat(tmp, 0.0)));
+ CHK(d3_eq(mat.specular_map.texcoord_scale, d3_splat(tmp, 1.0)));
+ CHK(d3_eq(mat.specular_map.texcoord_turbulence, d3_splat(tmp, 0.0)));
+
+ CHK(!strcmp(mat.specular_exponent_map.filename, "wisp.mps"));
+ CHK(mat.specular_exponent_map.options_mask == 0);
+ CHK(mat.specular_exponent_map.image_bias == 0.0);
+ CHK(mat.specular_exponent_map.image_scale == 1.0);
+ CHK(d3_eq(mat.specular_exponent_map.texcoord_scale, d3_splat(tmp, 1.0)));
+ CHK(d3_eq(mat.specular_exponent_map.texcoord_bias, d3_splat(tmp, 0.0)));
+ CHK(d3_eq(mat.specular_exponent_map.texcoord_turbulence, tmp) == 1);
+ CHK(mat.specular_exponent_map.scalar == AW_MAP_CHANNEL_LUMINANCE);
+
+ CHK(!strcmp(mat.bump_map.filename, "sand.mpb"));
+ CHK(mat.bump_map.options_mask == 0);
+ CHK(mat.bump_map.image_bias == 0.0);
+ CHK(mat.bump_map.image_scale == 1.0);
+ CHK(d3_eq(mat.bump_map.texcoord_scale, d3_splat(tmp, 1.0)));
+ CHK(d3_eq(mat.bump_map.texcoord_bias, d3_splat(tmp, 0.0)));
+ CHK(d3_eq(mat.bump_map.texcoord_turbulence, tmp) == 1);
+ CHK(mat.bump_map.scalar == AW_MAP_CHANNEL_LUMINANCE);
+ CHK(mat.bump_map.bump_multiplier == 1.0);
CHK(aw_mtl_purge(NULL) == RES_BAD_ARG);
CHK(aw_mtl_purge(mtl) == RES_OK);
- CHK(aw_mtl_materials_count_get(mtl, &nmtls) == RES_OK);
+ CHK(aw_mtl_get_materials_count(mtl, &nmtls) == RES_OK);
CHK(nmtls == 0);
}
@@ -205,8 +196,8 @@ test_multiple_materials(struct aw_mtl* mtl)
"Ks 2\n";
FILE* file;
size_t nmtls;
- float tmp[3];
- struct aw_material mtr;
+ double tmp[3];
+ struct aw_material mat;
CHK(mtl != NULL);
@@ -215,81 +206,78 @@ test_multiple_materials(struct aw_mtl* mtl)
fwrite(mtl_multi, sizeof(char), strlen(mtl_multi), file);
CHK(fseek(file, 0, SEEK_SET) == 0);
- CHK(aw_mtl_load_stream(NULL, NULL) == RES_BAD_ARG);
- CHK(aw_mtl_load_stream(mtl, NULL) == RES_BAD_ARG);
- CHK(aw_mtl_load_stream(NULL, file) == RES_BAD_ARG);
- CHK(aw_mtl_load_stream(mtl, file) == RES_OK);
- CHK(aw_mtl_materials_count_get(mtl, &nmtls) == RES_OK);
+ CHK(aw_mtl_load_stream(NULL, file, NULL) == RES_BAD_ARG);
+ CHK(aw_mtl_load_stream(mtl, NULL, NULL) == RES_BAD_ARG);
+ CHK(aw_mtl_load_stream(mtl, file, NULL) == RES_OK);
+ CHK(aw_mtl_get_materials_count(mtl, &nmtls) == RES_OK);
CHK(nmtls == 3);
- CHK(aw_material_init(NULL, &mtr) == RES_OK);
- CHK(aw_mtl_material_get(mtl, 0, &mtr) == RES_OK);
- CHK(strcmp(str_cget(&mtr.name), "material_0") == 0);
- CHK(mtr.specular_exponent == 8.f);
- CHK(mtr.refraction_index == 1.5f);
- CHK(mtr.transmission.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.transmission.value, f3_splat(tmp, 1.f)) == 1);
- CHK(mtr.illumination_model == 2);
- CHK(mtr.ambient.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.ambient.value, f3_splat(tmp, 0.f)) == 1);
- CHK(mtr.diffuse.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.diffuse.value, f3(tmp, 0.734118f, 0.730588f, 0.674118f)) == 1);
- CHK(mtr.specular.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.specular.value, f3_splat(tmp, 0.f)) == 1);
- CHK(strcmp
- (str_cget(&mtr.ambient_map.filename),
- "my_long_and_verbose_filename_of_a_RED_GREEN_BLUE_1024x64_image.png") == 0);
- CHK(mtr.ambient_map.options_mask == 0);
- CHK(mtr.ambient_map.image_bias == 0.f);
- CHK(mtr.ambient_map.image_scale == 1.f);
- CHK(f3_eq(mtr.ambient_map.texcoord_bias, f3_splat(tmp, 0.f)) == 1);
- CHK(f3_eq(mtr.ambient_map.texcoord_scale, f3_splat(tmp, 1.f)) == 1);
- CHK(f3_eq(mtr.ambient_map.texcoord_turbulence, f3_splat(tmp, 0.f)) == 1);
- CHK(mtr.ambient_map.resolution == 0);
- CHK(strcmp(str_cget(&mtr.diffuse_map.filename), "tp.png") == 0);
- CHK(str_len(&mtr.specular_map.filename) == 0);
- CHK(str_len(&mtr.specular_exponent_map.filename) == 0);
- CHK(str_len(&mtr.bump_map.filename) == 0);
-
- CHK(aw_mtl_material_get(mtl, 1, &mtr) == RES_OK);
- CHK(strcmp(str_cget(&mtr.name), "textured_material") == 0);
- CHK(mtr.specular_exponent == 6.f);
- CHK(mtr.refraction_index == (float)1.7f);
- CHK(mtr.transmission.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.transmission.value, f3(tmp, 1.f, 1.2f, 1.3f)) == 1);
- CHK(mtr.illumination_model == 0);
- CHK(mtr.ambient.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.ambient.value, f3_splat(tmp, 0.f)) == 1);
- CHK(mtr.diffuse.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.diffuse.value, f3(tmp, 0.734118f, 0.709412f, 0.674118f)) == 1);
- CHK(mtr.specular.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.specular.value, f3_splat(tmp, 0.f)) == 1);
- CHK(strcmp(str_cget(&mtr.ambient_map.filename), "tex6x6.png") == 0);
- CHK(strcmp(str_cget(&mtr.diffuse_map.filename), "tex6x6.png") == 0);
- CHK(strcmp(str_cget(&mtr.bump_map.filename), "tex6x6-bump.png") == 0);
- CHK(mtr.bump_map.scalar == AW_MAP_CHANNEL_RED);
- CHK(mtr.bump_map.bump_multiplier == (float)0.2f);
- CHK(str_len(&mtr.specular_exponent_map.filename) == 0);
-
- CHK(aw_mtl_material_get(mtl, 2, &mtr) == RES_OK);
- CHK(strcmp(str_cget(&mtr.name), "hello_world") == 0);
- CHK(mtr.specular_exponent == 8.f);
- CHK(mtr.refraction_index == 1.5f);
- CHK(mtr.transmission.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.transmission.value, f3_splat(tmp, 1.f)) == 1);
- CHK(mtr.illumination_model == 2);
- CHK(mtr.ambient.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.ambient.value, f3_splat(tmp, 0.f)) == 1);
- CHK(mtr.diffuse.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.diffuse.value, f3(tmp, 0.546274f, 0.219608f, 0.183922f)) == 1);
- CHK(mtr.specular.color_space == AW_COLOR_RGB);
- CHK(f3_eq(mtr.specular.value, f3_splat(tmp, 2.f)) == 1);
- CHK(str_len(&mtr.ambient_map.filename) == 0);
- CHK(str_len(&mtr.diffuse_map.filename) == 0);
- CHK(str_len(&mtr.bump_map.filename) == 0);
- CHK(str_len(&mtr.specular_exponent_map.filename) == 0);
-
- CHK(aw_material_release(&mtr) == RES_OK);
+ CHK(aw_mtl_get_material(mtl, 0, &mat) == RES_OK);
+ CHK(!strcmp(mat.name, "material_0"));
+ CHK(mat.specular_exponent == 8.f);
+ CHK(mat.refraction_index == 1.5f);
+ CHK(mat.transmission.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.transmission.value, d3_splat(tmp, 1.0)));
+ CHK(mat.illumination_model == 2);
+ CHK(mat.ambient.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.ambient.value, d3_splat(tmp, 0.0)));
+ CHK(mat.diffuse.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.diffuse.value, d3(tmp, 0.734118, 0.730588, 0.674118)));
+ CHK(mat.specular.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.specular.value, d3_splat(tmp, 0.0)));
+ CHK(!strcmp
+ (mat.ambient_map.filename,
+ "my_long_and_verbose_filename_of_a_RED_GREEN_BLUE_1024x64_image.png"));
+ CHK(mat.ambient_map.options_mask == 0);
+ CHK(mat.ambient_map.image_bias == 0.0);
+ CHK(mat.ambient_map.image_scale == 1.0);
+ CHK(d3_eq(mat.ambient_map.texcoord_bias, d3_splat(tmp, 0.0)));
+ CHK(d3_eq(mat.ambient_map.texcoord_scale, d3_splat(tmp, 1.0)));
+ CHK(d3_eq(mat.ambient_map.texcoord_turbulence, d3_splat(tmp, 0.0)));
+ CHK(mat.ambient_map.resolution == 0);
+ CHK(!strcmp(mat.diffuse_map.filename, "tp.png"));
+ CHK(!mat.specular_map.filename);
+ CHK(!mat.specular_exponent_map.filename);
+ CHK(!mat.bump_map.filename);
+
+ CHK(aw_mtl_get_material(mtl, 1, &mat) == RES_OK);
+ CHK(!strcmp(mat.name, "textured_material"));
+ CHK(mat.specular_exponent == 6.0);
+ CHK(mat.refraction_index == 1.7);
+ CHK(mat.transmission.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.transmission.value, d3(tmp, 1.0, 1.2, 1.3)));
+ CHK(mat.illumination_model == 0);
+ CHK(mat.ambient.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.ambient.value, d3_splat(tmp, 0.0)));
+ CHK(mat.diffuse.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.diffuse.value, d3(tmp, 0.734118, 0.709412, 0.674118)));
+ CHK(mat.specular.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.specular.value, d3_splat(tmp, 0.0)));
+ CHK(!strcmp(mat.ambient_map.filename, "tex6x6.png"));
+ CHK(!strcmp(mat.diffuse_map.filename, "tex6x6.png"));
+ CHK(!strcmp(mat.bump_map.filename, "tex6x6-bump.png"));
+ CHK(mat.bump_map.scalar == AW_MAP_CHANNEL_RED);
+ CHK(mat.bump_map.bump_multiplier == 0.2);
+ CHK(!mat.specular_exponent_map.filename);
+
+ CHK(aw_mtl_get_material(mtl, 2, &mat) == RES_OK);
+ CHK(!strcmp(mat.name, "hello_world"));
+ CHK(mat.specular_exponent == 8.0);
+ CHK(mat.refraction_index == 1.5);
+ CHK(mat.transmission.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.transmission.value, d3_splat(tmp, 1.0)));
+ CHK(mat.illumination_model == 2);
+ CHK(mat.ambient.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.ambient.value, d3_splat(tmp, 0.0)));
+ CHK(mat.diffuse.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.diffuse.value, d3(tmp, 0.546274, 0.219608, 0.183922)));
+ CHK(mat.specular.color_space == AW_COLOR_RGB);
+ CHK(d3_eq(mat.specular.value, d3_splat(tmp, 2.0)));
+ CHK(!mat.ambient_map.filename);
+ CHK(!mat.diffuse_map.filename);
+ CHK(!mat.bump_map.filename);
+ CHK(!mat.specular_exponent_map.filename);
+
fclose(file);
}
@@ -318,7 +306,7 @@ test_unloadable(struct aw_mtl* mtl)
fclose(file);
CHK(aw_mtl_load(mtl, "mtl0.mtl") == RES_BAD_ARG);
- CHK(aw_mtl_materials_count_get(mtl, &nmtls) == RES_OK);
+ CHK(aw_mtl_get_materials_count(mtl, &nmtls) == RES_OK);
CHK(nmtls == 0);
}
int
@@ -330,9 +318,9 @@ main(int argc, char** argv)
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(aw_mtl_create(NULL, NULL, 1, NULL) == RES_BAD_ARG);
- CHK(aw_mtl_create(NULL, &allocator, 1, NULL) == RES_BAD_ARG);
- CHK(aw_mtl_create(NULL, NULL, 1, &mtl) == RES_OK);
+ CHK(aw_mtl_create(LOGGER_DEFAULT, NULL, 1, NULL) == RES_BAD_ARG);
+ CHK(aw_mtl_create(LOGGER_DEFAULT, &allocator, 1, NULL) == RES_BAD_ARG);
+ CHK(aw_mtl_create(LOGGER_DEFAULT, NULL, 1, &mtl) == RES_OK);
CHK(aw_mtl_ref_get(NULL) == RES_BAD_ARG);
CHK(aw_mtl_ref_get(mtl) == RES_OK);
@@ -340,7 +328,7 @@ main(int argc, char** argv)
CHK(aw_mtl_ref_put(mtl) == RES_OK);
CHK(aw_mtl_ref_put(mtl) == RES_OK);
- CHK(aw_mtl_create(LOGGER_DEFAULT, &allocator, 1, &mtl) == RES_OK);
+ CHK(aw_mtl_create(NULL, &allocator, 1, &mtl) == RES_OK);
test_common(mtl);
test_multiple_materials(mtl);
diff --git a/src/test_aw_obj.c b/src/test_aw_obj.c
@@ -1,8 +1,8 @@
-/* Copyright (C) 2013-2016 Vincent Forest (vaplv@free.fr)
+/* Copyright (C) 2014-2017, 2020 Vincent Forest (vaplv@free.fr)
*
* This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation, either version 3 of the License, or
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -15,8 +15,8 @@
#include "aw.h"
-#include <rsys/float3.h>
-#include <rsys/float4.h>
+#include <rsys/double3.h>
+#include <rsys/double4.h>
#include <rsys/logger.h>
#include <rsys/mem_allocator.h>
@@ -29,6 +29,7 @@ test_plane(struct aw_obj* obj)
"mtllib master.mtl"
"\n"
"g\n"
+ "o plane\n"
"v 0.0000 2.0000 0.0000\n"
"v 0.0000 0.0000 0.0000\n"
"v 2.0000 0.0000 0.0000\n"
@@ -42,12 +43,13 @@ test_plane(struct aw_obj* obj)
"usemtl wood\n"
"f 1/1 2/2 3/3 4/4\n"
"# 1 element\n";
- float v4[4];
+ double v4[4];
struct aw_obj_desc desc;
struct aw_obj_face face;
struct aw_obj_named_group group;
struct aw_obj_named_group mtl;
struct aw_obj_vertex vertex;
+ struct aw_obj_vertex_data vdata;
FILE* file;
const char* mtllib;
@@ -58,98 +60,89 @@ test_plane(struct aw_obj* obj)
fwrite(plane_obj, sizeof(char), strlen(plane_obj), file);
fclose(file);
- CHK(aw_obj_named_group_init(NULL, NULL) == RES_BAD_ARG);
- CHK(aw_obj_named_group_init(NULL, &group) == RES_OK);
- CHK(aw_obj_named_group_init(NULL, &mtl) == RES_OK);
-
- CHK(aw_obj_load(NULL, NULL) == RES_BAD_ARG);
CHK(aw_obj_load(obj, NULL) == RES_BAD_ARG);
CHK(aw_obj_load(NULL, "test_obj_plane.obj") == RES_BAD_ARG);
CHK(aw_obj_load(obj, "none.obj") == RES_IO_ERR);
CHK(aw_obj_load(obj, "test_obj_plane.obj") == RES_OK);
- CHK(aw_obj_desc_get(NULL, NULL) == RES_BAD_ARG);
- CHK(aw_obj_desc_get(obj, NULL) == RES_BAD_ARG);
- CHK(aw_obj_desc_get(NULL, &desc) == RES_BAD_ARG);
- CHK(aw_obj_desc_get(obj, &desc) == RES_OK);
+ CHK(aw_obj_get_desc(NULL, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_get_desc(obj, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_get_desc(NULL, &desc) == RES_BAD_ARG);
+ CHK(aw_obj_get_desc(obj, &desc) == RES_OK);
CHK(desc.faces_count == 1);
CHK(desc.groups_count == 1);
CHK(desc.smooth_groups_count == 0);
CHK(desc.usemtls_count == 1);
CHK(desc.mtllibs_count == 1);
- CHK(aw_obj_face_get(NULL, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_face_get(obj, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_face_get(NULL, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_face_get(obj, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_face_get(NULL, AW_ID_NONE, &face) == RES_BAD_ARG);
- CHK(aw_obj_face_get(obj, AW_ID_NONE, &face) == RES_BAD_ARG);
- CHK(aw_obj_face_get(NULL, 0, &face) == RES_BAD_ARG);
- CHK(aw_obj_face_get(obj, 0, &face) == RES_OK);
+ CHK(aw_obj_get_face(NULL, 0, &face) == RES_BAD_ARG);
+ CHK(aw_obj_get_face(obj, AW_ID_NONE, &face) == RES_BAD_ARG);
+ CHK(aw_obj_get_face(obj, 0, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_get_face(obj, 0, &face) == RES_OK);
CHK(face.vertex_id == 0);
CHK(face.vertices_count == 4);
CHK(face.group_id == 0);
CHK(face.smooth_group_id == AW_ID_NONE);
CHK(face.mtl_id == 0);
- CHK(aw_obj_mtl_get(NULL, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_mtl_get(obj, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_mtl_get(NULL, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_mtl_get(obj, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_mtl_get(NULL, AW_ID_NONE, &mtl) == RES_BAD_ARG);
- CHK(aw_obj_mtl_get(obj, AW_ID_NONE, &mtl) == RES_BAD_ARG);
- CHK(aw_obj_mtl_get(NULL, 0, &mtl) == RES_BAD_ARG);
- CHK(aw_obj_mtl_get(obj, 0, &mtl) == RES_OK);
- CHK(strcmp(str_cget(&mtl.name), "wood") == 0);
+ CHK(aw_obj_get_mtl(NULL, 0, &mtl) == RES_BAD_ARG);
+ CHK(aw_obj_get_mtl(obj, AW_ID_NONE, &mtl) == RES_BAD_ARG);
+ CHK(aw_obj_get_mtl(obj, 0, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_get_mtl(obj, 0, &mtl) == RES_OK);
+ CHK(!strcmp(mtl.name, "wood"));
CHK(mtl.face_id == 0);
CHK(mtl.faces_count == 1);
- CHK(aw_obj_mtllib_get(NULL, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_mtllib_get(obj, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_mtllib_get(NULL, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_mtllib_get(obj, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_mtllib_get(NULL, AW_ID_NONE, &mtllib) == RES_BAD_ARG);
- CHK(aw_obj_mtllib_get(obj, AW_ID_NONE, &mtllib) == RES_BAD_ARG);
- CHK(aw_obj_mtllib_get(NULL, 0, &mtllib) == RES_BAD_ARG);
- CHK(aw_obj_mtllib_get(obj, 0, &mtllib) == RES_OK);
+ CHK(aw_obj_get_mtllib(NULL, 0, &mtllib) == RES_BAD_ARG);
+ CHK(aw_obj_get_mtllib(obj, AW_ID_NONE, &mtllib) == RES_BAD_ARG);
+ CHK(aw_obj_get_mtllib(obj, 0, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_get_mtllib(obj, 0, &mtllib) == RES_OK);
CHK(strcmp(mtllib, "master.mtl") == 0);
- CHK(aw_obj_vertex_get(NULL, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_vertex_get(obj, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_vertex_get(NULL, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_vertex_get(obj, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_vertex_get(NULL, AW_ID_NONE, &vertex) == RES_BAD_ARG);
- CHK(aw_obj_vertex_get(obj, AW_ID_NONE, &vertex) == RES_BAD_ARG);
- CHK(aw_obj_vertex_get(NULL, 0, &vertex) == RES_BAD_ARG);
-
- CHK(aw_obj_vertex_get(obj, 0, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 0.f, 2.f, 0.f, 1.f)) == 1);
- CHK(f3_eq(vertex.texcoord, f3(v4, 0.f, 1.f, 0.f)) == 1);
- CHK(aw_obj_vertex_get(obj, 1, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 0.f, 0.f, 0.f, 1.f)) == 1);
- CHK(f3_eq(vertex.texcoord, f3(v4, 0.f, 0.f, 0.f)) == 1);
- CHK(aw_obj_vertex_get(obj, 2, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 2.f, 0.f, 0.f, 1.f)) == 1);
- CHK(f3_eq(vertex.texcoord, f3(v4, 1.f, 0.f, 0.f)) == 1);
- CHK(aw_obj_vertex_get(obj, 3, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 2.f, 2.f, 0.f, 1.f)) == 1);
- CHK(f3_eq(vertex.texcoord, f3(v4, 1.f, 1.f, 0.f)) == 1);
-
- CHK(aw_obj_group_get(NULL, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_group_get(obj, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_group_get(NULL, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_group_get(obj, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_group_get(NULL, AW_ID_NONE, &group) == RES_BAD_ARG);
- CHK(aw_obj_group_get(obj, AW_ID_NONE, &group) == RES_BAD_ARG);
- CHK(aw_obj_group_get(NULL, 0, &group) == RES_BAD_ARG);
- CHK(aw_obj_group_get(obj, 0, &group) == RES_OK);
- CHK(strcmp(str_cget(&group.name), "default") == 0);
+ CHK(aw_obj_get_vertex(NULL, 0, &vertex) == RES_BAD_ARG);
+ CHK(aw_obj_get_vertex(obj, AW_ID_NONE, &vertex) == RES_BAD_ARG);
+ CHK(aw_obj_get_vertex(obj, 0, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_get_vertex(obj, 0, &vertex) == RES_OK);
+
+ CHK(aw_obj_get_vertex_data(NULL, &vertex, &vdata) == RES_BAD_ARG);
+ CHK(aw_obj_get_vertex_data(obj, NULL, &vdata) == RES_BAD_ARG);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, NULL) == RES_BAD_ARG);
+
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 0, 2, 0, 1)));
+ CHK(d3_eq(vdata.texcoord, d3(v4, 0, 1, 0)));
+
+ vertex.position_id = 4;
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_BAD_ARG);
+ vertex.position_id = 0;
+ vertex.texcoord_id = 4;
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_BAD_ARG);
+ vertex.texcoord_id = 0;
+ vertex.normal_id = 0;
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_BAD_ARG);
+
+ CHK(aw_obj_get_vertex(obj, 1, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 0, 0, 0, 1)));
+ CHK(d3_eq(vdata.texcoord, d3(v4, 0, 0, 0)));
+
+ CHK(aw_obj_get_vertex(obj, 2, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 2, 0, 0, 1)));
+ CHK(d3_eq(vdata.texcoord, d3(v4, 1, 0, 0)));
+
+ CHK(aw_obj_get_vertex(obj, 3, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 2, 2, 0, 1)));
+ CHK(d3_eq(vdata.texcoord, d3(v4, 1, 1, 0)));
+
+ CHK(aw_obj_get_group(NULL, 0, &group) == RES_BAD_ARG);
+ CHK(aw_obj_get_group(obj, AW_ID_NONE, &group) == RES_BAD_ARG);
+ CHK(aw_obj_get_group(obj, 0, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_get_group(obj, 0, &group) == RES_OK);
+ CHK(!strcmp(group.name, "default"));
CHK(group.face_id == 0);
CHK(group.faces_count == 1);
-
- CHK(aw_obj_named_group_release(NULL) == RES_BAD_ARG);
- CHK(aw_obj_named_group_release(&group) == RES_OK);
- CHK(aw_obj_named_group_release(&mtl) == RES_OK);
}
static void
@@ -177,18 +170,17 @@ test_squares(struct aw_obj* obj)
"f 1//1 2//2 3//3 4//4\n"
"f 4//4 3//3 5//5 6//6\n"
"# 2 elements\n";
- float v4[4];
+ double v4[4];
struct aw_obj_desc desc;
struct aw_obj_face face;
struct aw_obj_named_group group;
struct aw_obj_named_group mtl;
struct aw_obj_smooth_group sgroup;
struct aw_obj_vertex vertex;
+ struct aw_obj_vertex_data vdata;
FILE* file;
CHK(obj != NULL);
- CHK(aw_obj_named_group_init(NULL, &group) == RES_OK);
- CHK(aw_obj_named_group_init(NULL, &mtl) == RES_OK);
file = fopen("test_obj_squares.obj", "w");
CHK(file != NULL);
@@ -196,81 +188,78 @@ test_squares(struct aw_obj* obj)
fclose(file);
CHK(aw_obj_load(obj, "test_obj_squares.obj") == RES_OK);
- CHK(aw_obj_desc_get(obj, &desc) == RES_OK);
+ CHK(aw_obj_get_desc(obj, &desc) == RES_OK);
CHK(desc.faces_count == 2);
CHK(desc.groups_count == 1);
CHK(desc.smooth_groups_count == 1);
CHK(desc.usemtls_count == 0);
CHK(desc.mtllibs_count == 0);
- CHK(aw_obj_face_get(obj, 0, &face) == RES_OK);
+ CHK(aw_obj_get_face(obj, 0, &face) == RES_OK);
CHK(face.vertex_id == 0);
CHK(face.vertices_count == 4);
CHK(face.group_id == 0);
CHK(face.smooth_group_id == 0);
CHK(face.mtl_id == AW_ID_NONE);
- CHK(aw_obj_vertex_get(obj, 0, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 0.f, 2.f, 0.f, 1.f)) == 1);
- CHK(f3_eq(vertex.normal, f3(v4, 0.f, 0.f, 1.f)) == 1);
- CHK(aw_obj_vertex_get(obj, 1, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 0.f, 0.f, 0.f, 1.f)) == 1);
- CHK(f3_eq(vertex.normal, f3(v4, 0.f, 0.f, 1.f)) == 1);
- CHK(aw_obj_vertex_get(obj, 2, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 2.f, 0.f, 0.f, 1.f)) == 1);
- CHK(f3_eq(vertex.normal, f3(v4, 0.276597f, 0.f, 0.960986f)) == 1);
- CHK(aw_obj_vertex_get(obj, 3, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 2.f, 2.f, 0.f, 1.f)) == 1);
- CHK(f3_eq(vertex.normal, f3(v4, 0.276597f, 0.f, 0.960986f)) == 1);
-
- CHK(aw_obj_face_get(obj, 1, &face) == RES_OK);
+ CHK(aw_obj_get_vertex(obj, 0, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 0.0, 2.0, 0.0, 1.0)));
+ CHK(d3_eq(vdata.normal, d3(v4, 0.0, 0.0, 1.0)));
+ CHK(aw_obj_get_vertex(obj, 1, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 0.0, 0.0, 0.0, 1.0)));
+ CHK(d3_eq(vdata.normal, d3(v4, 0.0, 0.0, 1.0)));
+ CHK(aw_obj_get_vertex(obj, 2, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 2.0, 0.0, 0.0, 1.0)));
+ CHK(d3_eq(vdata.normal, d3(v4, 0.276597, 0.0, 0.960986)));
+ CHK(aw_obj_get_vertex(obj, 3, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 2.0, 2.0, 0.0, 1.0)));
+ CHK(d3_eq(vdata.normal, d3(v4, 0.276597, 0.0, 0.960986)));
+
+ CHK(aw_obj_get_face(obj, 1, &face) == RES_OK);
CHK(face.vertex_id == 4);
CHK(face.vertices_count == 4);
CHK(face.group_id == 0);
CHK(face.smooth_group_id == 0);
CHK(face.mtl_id == AW_ID_NONE);
- CHK(aw_obj_vertex_get(obj, 4, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 2.f, 2.f, 0.f, 1.f)) == 1);
- CHK(f3_eq(vertex.normal, f3(v4, 0.276597f, 0.f, 0.960986f)) == 1);
- CHK(aw_obj_vertex_get(obj, 5, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 2.f, 0.f, 0.f, 1.f)) == 1);
- CHK(f3_eq(vertex.normal, f3(v4, 0.276597f, 0.f, 0.960986f)) == 1);
- CHK(aw_obj_vertex_get(obj, 6, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 4.f, 0.f, -1.255298f, 1.f)) == 1);
- CHK(f3_eq(vertex.normal, f3(v4, 0.531611f, 0.f, 0.846988f)) == 1);
- CHK(aw_obj_vertex_get(obj, 7, &vertex) == RES_OK);
- CHK(f4_eq(vertex.position, f4(v4, 4.f, 2.f, -1.255298f, 1.f)) == 1);
- CHK(f3_eq(vertex.normal, f3(v4, 0.531611f, 0.f, 0.846988f)) == 1);
-
- CHK(aw_obj_group_get(NULL, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_group_get(obj, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_group_get(NULL, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_group_get(obj, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_group_get(NULL, AW_ID_NONE, &group) == RES_BAD_ARG);
- CHK(aw_obj_group_get(obj, AW_ID_NONE, &group) == RES_BAD_ARG);
- CHK(aw_obj_group_get(NULL, 0, &group) == RES_BAD_ARG);
- CHK(aw_obj_group_get(obj, 0, &group) == RES_OK);
- CHK(strcmp(str_cget(&group.name), "all") == 0);
+ CHK(aw_obj_get_vertex(obj, 4, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 2.0, 2.0, 0.0, 1.0)));
+ CHK(d3_eq(vdata.normal, d3(v4, 0.276597, 0.0, 0.960986)));
+ CHK(aw_obj_get_vertex(obj, 5, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 2.0, 0.0, 0.0, 1.0)));
+ CHK(d3_eq(vdata.normal, d3(v4, 0.276597, 0.0, 0.960986)));
+ CHK(aw_obj_get_vertex(obj, 6, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 4.0, 0.0, -1.255298, 1.0)));
+ CHK(d3_eq(vdata.normal, d3(v4, 0.531611, 0.0, 0.8469880)));
+ CHK(aw_obj_get_vertex(obj, 7, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d4_eq(vdata.position, d4(v4, 4.0, 2.0, -1.255298, 1.0)) == 1);
+ CHK(d3_eq(vdata.normal, d3(v4, 0.531611, 0.0, 0.846988)) == 1);
+
+ CHK(aw_obj_get_group(NULL, 0, &group) == RES_BAD_ARG);
+ CHK(aw_obj_get_group(obj, AW_ID_NONE, &group) == RES_BAD_ARG);
+ CHK(aw_obj_get_group(obj, 0, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_get_group(obj, 0, &group) == RES_OK);
+ CHK(strcmp(group.name, "all") == 0);
CHK(group.face_id == 0);
CHK(group.faces_count == 2);
- CHK(aw_obj_smooth_group_get(NULL, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_smooth_group_get(obj, AW_ID_NONE, NULL) == RES_BAD_ARG);
- CHK(aw_obj_smooth_group_get(NULL, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_smooth_group_get(obj, 0, NULL) == RES_BAD_ARG);
- CHK(aw_obj_smooth_group_get(NULL, AW_ID_NONE, &sgroup) == RES_BAD_ARG);
- CHK(aw_obj_smooth_group_get(obj, AW_ID_NONE, &sgroup) == RES_BAD_ARG);
- CHK(aw_obj_smooth_group_get(NULL, 0, &sgroup) == RES_BAD_ARG);
- CHK(aw_obj_smooth_group_get(obj, 0, &sgroup) == RES_OK);
+ CHK(aw_obj_get_smooth_group(NULL, 0, &sgroup) == RES_BAD_ARG);
+ CHK(aw_obj_get_smooth_group(obj, AW_ID_NONE, &sgroup) == RES_BAD_ARG);
+ CHK(aw_obj_get_smooth_group(obj, 0, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_get_smooth_group(obj, 0, &sgroup) == RES_OK);
CHK(sgroup.is_smoothed == 1);
CHK(sgroup.face_id == 0);
CHK(sgroup.faces_count == 2);
- CHK(aw_obj_mtl_get(obj, 0, &mtl) == RES_BAD_ARG);
-
- CHK(aw_obj_named_group_release(&group) == RES_OK);
- CHK(aw_obj_named_group_release(&mtl) == RES_OK);
+ CHK(aw_obj_get_mtl(obj, 0, &mtl) == RES_BAD_ARG);
}
static void
@@ -324,12 +313,11 @@ test_cube(struct aw_obj* obj)
fwrite(cube_obj, sizeof(char), strlen(cube_obj), file);
CHK(fseek(file, 0, SEEK_SET) == 0);
- CHK(aw_obj_load_stream(NULL, NULL) == RES_BAD_ARG);
- CHK(aw_obj_load_stream(obj, NULL) == RES_BAD_ARG);
- CHK(aw_obj_load_stream(NULL, file) == RES_BAD_ARG);
- CHK(aw_obj_load_stream(obj, file) == RES_OK);
+ CHK(aw_obj_load_stream(obj, NULL, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_load_stream(NULL, file, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_load_stream(obj, file, NULL) == RES_OK);
- CHK(aw_obj_desc_get(obj, &desc) == RES_OK);
+ CHK(aw_obj_get_desc(obj, &desc) == RES_OK);
CHK(desc.faces_count == 6);
CHK(desc.groups_count == 6);
CHK(desc.smooth_groups_count == 0);
@@ -338,7 +326,7 @@ test_cube(struct aw_obj* obj)
CHK(aw_obj_clear(NULL) == RES_BAD_ARG);
CHK(aw_obj_clear(obj) == RES_OK);
- CHK(aw_obj_desc_get(obj, &desc) == RES_OK);
+ CHK(aw_obj_get_desc(obj, &desc) == RES_OK);
CHK(desc.faces_count == 0);
CHK(desc.groups_count == 0);
CHK(desc.smooth_groups_count == 0);
@@ -346,12 +334,12 @@ test_cube(struct aw_obj* obj)
CHK(desc.mtllibs_count == 0);
CHK(fseek(file, 0, SEEK_SET) == 0);
- CHK(aw_obj_load_stream(obj, file) == RES_OK);
- CHK(aw_obj_desc_get(obj, &desc) == RES_OK);
+ CHK(aw_obj_load_stream(obj, file, "cube") == RES_OK);
+ CHK(aw_obj_get_desc(obj, &desc) == RES_OK);
FOR_EACH(i, 0, 6) {
struct aw_obj_face face;
- CHK(aw_obj_face_get(obj, i, &face) == RES_OK);
+ CHK(aw_obj_get_face(obj, i, &face) == RES_OK);
CHK(face.vertex_id == i*4);
CHK(face.vertices_count == 4);
CHK(face.group_id == i);
@@ -361,35 +349,31 @@ test_cube(struct aw_obj* obj)
FOR_EACH(i, 0, 6) {
struct aw_obj_named_group group;
- CHK(aw_obj_named_group_init(NULL, &group) == RES_OK);
- CHK(aw_obj_group_get(obj, i, &group) == RES_OK);
- CHK(strcmp(str_cget(&group.name), group_names[i]) == 0);
+ CHK(aw_obj_get_group(obj, i, &group) == RES_OK);
+ CHK(!strcmp(group.name, group_names[i]));
CHK(group.face_id == i);
CHK(group.faces_count == 1);
- CHK(aw_obj_named_group_release(&group) == RES_OK);
}
FOR_EACH(i, 0, 6) {
struct aw_obj_named_group mtl;
- CHK(aw_obj_named_group_init(NULL, &mtl) == RES_OK);
- CHK(aw_obj_mtl_get(obj, i, &mtl) == RES_OK);
- CHK(strcmp(str_cget(&mtl.name), mtl_names[i]) == 0);
+ CHK(aw_obj_get_mtl(obj, i, &mtl) == RES_OK);
+ CHK(!strcmp(mtl.name, mtl_names[i]));
CHK(mtl.face_id == i);
CHK(mtl.faces_count == 1);
- CHK(aw_obj_named_group_release(&mtl) == RES_OK);
}
- CHK(aw_obj_mtllib_get(obj, 0, &mtllib) == RES_OK);
- CHK(strcmp(mtllib, "master.mtl") == 0);
- CHK(aw_obj_mtllib_get(obj, 1, &mtllib) == RES_OK);
- CHK(strcmp(mtllib, "hop.mtl") == 0);
- CHK(aw_obj_mtllib_get(obj, 2, &mtllib) == RES_OK);
- CHK(strcmp(mtllib, "my.mtl") == 0);
- CHK(aw_obj_mtllib_get(obj, 3, &mtllib) == RES_BAD_ARG);
+ CHK(aw_obj_get_mtllib(obj, 0, &mtllib) == RES_OK);
+ CHK(!strcmp(mtllib, "master.mtl"));
+ CHK(aw_obj_get_mtllib(obj, 1, &mtllib) == RES_OK);
+ CHK(!strcmp(mtllib, "hop.mtl"));
+ CHK(aw_obj_get_mtllib(obj, 2, &mtllib) == RES_OK);
+ CHK(!strcmp(mtllib, "my.mtl"));
+ CHK(aw_obj_get_mtllib(obj, 3, &mtllib) == RES_BAD_ARG);
CHK(aw_obj_purge(NULL) == RES_BAD_ARG);
CHK(aw_obj_purge(obj) == RES_OK);
- CHK(aw_obj_desc_get(obj, &desc) == RES_OK);
+ CHK(aw_obj_get_desc(obj, &desc) == RES_OK);
CHK(desc.faces_count == 0);
CHK(desc.groups_count == 0);
CHK(desc.smooth_groups_count == 0);
@@ -446,106 +430,114 @@ test_cbox(struct aw_obj* obj)
struct aw_obj_desc desc;
struct aw_obj_face face;
struct aw_obj_vertex vertex;
+ struct aw_obj_vertex_data vdata;
struct aw_obj_named_group group;
struct aw_obj_named_group mtl;
- float tmp[3];
+ double tmp[3];
FILE* file;
CHK(obj != NULL);
- CHK(aw_obj_named_group_init(NULL, &group) == RES_OK);
- CHK(aw_obj_named_group_init(NULL, &mtl) == RES_OK);
file = fopen("test_cbox.obj", "w+");
CHK(file != NULL);
fwrite(cbox_obj, sizeof(char), strlen(cbox_obj), file);
CHK(fseek(file, 0, SEEK_SET) == 0);
- CHK(aw_obj_load_stream(obj, file) == RES_OK);
+ CHK(aw_obj_load_stream(obj, file, "cbox") == RES_OK);
fclose(file);
- CHK(aw_obj_desc_get(obj, &desc) == RES_OK);
+ CHK(aw_obj_get_desc(obj, &desc) == RES_OK);
CHK(desc.faces_count == 5);
CHK(desc.groups_count == 5);
CHK(desc.smooth_groups_count == 0);
CHK(desc.usemtls_count == 5);
CHK(desc.mtllibs_count == 1);
- CHK(aw_obj_face_get(obj, 0, &face) == RES_OK);
+ CHK(aw_obj_get_face(obj, 0, &face) == RES_OK);
CHK(face.vertex_id == 0);
CHK(face.vertices_count == 4);
CHK(face.group_id == 0);
CHK(face.mtl_id == 0);
- CHK(aw_obj_group_get(obj, 0, &group) == RES_OK);
- CHK(strcmp(str_cget(&group.name), "floor") == 0);
+ CHK(aw_obj_get_group(obj, 0, &group) == RES_OK);
+ CHK(!strcmp(group.name, "floor"));
CHK(group.face_id == 0);
CHK(group.faces_count == 1);
- CHK(aw_obj_mtl_get(obj, 0, &mtl) == RES_OK);
- CHK(strcmp(str_cget(&mtl.name), "floor") == 0);
+ CHK(aw_obj_get_mtl(obj, 0, &mtl) == RES_OK);
+ CHK(!strcmp(mtl.name, "floor"));
CHK(mtl.face_id == 0);
CHK(mtl.faces_count == 1);
- CHK(aw_obj_vertex_get(obj, 0, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, -1.01f, 0.f, 0.99f), 1.e-6f) == 1);
- CHK(aw_obj_vertex_get(obj, 1, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, 1.f, 0.f, 0.99f), 1.e-6f) == 1);
- CHK(aw_obj_vertex_get(obj, 2, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, 1.f, 0.f, -1.04f), 1.e-6f) == 1);
- CHK(aw_obj_vertex_get(obj, 3, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, -0.99f, 0.f, -1.04f), 1.e-6f) == 1);
-
- CHK(aw_obj_face_get(obj, 1, &face) == RES_OK);
+ CHK(aw_obj_get_vertex(obj, 0, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, -1.01, 0.0, 0.99), 1.e-6));
+ CHK(aw_obj_get_vertex(obj, 1, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, 1.0, 0.0, 0.99), 1.e-6));
+ CHK(aw_obj_get_vertex(obj, 2, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, 1.f, 0.0, -1.04), 1.e-6));
+ CHK(aw_obj_get_vertex(obj, 3, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, -0.99, 0.0, -1.04), 1.e-6));
+
+ CHK(aw_obj_get_face(obj, 1, &face) == RES_OK);
CHK(face.vertex_id == 4);
CHK(face.vertices_count == 4);
CHK(face.group_id == 1);
CHK(face.mtl_id == 1);
- CHK(aw_obj_group_get(obj, 1, &group) == RES_OK);
- CHK(strcmp(str_cget(&group.name), "ceiling") == 0);
+ CHK(aw_obj_get_group(obj, 1, &group) == RES_OK);
+ CHK(!strcmp(group.name, "ceiling"));
CHK(group.face_id == 1);
CHK(group.faces_count == 1);
- CHK(aw_obj_mtl_get(obj, 1, &mtl) == RES_OK);
- CHK(strcmp(str_cget(&mtl.name), "ceiling") == 0);
+ CHK(aw_obj_get_mtl(obj, 1, &mtl) == RES_OK);
+ CHK(!strcmp(mtl.name, "ceiling"));
CHK(mtl.face_id == 1);
CHK(mtl.faces_count == 1);
- CHK(aw_obj_vertex_get(obj, 4, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, -1.02f, 1.99f, 0.99f), 1.e-6f) == 1);
- CHK(aw_obj_vertex_get(obj, 5, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, -1.02f, 1.99f, -1.04f), 1.e-6f) == 1);
- CHK(aw_obj_vertex_get(obj, 6, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, 1.f, 1.99f, -1.04f), 1.e-6f) == 1);
- CHK(aw_obj_vertex_get(obj, 7, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, 1.f, 1.99f, 0.99f), 1.e-6f) == 1);
-
- CHK(aw_obj_face_get(obj, 4, &face) == RES_OK);
+ CHK(aw_obj_get_vertex(obj, 4, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, -1.02, 1.99, 0.99), 1.e-6));
+ CHK(aw_obj_get_vertex(obj, 5, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, -1.02, 1.99, -1.04), 1.e-6f));
+ CHK(aw_obj_get_vertex(obj, 6, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, 1.0, 1.99, -1.04), 1.e-6f));
+ CHK(aw_obj_get_vertex(obj, 7, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, 1.0, 1.99, 0.99), 1.e-6f));
+
+ CHK(aw_obj_get_face(obj, 4, &face) == RES_OK);
CHK(face.vertex_id == 16);
CHK(face.vertices_count == 4);
CHK(face.group_id == 4);
CHK(face.mtl_id == 4);
- CHK(aw_obj_group_get(obj, 4, &group) == RES_OK);
- CHK(strcmp(str_cget(&group.name), "left") == 0);
+ CHK(aw_obj_get_group(obj, 4, &group) == RES_OK);
+ CHK(!strcmp(group.name, "left"));
CHK(group.face_id == 4);
CHK(group.faces_count == 1);
- CHK(aw_obj_mtl_get(obj, 4, &mtl) == RES_OK);
- CHK(strcmp(str_cget(&mtl.name), "left") == 0);
+ CHK(aw_obj_get_mtl(obj, 4, &mtl) == RES_OK);
+ CHK(!strcmp(mtl.name, "left"));
CHK(mtl.face_id == 4);
CHK(mtl.faces_count == 1);
- CHK(aw_obj_vertex_get(obj, 16, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, -1.01f, 0.f, 0.99f), 1.e-6f) == 1);
- CHK(aw_obj_vertex_get(obj, 17, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, -0.99f, 0.f, -1.04f), 1.e-6f) == 1);
- CHK(aw_obj_vertex_get(obj, 18, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, -1.02f, 1.99f, -1.04f), 1.e-6f) == 1);
- CHK(aw_obj_vertex_get(obj, 19, &vertex) == RES_OK);
- CHK(f3_eq_eps(vertex.position, f3(tmp, -1.02f, 1.99f, 0.99f), 1.e-6f) == 1);
-
- CHK(aw_obj_named_group_release(&group) == RES_OK);
- CHK(aw_obj_named_group_release(&mtl) == RES_OK);
+ CHK(aw_obj_get_vertex(obj, 16, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, -1.01, 0.0, 0.99), 1.e-6));
+ CHK(aw_obj_get_vertex(obj, 17, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, -0.99, 0.0, -1.04), 1.e-6));
+ CHK(aw_obj_get_vertex(obj, 18, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, -1.02, 1.99, -1.04), 1.e-6));
+ CHK(aw_obj_get_vertex(obj, 19, &vertex) == RES_OK);
+ CHK(aw_obj_get_vertex_data(obj, &vertex, &vdata) == RES_OK);
+ CHK(d3_eq_eps(vdata.position, d3(tmp, -1.02, 1.99, 0.99), 1.e-6));
}
int
@@ -557,9 +549,9 @@ main(int argc, char** argv)
mem_init_proxy_allocator(&allocator, &mem_default_allocator);
- CHK(aw_obj_create(NULL, NULL, 1, NULL) == RES_BAD_ARG);
- CHK(aw_obj_create(NULL, &allocator, 1, NULL) == RES_BAD_ARG);
- CHK(aw_obj_create(NULL, NULL, 1, &obj) == RES_OK);
+ CHK(aw_obj_create(LOGGER_DEFAULT, NULL, 1, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_create(LOGGER_DEFAULT, &allocator, 1, NULL) == RES_BAD_ARG);
+ CHK(aw_obj_create(LOGGER_DEFAULT, NULL, 1, &obj) == RES_OK);
CHK(aw_obj_ref_get(NULL) == RES_BAD_ARG);
CHK(aw_obj_ref_get(obj) == RES_OK);
@@ -567,7 +559,7 @@ main(int argc, char** argv)
CHK(aw_obj_ref_put(obj) == RES_OK);
CHK(aw_obj_ref_put(obj) == RES_OK);
- CHK(aw_obj_create(LOGGER_DEFAULT, &allocator, 1, &obj) == RES_OK);
+ CHK(aw_obj_create(NULL, &allocator, 1, &obj) == RES_OK);
test_plane(obj);
test_squares(obj);