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:
| M | src/obj.c | | | 118 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
| M | src/obj.h | | | 13 | +++++++++++++ |
| M | src/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);