commit 9808a29fabc49121e470c8438405b08fd422ace1
parent 109941ccf0eb44d83fb12c250c79fd2e97882cb5
Author: vaplv <vaplv@free.fr>
Date: Mon, 14 Jul 2014 16:56:41 +0200
Test the mtl loader
Diffstat:
| M | src/aw.h | | | 31 | +++++++++++++++++++++++++++++++ |
| M | src/aw_mtl.c | | | 79 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ |
| M | src/test_aw_mtl.c | | | 87 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 167 insertions(+), 30 deletions(-)
diff --git a/src/aw.h b/src/aw.h
@@ -26,6 +26,11 @@ enum aw_result {
AW_OK
};
+enum aw_color_space {
+ AW_COLOR_RGB,
+ AW_COLOR_XYZ
+};
+
struct aw_obj_desc {
size_t faces_count;
size_t groups_count;
@@ -66,6 +71,21 @@ struct aw_obj_vertex {
float texcoord[3];
};
+struct aw_color {
+ float value[3];
+ enum aw_color_space color_space;
+};
+
+struct aw_material {
+ 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;
+};
+
struct aw_obj;
struct aw_mtl;
struct mem_allocator;
@@ -149,6 +169,17 @@ aw_mtl_load
(struct aw_mtl* mtl,
const char* filename);
+AW_API enum aw_result
+aw_mtl_materials_count_get
+ (struct aw_mtl* mtl,
+ size_t* materials_count);
+
+AW_API enum aw_result
+aw_mtl_material_get
+ (struct aw_mtl* mtl,
+ const size_t imaterial,
+ struct aw_material* material);
+
END_DECLS
#endif /* AW_H */
diff --git a/src/aw_mtl.c b/src/aw_mtl.c
@@ -11,22 +11,6 @@
#include <float.h>
/*******************************************************************************
- * Color helper data structure
- ******************************************************************************/
-struct color {
- float value[3];
- char is_CIEXYZ; /* Define if value is encoded in the CIE XYZ color space */
-};
-
-static FINLINE void
-color_copy(struct color* dst, const struct color* src)
-{
- ASSERT(dst && src);
- f3_set(dst->value, src->value);
- dst->is_CIEXYZ = src->is_CIEXYZ;
-}
-
-/*******************************************************************************
* Map helper data structure
******************************************************************************/
enum map_type {
@@ -115,10 +99,10 @@ map_copy_and_release(struct map* dst, struct map* src)
******************************************************************************/
struct material {
struct str name;
- struct color ambient;
- struct color diffuse;
- struct color specular;
- struct color transmission;
+ struct aw_color ambient;
+ struct aw_color diffuse;
+ struct aw_color specular;
+ struct aw_color transmission;
float specexp;
float refraction_id;
size_t illumination; /* Illumination model identifier */
@@ -157,10 +141,10 @@ static FINLINE void
material_copy_pod__(struct material* dst, const struct material* src)
{
ASSERT(dst && src);
- color_copy(&dst->ambient, &src->ambient);
- color_copy(&dst->diffuse, &src->diffuse);
- color_copy(&dst->specular, &src->specular);
- color_copy(&dst->transmission, &src->transmission);
+ dst->ambient = src->ambient;
+ dst->diffuse = src->diffuse;
+ dst->specular = src->specular;
+ dst->transmission = src->transmission;
dst->specexp = src->specexp;
dst->refraction_id = src->refraction_id;
dst->illumination = src->illumination;
@@ -252,7 +236,7 @@ parse_newmtl(struct aw_mtl* mtl, char** word_tk)
}
static enum aw_result
-parse_color(struct color* col, char** word_tk)
+parse_color(struct aw_color* col, char** word_tk)
{
char* word;
enum aw_result res = AW_OK;
@@ -267,8 +251,9 @@ parse_color(struct color* col, char** word_tk)
return AW_BAD_ARGUMENT;
}
- col->is_CIEXYZ = strcmp(word, "xyz") == 0;
- if(col->is_CIEXYZ && !(word = strtok_r(NULL, " ", word_tk)))
+ col->color_space = strcmp(word, "xyz") == 0 ? AW_COLOR_XYZ : AW_COLOR_RGB;
+ if(col->color_space == AW_COLOR_XYZ
+ && !(word = strtok_r(NULL, " ", word_tk)))
return AW_BAD_ARGUMENT;
if(AW_OK != (res = string_to_float(word, &col->value[0])))
@@ -417,7 +402,7 @@ parse_mtl_file(struct aw_mtl* mtl, const char* path, char* content)
while(line) {
char* word, *word_tk;
word = strtok_r(line, " ", &word_tk);
- while(word) {
+ if(word) {
if(!strcmp(word, "newmtl")) { /* Material name declaration */
res = parse_newmtl(mtl, &word_tk);
} else if(mtl->newmtl == NULL) {
@@ -435,7 +420,7 @@ parse_mtl_file(struct aw_mtl* mtl, const char* path, char* content)
(&mtl->newmtl->specexp, 1, 1, 0.f, FLT_MAX, 0.f, &word_tk);
} else if(!strcmp(word, "Ni")) { /* Refraction index */
res = parse_floatX
- (&mtl->newmtl->refraction_id, 1, 1, 0.001f, 10.f, 0.f, &word_tk);
+ (&mtl->newmtl->refraction_id, 1, 1, 0.001f, 10.f, 0.001f, &word_tk);
} else if(!strcmp(word, "illum")) { /* Illumination model */
res = parse_size_t(&mtl->newmtl->illumination, 0, 10, &word_tk);
} else if(!strcmp(word, "map_Ka")) { /* Ambient texture */
@@ -452,10 +437,15 @@ parse_mtl_file(struct aw_mtl* mtl, const char* path, char* content)
res = AW_OK;
fprintf(stderr, "%s:%lu: warning: ignored or malformed directive %s\n",
path, iline, word);
+ while((word = strtok_r(NULL, " ", &word_tk)));
}
if(res != AW_OK)
goto error;
- word = strtok_r(NULL, " ", &word_tk);
+ if((word = strtok_r(NULL, " ", &word_tk))) {
+ fprintf(stderr, "%s:%lu: unexpected directive %s\n", path, iline, word);
+ res = AW_BAD_ARGUMENT;
+ goto error;
+ }
}
line = strtok_r(NULL, "\n", &line_tk);
++iline;
@@ -567,3 +557,32 @@ error:
goto exit;
}
+enum aw_result
+aw_mtl_materials_count_get(struct aw_mtl* mtl, size_t* nmtls)
+{
+ if(!mtl || !nmtls)
+ return AW_BAD_ARGUMENT;
+ *nmtls = darray_material_size_get(&mtl->materials);
+ return AW_OK;
+}
+
+enum aw_result
+aw_mtl_material_get
+ (struct aw_mtl* mtl,
+ const size_t imaterial,
+ struct aw_material* material)
+{
+ const struct material* mtr;
+ if(!mtl || !material || imaterial>=darray_material_size_get(&mtl->materials))
+ return AW_BAD_ARGUMENT;
+ mtr = darray_material_cdata_get(&mtl->materials) + imaterial;
+ material->name = str_cget(&mtr->name);
+ material->ambient = mtr->ambient;
+ material->diffuse = mtr->diffuse;
+ material->specular = mtr->specular;
+ material->transmission = mtr->transmission;
+ material->specular_exponent = mtr->specexp;
+ material->refraction_index = mtr->refraction_id;
+ return AW_OK;
+}
+
diff --git a/src/test_aw_mtl.c b/src/test_aw_mtl.c
@@ -1,6 +1,90 @@
#include "aw.h"
+
+#include <rsys/float3.h>
#include <rsys/mem_allocator.h>
+#include <string.h>
+
+static void
+test_common(struct aw_mtl* mtl)
+{
+ static const char* mtl_common =
+ "newmtl my_mtl\n"
+ "\n"
+ "Ka 0.0435 0.0436 0.0437\n"
+ "Kd 0.1086 0.1087 0.1088\n"
+ "Ks 0 0 0\n"
+ "Tf xyz 0.987 0.988 0.989\n"
+ "illum 6\n"
+ "d -halo 0.66\n"
+ "Ns 10.0\n"
+ "sharpness 60\n"
+ "Ni 1.19713\n"
+ "\n"
+ "map_Ka -s 1 1 1 -o 0 0 0 -mm 0 1 chrome.mpc\n"
+ "map_Kd -s 1 1 1 -o 0 0 0 -mm 0 1 chrome.mpc\n"
+ "map_Ks -s 1 1 1 -o 0 0 0 -mm 0 1 chrome.mpc\n"
+ "map_Ns -s 1 1 1 -o 0 0 0 -mm 0 1 wisp.mps\n"
+ "map_d -s 1 1 1 -o 0 0 0 -mm 0 1 wisp.mps\n"
+ "disp -s 1 1 .5 wisp.mps\n"
+ "decal -s 1 1 1 -o 0 0 0 -mm 0 1 sand.mps\n"
+ "bump -s 1 1 1 -o 0 0 0 -bm 1 sand.mpb\n"
+ "\n"
+ "refl -type sphere -mm 0 1 clouds.mpc\n";
+ FILE* file;
+ size_t nmtls;
+ float tmp[3];
+ struct aw_material mtr;
+
+ NCHECK(mtl, NULL);
+
+ file = fopen("test_mtl_common.mtl", "w");
+ NCHECK(file, NULL);
+ fwrite(mtl_common, sizeof(char), strlen(mtl_common), file);
+ fclose(file);
+
+ CHECK(aw_mtl_load(NULL, NULL), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_load(mtl, NULL), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_load(NULL, "test_mtl_common.mtl"), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_load(mtl, "test_mtl_common.mtl"), AW_OK);
+
+ CHECK(aw_mtl_materials_count_get(NULL, NULL), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_materials_count_get(mtl, NULL), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_materials_count_get(NULL, &nmtls), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_materials_count_get(mtl, &nmtls), AW_OK);
+
+ CHECK(nmtls, 1);
+
+ CHECK(aw_mtl_material_get(NULL, SIZE_MAX, NULL), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_material_get(mtl, SIZE_MAX, NULL), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_material_get(NULL, 0, NULL), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_material_get(mtl, 0, NULL), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_material_get(NULL, SIZE_MAX, &mtr), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_material_get(mtl, SIZE_MAX, &mtr), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_material_get(NULL, 0, &mtr), AW_BAD_ARGUMENT);
+ CHECK(aw_mtl_material_get(mtl, 0, &mtr), AW_OK);
+
+ CHECK(strcmp(mtr.name, "my_mtl"), 0);
+ CHECK(mtr.ambient.color_space, AW_COLOR_RGB);
+ f3(tmp, 0.0435f, 0.0436f, 0.0437f);
+ CHECK(f3_eq(mtr.ambient.value, tmp), 1);
+
+ CHECK(mtr.diffuse.color_space, AW_COLOR_RGB);
+ f3(tmp, 0.1086f, 0.1087f, 0.1088f);
+ CHECK(f3_eq(mtr.diffuse.value, tmp), 1);
+
+ CHECK(mtr.specular.color_space, AW_COLOR_RGB);
+ f3_splat(tmp, 0.f);
+ CHECK(f3_eq(mtr.specular.value, tmp), 1);
+
+ CHECK(mtr.transmission.color_space, AW_COLOR_XYZ);
+ f3(tmp, 0.987f, 0.988f, 0.989f);
+ CHECK(f3_eq(mtr.transmission.value, tmp), 1);
+
+ CHECK(mtr.specular_exponent, 10.f);
+ CHECK(mtr.refraction_index, 1.19713f);
+}
+
int
main(int argc, char** argv)
{
@@ -21,6 +105,9 @@ main(int argc, char** argv)
CHECK(aw_mtl_ref_put(mtl), AW_OK);
CHECK(aw_mtl_create(&allocator, &mtl), AW_OK);
+
+ test_common(mtl);
+
CHECK(aw_mtl_ref_put(mtl), AW_OK);
if(MEM_ALLOCATED_SIZE(&allocator)) {