loader_aw

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

commit 0eb797de96c8724ee10d5e5290768b2d8e9108d0
parent 487f04b14be123d9232e20245b183e8973901f74
Author: vaplv <vaplv@free.fr>
Date:   Sat,  5 Jul 2014 15:04:03 +0200

Handle multiple groups declaration on the same line

Diffstat:
Msrc/obj.c | 118++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/obj.h | 13+++++++++++++
Msrc/test_obj.c | 25+++++++++++++++++++++++++
3 files changed, 119 insertions(+), 37 deletions(-)

diff --git a/src/obj.c b/src/obj.c @@ -16,6 +16,9 @@ struct vertex { struct face { size_t ivertex; /* Index toward the first vertex */ size_t nvertices; /* Vertex count */ + size_t igroup; /* Index toward the face group */ + size_t ismooth_group; /* Index toward the face smooth group */ + size_t imtl; /* Index toward the face material */ }; struct named_group { @@ -108,6 +111,8 @@ struct obj { struct darray_named_group usemtls; struct darray_mtllib mtllibs; + size_t igroups_active; /* Index toward the first active group */ + ref_T ref; struct mem_allocator* allocator; }; @@ -142,35 +147,52 @@ string_to_size_t(const char* str, size_t* i) } static FINLINE void -flush_named_group - (struct darray_named_group* groups, const struct darray_face* faces) +flush_groups(struct obj* obj) { - struct named_group* grp; size_t nfaces, ngrps; - ASSERT(groups && faces); - if(0 == (nfaces = darray_face_size_get(faces))) + ASSERT(obj); + if(0 == (nfaces = darray_face_size_get(&obj->faces))) return; - if( 0 == (ngrps = darray_named_group_size_get(groups))) + if(0 == (ngrps = darray_named_group_size_get(&obj->groups))) return; - grp = darray_named_group_data_get(groups) + (ngrps - 1); - ASSERT(grp->iface < nfaces); - grp->nfaces =nfaces - grp->iface; + if(obj->igroups_active >= ngrps) + return; + FOR_EACH(obj->igroups_active, obj->igroups_active, ngrps) { + struct named_group* grp; + grp = darray_named_group_data_get(&obj->groups) + obj->igroups_active; + ASSERT(grp->iface < nfaces); + grp->nfaces = nfaces - grp->iface; + } +} + +static FINLINE void +flush_usemtl(struct obj* obj) +{ + 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; + mtl = darray_named_group_data_get(&obj->usemtls) + (ngrps - 1); + ASSERT(mtl->iface < nfaces); + mtl->nfaces = nfaces - mtl->iface; } static FINLINE void -flush_smooth_group - (struct darray_smooth_group* groups, const struct darray_face* faces) +flush_smooth_group(struct obj* obj) { struct smooth_group* grp; size_t nfaces, ngrps; - ASSERT(groups && faces); - if(0 == (nfaces = darray_face_size_get(faces))) + ASSERT(obj); + if(0 == (nfaces = darray_face_size_get(&obj->faces))) return; - if( 0 == (ngrps = darray_smooth_group_size_get(groups))) + if(0 == (ngrps = darray_smooth_group_size_get(&obj->smooth_groups))) return; - grp = darray_smooth_group_data_get(groups) + (ngrps - 1); + grp = darray_smooth_group_data_get(&obj->smooth_groups) + (ngrps - 1); ASSERT(grp->iface < nfaces); - grp->nfaces =nfaces - grp->iface; + grp->nfaces = nfaces - grp->iface; } static enum obj_result @@ -228,6 +250,9 @@ parse_face(struct obj* obj, char** word_tk) face.ivertex = darray_vertex_size_get(&obj->vertices); face.nvertices = 0; + face.igroup = darray_named_group_size_get(&obj->groups) - 1; + face.ismooth_group = darray_smooth_group_size_get(&obj->smooth_groups) - 1; + face.imtl = darray_named_group_size_get(&obj->usemtls) - 1; while((word = strtok_r(NULL, " ", word_tk))) { char* id, *id_tk; struct vertex vert; @@ -270,12 +295,11 @@ static enum obj_result parse_group(struct obj* obj, char** word_tk) { char* word; - struct named_group* grp = NULL; - size_t ngrps; + size_t ngrps = 0, igrp = 0; enum obj_result res = OBJ_OK; ASSERT(obj && word_tk); - flush_named_group(&obj->groups, &obj->faces); + flush_groups(obj); word = strtok_r(NULL, " ", word_tk); if(!word) { @@ -283,22 +307,29 @@ parse_group(struct obj* obj, char** word_tk) goto error; } #define CALL(Func) { if(Func) { res = OBJ_MEMORY_ERROR; goto error; } }(void)0 - ngrps = darray_named_group_size_get(&obj->groups); - CALL(darray_named_group_resize(&obj->groups, ngrps + 1)); - grp = darray_named_group_data_get(&obj->groups) + ngrps; - CALL(str_set(&grp->name, word)); - while((word = strtok_r(NULL, " ", word_tk))) { - CALL(str_append_char(&grp->name, ' ')); - CALL(str_append(&grp->name, word)); - } - #undef CALL - grp->iface = darray_face_size_get(&obj->faces); - grp->nfaces = 0; + ngrps = igrp = darray_named_group_size_get(&obj->groups); + obj->igroups_active = ngrps; + do { + struct named_group* grp = NULL; + if(darray_named_group_resize(&obj->groups, igrp + 1)) { + res = OBJ_MEMORY_ERROR; + goto error; + } + grp = darray_named_group_data_get(&obj->groups) + ngrps; + ++igrp; + if(str_set(&grp->name, word)) { + res = OBJ_MEMORY_ERROR; + goto error; + } + grp->iface = darray_face_size_get(&obj->faces); + grp->nfaces = 0; + } while((word = strtok_r(NULL, " ", word_tk))); + exit: return res; error: - if(grp) - darray_named_group_pop_back(&obj->groups); + if(igrp != ngrps) + CHECK(darray_named_group_resize(&obj->groups, ngrps), 0); goto exit; } @@ -311,7 +342,7 @@ parse_smooth_group(struct obj* obj, char** word_tk) size_t i; ASSERT(obj && word_tk); - flush_smooth_group(&obj->smooth_groups, &obj->faces); + flush_smooth_group(obj); word = strtok_r(NULL, " ", word_tk); if(!strcmp(word, "off")) { @@ -379,7 +410,7 @@ parse_usemtl(struct obj* obj, char** word_tk) enum obj_result res = OBJ_OK; ASSERT(obj && word_tk); - flush_named_group(&obj->usemtls, &obj->faces); + flush_usemtl(obj); word= strtok_r(NULL, " ", word_tk); if(!word_tk) { @@ -451,9 +482,9 @@ parse_file(struct obj* obj, const char* path, char* content) line = strtok_r(NULL, "\n", &line_tk); ++iline; } - flush_named_group(&obj->groups, &obj->faces); - flush_named_group(&obj->usemtls, &obj->faces); - flush_smooth_group(&obj->smooth_groups, &obj->faces); + flush_groups(obj); + flush_smooth_group(obj); + flush_usemtl(obj); exit: return res; error: @@ -474,6 +505,7 @@ obj_clear(struct obj* obj) darray_named_group_clear(&obj->usemtls); darray_smooth_group_clear(&obj->smooth_groups); darray_mtllib_clear(&obj->mtllibs); + obj->igroups_active = 0; } static void @@ -607,4 +639,16 @@ error: goto exit; } +enum obj_result +obj_desc_get(struct obj* obj, struct obj_desc* desc) +{ + if(!obj || !desc) + return OBJ_BAD_ARGUMENT; + desc->faces_count = darray_face_size_get(&obj->faces); + desc->groups_count = darray_named_group_size_get(&obj->groups); + desc->smooth_groups_count = darray_smooth_group_size_get(&obj->smooth_groups); + desc->usemtls_count = darray_named_group_size_get(&obj->usemtls); + desc->mtllibs_count = darray_mtllib_size_get(&obj->mtllibs); + return OBJ_OK; +} diff --git a/src/obj.h b/src/obj.h @@ -24,6 +24,14 @@ enum obj_result { OBJ_OK }; +struct obj_desc { + size_t faces_count; + size_t groups_count; + size_t smooth_groups_count; + size_t usemtls_count; + size_t mtllibs_count; +}; + struct obj; struct mem_allocator; @@ -47,6 +55,11 @@ obj_load (struct obj* obj, const char* filename); +OBJ_API enum obj_result +obj_desc_get + (struct obj* obj, + struct obj_desc* desc); + END_DECLS #endif /* OBJ_H */ diff --git a/src/test_obj.c b/src/test_obj.c @@ -79,6 +79,7 @@ int main(int argc, char** argv) { struct mem_allocator allocator; + struct obj_desc desc; struct obj* obj; FILE* file; (void)argc, (void)argv; @@ -117,8 +118,32 @@ main(int argc, char** argv) CHECK(obj_load(NULL, "test_obj_cube.obj"), OBJ_BAD_ARGUMENT); CHECK(obj_load(obj, "none.obj"), OBJ_IO_ERROR); CHECK(obj_load(obj, "test_obj_plane.obj"), OBJ_OK); + + CHECK(obj_desc_get(NULL, NULL), OBJ_BAD_ARGUMENT); + CHECK(obj_desc_get(obj, NULL), OBJ_BAD_ARGUMENT); + CHECK(obj_desc_get(NULL, &desc), OBJ_BAD_ARGUMENT); + CHECK(obj_desc_get(obj, &desc), OBJ_OK); + CHECK(desc.faces_count, 1); + CHECK(desc.groups_count, 0); + CHECK(desc.smooth_groups_count, 0); + CHECK(desc.usemtls_count, 1); + CHECK(desc.mtllibs_count, 1); + CHECK(obj_load(obj, "test_obj_squares.obj"), OBJ_OK); + CHECK(obj_desc_get(obj, &desc), OBJ_OK); + CHECK(desc.faces_count, 2); + CHECK(desc.groups_count, 1); + CHECK(desc.smooth_groups_count, 1); + CHECK(desc.usemtls_count, 0); + CHECK(desc.mtllibs_count, 0); + CHECK(obj_load(obj, "test_obj_cube.obj"), OBJ_OK); + CHECK(obj_desc_get(obj, &desc), OBJ_OK); + CHECK(desc.faces_count, 6); + CHECK(desc.groups_count, 6); + CHECK(desc.smooth_groups_count, 0); + CHECK(desc.usemtls_count, 6); + CHECK(desc.mtllibs_count, 1); CHECK(obj_ref_put(obj), OBJ_OK);