loader_aw

Load OBJ/MTL file formats
git clone git://git.meso-star.fr/loader_aw.git
Log | Files | Refs | README | LICENSE

commit 9808a29fabc49121e470c8438405b08fd422ace1
parent 109941ccf0eb44d83fb12c250c79fd2e97882cb5
Author: vaplv <vaplv@free.fr>
Date:   Mon, 14 Jul 2014 16:56:41 +0200

Test the mtl loader

Diffstat:
Msrc/aw.h | 31+++++++++++++++++++++++++++++++
Msrc/aw_mtl.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Msrc/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)) {