loader_aw

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

commit 109941ccf0eb44d83fb12c250c79fd2e97882cb5
parent 9c19d9a02bf07a4248d90e6ffa6cb19b9f1df4f7
Author: vaplv <vaplv@free.fr>
Date:   Sun, 13 Jul 2014 17:12:59 +0200

Parse the mm, imchan, o, s, t, bm and texres map options

Diffstat:
Msrc/aw.c | 38++++++++++++++++++++++++++++++++++++++
Msrc/aw_c.h | 10++++++++++
Msrc/aw_mtl.c | 104++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Msrc/aw_obj.c | 59+++++++++++++++++++----------------------------------------
4 files changed, 136 insertions(+), 75 deletions(-)

diff --git a/src/aw.c b/src/aw.c @@ -1,5 +1,8 @@ +#define _POSIX_C_SOURCE 200112L /* strtok_r support */ + #include "aw_c.h" #include <rsys/mem_allocator.h> +#include <string.h> /******************************************************************************* * Local functions @@ -45,3 +48,38 @@ error: } goto exit; } + +enum aw_result +parse_floatX + (float* f, + 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) +{ + size_t i; + ASSERT(f && count_min <= count_max && range_min <= range_max && tk_ctxt); + ASSERT(default_value >= range_min && default_value <= range_max); + + FOR_EACH(i, 0, count_max) { + char* real; + enum aw_result res; + if(NULL == (real = strtok_r(NULL, " ", tk_ctxt))) + break; + res = string_to_float(real, f + i); + if(res != AW_OK) + return res; + if(f[i] < range_min || f[i] > range_max) + return AW_BAD_ARGUMENT; + } + if(i < count_min) + return AW_BAD_ARGUMENT; + + FOR_EACH(i, i, count_max) + f[i] = default_value; + + return AW_OK; +} + diff --git a/src/aw_c.h b/src/aw_c.h @@ -38,5 +38,15 @@ read_file const char* filename, char** file); +extern LOCAL_SYM enum aw_result +parse_floatX + (float* f, + 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); + #endif /* AW_C_H */ diff --git a/src/aw_mtl.c b/src/aw_mtl.c @@ -29,6 +29,12 @@ color_copy(struct color* dst, const struct color* src) /******************************************************************************* * Map helper data structure ******************************************************************************/ +enum map_type { + MAP_COMMON = BIT(0), + MAP_SCALAR = BIT(1), + MAP_BUMP = MAP_SCALAR | BIT(2) +}; + enum map_flag { MAP_BLEND_U = BIT(0), MAP_BLEND_V = BIT(1), @@ -55,6 +61,7 @@ struct map { float scale[3]; /* Texcoord scale */ float turbulence[3]; /* Texcoord turbulence */ size_t resolution; + float bump_multiplier; }; static FINLINE void @@ -84,6 +91,7 @@ map_copy_pod__(struct map* dst, const struct map* src) f3_set(dst->scale, src->scale); f3_set(dst->turbulence, src->turbulence); dst->resolution = src->resolution; + dst->bump_multiplier = src->bump_multiplier; } static FINLINE int @@ -111,13 +119,13 @@ struct material { struct color diffuse; struct color specular; struct color transmission; - float specular_exp; + float specexp; float refraction_id; size_t illumination; /* Illumination model identifier */ struct map ambient_map; struct map diffuse_map; struct map specular_map; - struct map specular_exp_map; + struct map specexp_map; struct map bump_map; }; @@ -129,7 +137,7 @@ material_init(struct mem_allocator* allocator, struct material* mtl) map_init(allocator, &mtl->ambient_map); map_init(allocator, &mtl->diffuse_map); map_init(allocator, &mtl->specular_map); - map_init(allocator, &mtl->specular_exp_map); + map_init(allocator, &mtl->specexp_map); map_init(allocator, &mtl->bump_map); } @@ -141,7 +149,7 @@ material_release(struct material* mtl) map_release(&mtl->ambient_map); map_release(&mtl->diffuse_map); map_release(&mtl->specular_map); - map_release(&mtl->specular_exp_map); + map_release(&mtl->specexp_map); map_release(&mtl->bump_map); } @@ -153,7 +161,7 @@ material_copy_pod__(struct material* dst, const struct material* src) color_copy(&dst->diffuse, &src->diffuse); color_copy(&dst->specular, &src->specular); color_copy(&dst->transmission, &src->transmission); - dst->specular_exp = src->specular_exp; + dst->specexp = src->specexp; dst->refraction_id = src->refraction_id; dst->illumination = src->illumination; } @@ -168,7 +176,7 @@ material_copy(struct material* dst, const struct material* src) return -1; if(map_copy(&dst->specular_map, &src->specular_map)) return -1; - if(map_copy(&dst->specular_exp_map, &src->specular_exp_map)) + if(map_copy(&dst->specexp_map, &src->specexp_map)) return -1; if(map_copy(&dst->bump_map, &src->bump_map)) return -1; @@ -187,7 +195,7 @@ material_copy_and_release(struct material* dst, struct material* src) return -1; if(map_copy_and_release(&dst->specular_map, &src->specular_map)) return -1; - if(map_copy_and_release(&dst->specular_exp_map, &src->specular_exp_map)) + if(map_copy_and_release(&dst->specexp_map, &src->specexp_map)) return -1; if(map_copy_and_release(&dst->bump_map, &src->bump_map)) return -1; @@ -282,22 +290,6 @@ parse_color(struct color* col, char** word_tk) } static INLINE enum aw_result -parse_float - (float* f, const float range_min, const float range_max, char** word_tk) -{ - char* word; - enum aw_result res = AW_OK; - ASSERT(f && word_tk && range_min < range_max); - - word = strtok_r(NULL, "\n", word_tk); - if(AW_OK != (res = string_to_float(word, f))) - return res; - if(range_min > *f || range_max < *f) - return AW_BAD_ARGUMENT; - return AW_OK; -} - -static INLINE enum aw_result parse_size_t (size_t* s, const size_t range_min, const size_t range_max, char** word_tk) { @@ -332,8 +324,37 @@ parse_bool_option return AW_OK; } +static FINLINE enum aw_result +parse_imfchan_option(enum map_channel* channel, char** tk_ctxt) +{ + char* word; + ASSERT(channel && tk_ctxt); + word = strtok_r(NULL, " ", tk_ctxt); + if(!word) + return AW_BAD_ARGUMENT; + if(!strcmp(word, "r")) { + *channel = MAP_CHANNEL_RED; + } else if(!strcmp(word, "g")) { + *channel = MAP_CHANNEL_GREEN; + } else if(!strcmp(word, "b")) { + *channel = MAP_CHANNEL_BLUE; + } else if(!strcmp(word, "m")) { + *channel = MAP_CHANNEL_MATTE; + } else if(!strcmp(word, "l")) { + *channel = MAP_CHANNEL_LUMINANCE; + } else if(!strcmp(word, "z")) { + *channel = MAP_CHANNEL_DEPTH; + } else { + return AW_BAD_ARGUMENT; + } + return AW_OK; +} + static enum aw_result -parse_map(struct map* map, char** tk_ctxt) +parse_map + (struct map* map, + const enum map_type type, + char** tk_ctxt) { char* word; ASSERT(map && tk_ctxt); @@ -350,15 +371,26 @@ parse_map(struct map* map, char** tk_ctxt) res = parse_bool_option(&map->mask_options, MAP_COLOR_CORRECTION,tk_ctxt); } else if(!strcmp(word, "-clamp")) { res = parse_bool_option(&map->mask_options, MAP_CLAMP, tk_ctxt); - } else if(!strcmp(word, "-imfchan")) { /* Scalar texture channel */ - /* res = parse_imfchan(&map->channel, tk_ctxt); */ + } else if(!strcmp(word, "-imfchan") && (type & MAP_SCALAR)) { + res = parse_imfchan_option(&map->channel, tk_ctxt); } else if(!strcmp(word, "-mm")) { /* Image bias and scale */ - /* res = parse_float TODO */ + res = parse_floatX + (&map->texture_bias, 1, 1, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt); + if(res == AW_OK) { + res = parse_floatX + (&map->texture_scale, 1, 1, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt); + } } else if(!strcmp(word, "-o")) { /* Texcoord offset */ + res = parse_floatX(map->origin, 1, 3, -FLT_MAX, FLT_MAX, 0.f, tk_ctxt); } else if(!strcmp(word, "-s")) { /* Texcoord scale */ + res = parse_floatX(map->scale, 1, 3, -FLT_MAX, FLT_MAX, 1.f, tk_ctxt); } else if(!strcmp(word, "-t")) { /* Texcoord turbulence */ + res = parse_floatX(map->turbulence, 1, 3,-FLT_MAX, FLT_MAX, 0.f, tk_ctxt); } else if(!strcmp(word, "-texres")) { /* Texture resolution */ - } else if(!strcmp(word, "-bm")) { /* Bump multiplier */ + 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 { do { if(str_append(&map->filename, word)) @@ -399,21 +431,23 @@ parse_mtl_file(struct aw_mtl* mtl, const char* path, char* content) } else if(!strcmp(word, "Tf")) { /* Transimission filter */ res = parse_color(&mtl->newmtl->transmission, &word_tk); } else if(!strcmp(word, "Ns")) { /* Specular exponent */ - res = parse_float(&mtl->newmtl->specular_exp, 0.f, FLT_MAX, &word_tk); + res = parse_floatX + (&mtl->newmtl->specexp, 1, 1, 0.f, FLT_MAX, 0.f, &word_tk); } else if(!strcmp(word, "Ni")) { /* Refraction index */ - res = parse_float(&mtl->newmtl->refraction_id, 0.001f, 10.f, &word_tk); + res = parse_floatX + (&mtl->newmtl->refraction_id, 1, 1, 0.001f, 10.f, 0.f, &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 */ - res = parse_map(&mtl->newmtl->ambient_map, &word_tk); + 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, &word_tk); + 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, &word_tk); + 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_exp_map, &word_tk); + res = parse_map(&mtl->newmtl->specexp_map, MAP_SCALAR, &word_tk); } else if(!strcmp(word, "bump")) { /* Bump map */ - res = parse_map(&mtl->newmtl->bump_map, &word_tk); + res = parse_map(&mtl->newmtl->bump_map, MAP_BUMP, &word_tk); } else { res = AW_OK; fprintf(stderr, "%s:%lu: warning: ignored or malformed directive %s\n", diff --git a/src/aw_obj.c b/src/aw_obj.c @@ -161,48 +161,27 @@ flush_smooth_group(struct aw_obj* obj) } static enum aw_result -parse_floatX - (char** word_tk, - const unsigned count_min, - const unsigned count_max, +parse_floatX_in_darray + (struct darray_float* darray, + const unsigned int count_min, + const unsigned int count_max, const float default_value, - struct darray_float* dst) + char** tk_ctxt) { - unsigned i; - enum aw_result res = AW_OK; - ASSERT(word_tk && dst && count_min <= count_max); - - FOR_EACH(i, 0, count_max) { - char* real; - float f; - if(NULL == (real = strtok_r(NULL, " ", word_tk))) - break; - res = string_to_float(real, &f); - if(res != AW_OK) - goto error; - if(darray_float_push_back(dst, &f)) { - res = AW_MEMORY_ERROR; - goto error; - } - } - if(i < count_min) { - res = AW_BAD_ARGUMENT; - goto error; - } + enum aw_result res; + size_t i; + ASSERT(darray); - FOR_EACH(i, i, count_max) { - if(darray_float_push_back(dst, &default_value)) { - res = AW_MEMORY_ERROR; - goto error; - } - } + i = darray_float_size_get(darray); + if(darray_float_resize(darray, i + count_max)) + return AW_MEMORY_ERROR; -exit: + res = parse_floatX + (darray_float_data_get(darray) + i, + count_min, count_max, -FLT_MAX, FLT_MAX, default_value, tk_ctxt); + if(res != AW_OK) + darray_float_resize(darray, i); return res; -error: - FOR_EACH_REVERSE(i, i, 0) - darray_float_pop_back(dst); - goto exit; } static enum aw_result @@ -438,11 +417,11 @@ parse_obj_file(struct aw_obj* obj, const char* path, char* content) if(word[0] == '#') { /* Comment */ break; } else if(!strcmp(word, "v")) { /* Vertex position */ - res = parse_floatX(&word_tk, 3, 4, 1.f, &obj->positions); + res = parse_floatX_in_darray(&obj->positions, 3, 4, 1.f, &word_tk); } else if(!strcmp(word, "vn")) { /* Vertex normal */ - res = parse_floatX(&word_tk, 3, 3, 0.f, &obj->normals); + res = parse_floatX_in_darray(&obj->normals, 3, 3, 0.f, &word_tk); } else if(!strcmp(word, "vt")) { /* Vertex texture coordinates */ - res = parse_floatX(&word_tk, 1, 3, 0.f, &obj->texcoords); + 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 */