loader_aw

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

commit 95c780728ce0366819c1ba9f7fab3c9064c84663
parent 0eb797de96c8724ee10d5e5290768b2d8e9108d0
Author: vaplv <vaplv@free.fr>
Date:   Sat,  5 Jul 2014 15:29:30 +0200

Add and test the face getter

Diffstat:
Msrc/obj.c | 36+++++++++++++++++++-----------------
Msrc/obj.h | 16++++++++++++++++
Msrc/test_obj.c | 272+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
3 files changed, 204 insertions(+), 120 deletions(-)

diff --git a/src/obj.c b/src/obj.c @@ -13,14 +13,6 @@ struct vertex { size_t itexcoord; }; -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 { struct str name; size_t iface; /* Index toward the first face */ @@ -74,7 +66,7 @@ named_group_copy_and_release(struct named_group* dst, struct named_group* src) /* Generate the darray_face data structure */ #define DARRAY_NAME face -#define DARRAY_DATA struct face +#define DARRAY_DATA struct obj_face #include <rsys/dynamic_array.h> /* Generate the darray_named_group data structure */ @@ -243,16 +235,16 @@ error: static enum obj_result parse_face(struct obj* obj, char** word_tk) { - struct face face; + struct obj_face face; char* word; enum obj_result res = OBJ_OK; ASSERT(obj && 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; + face.vertex_id = darray_vertex_size_get(&obj->vertices); + face.vertices_count = 0; + face.group_id = darray_named_group_size_get(&obj->groups) - 1; + face.smooth_group_id = darray_smooth_group_size_get(&obj->smooth_groups) - 1; + face.mtl_id = darray_named_group_size_get(&obj->usemtls) - 1; while((word = strtok_r(NULL, " ", word_tk))) { char* id, *id_tk; struct vertex vert; @@ -275,7 +267,7 @@ parse_face(struct obj* obj, char** word_tk) res = OBJ_MEMORY_ERROR; goto error; } - ++face.nvertices; + ++face.vertices_count; } if(darray_face_push_back(&obj->faces, &face)) { @@ -286,7 +278,7 @@ parse_face(struct obj* obj, char** word_tk) exit: return res; error: - FOR_EACH_REVERSE(face.nvertices, face.nvertices, 0) + FOR_EACH_REVERSE(face.vertices_count, face.vertices_count, 0) darray_vertex_pop_back(&obj->vertices); goto exit; } @@ -652,3 +644,13 @@ obj_desc_get(struct obj* obj, struct obj_desc* desc) return OBJ_OK; } +enum obj_result +obj_face_get(const struct obj* obj, const size_t iface, struct obj_face* face) +{ + if(!obj || !face || iface >= darray_face_size_get(&obj->faces)) + return OBJ_BAD_ARGUMENT; + *face = darray_face_cdata_get(&obj->faces)[iface]; + return OBJ_OK; +} + + diff --git a/src/obj.h b/src/obj.h @@ -17,6 +17,8 @@ #define OBJ(Func) obj_##Func #endif +#define OBJ_ID_NONE ((size_t)(-1)) + enum obj_result { OBJ_BAD_ARGUMENT, OBJ_IO_ERROR, @@ -32,6 +34,14 @@ struct obj_desc { size_t mtllibs_count; }; +struct obj_face { + size_t vertex_id; /* Index of the first face vertex */ + size_t vertices_count; + size_t group_id; /* Index of the face group */ + size_t smooth_group_id; /* Index of the face smooth group */ + size_t mtl_id; /* Index of the face material */ +}; + struct obj; struct mem_allocator; @@ -60,6 +70,12 @@ obj_desc_get (struct obj* obj, struct obj_desc* desc); +OBJ_API enum obj_result +obj_face_get + (const struct obj* obj, + const size_t face_id, + struct obj_face* face); + END_DECLS #endif /* OBJ_H */ diff --git a/src/test_obj.c b/src/test_obj.c @@ -2,120 +2,39 @@ #include <rsys/mem_allocator.h> #include <string.h> -static const char* plane_obj = - "mtllib master.mtl" - "\n" - "v 0.0000 2.0000 0.0000\n" - "v 0.0000 0.0000 0.0000\n" - "v 2.0000 0.0000 0.0000\n" - "v 2.0000 2.0000 0.0000\n" - "vt 0.0000 1.0000 0.0000\n" - "vt 0.0000 0.0000 0.0000\n" - "vt 1.0000 0.0000 0.0000\n" - "vt 1.0000 1.0000 0.0000\n" - "# 4 vertices\n" - "\n" - "usemtl wood\n" - "f 1/1 2/2 3/3 4/4\n" - "# 1 element\n"; - - -static const char* squares_obj = - "v 0.000000 2.000000 0.000000\n" - "v 0.000000 0.000000 0.000000\n" - "v 2.000000 0.000000 0.000000\n" - "v 2.000000 2.000000 0.000000\n" - "v 4.000000 0.000000 -1.255298\n" - "v 4.000000 2.000000 -1.255298\n" - "vn 0.000000 0.000000 1.000000\n" - "vn 0.000000 0.000000 1.000000\n" - "vn 0.276597 0.000000 0.960986\n" - "vn 0.276597 0.000000 0.960986\n" - "vn 0.531611 0.000000 0.846988\n" - "vn 0.531611 0.000000 0.846988\n" - "# 6 vertices\n" - "\n" - "# 6 normals\n" - "\n" - "g all\n" - "s 1\n" - "f 1//1 2//2 3//3 4//4\n" - "f 4//4 3//3 5//5 6//6\n" - "# 2 elements\n"; - -static const char* cube_obj = - "# Cube with a different material applied to each of its faces\n" - "mtllib master.mtl\n" - "v 0.0000 2.0000 2.0000\n" - "v 0.0000 0.0000 2.0000\n" - "v 2.0000 0.0000 2.0000\n" - "v 2.0000 2.0000 2.0000\n" - "v 0.0000 2.0000 0.0000\n" - "v 0.0000 0.0000 0.0000\n" - "v 2.0000 0.0000 0.0000\n" - "v 2.0000 2.0000 0.0000\n" - "# 8 vertices\n" - "g front\n" - "usemtl red\n" - "f 1 2 3 4\n" - "g back\n" - "usemtl blue\n" - "f 8 7 6 5\n" - "g right\n" - "usemtl green\n" - "f 4 3 7 8\n" - "g top\n" - "usemtl gold\n" - "f 5 1 4 8\n" - "g left\n" - "usemtl orange\n" - "f 5 6 2 1\n" - "g bottom\n" - "usemtl purple\n" - "f 2 6 7 3\n" - "# 6 elements\n"; - -int -main(int argc, char** argv) +static void +test_plane(struct obj* obj) { - struct mem_allocator allocator; + static const char* plane_obj = + "mtllib master.mtl" + "\n" + "v 0.0000 2.0000 0.0000\n" + "v 0.0000 0.0000 0.0000\n" + "v 2.0000 0.0000 0.0000\n" + "v 2.0000 2.0000 0.0000\n" + "vt 0.0000 1.0000 0.0000\n" + "vt 0.0000 0.0000 0.0000\n" + "vt 1.0000 0.0000 0.0000\n" + "vt 1.0000 1.0000 0.0000\n" + "# 4 vertices\n" + "\n" + "usemtl wood\n" + "f 1/1 2/2 3/3 4/4\n" + "# 1 element\n"; struct obj_desc desc; - struct obj* obj; + struct obj_face face; FILE* file; - (void)argc, (void)argv; + + NCHECK(obj, NULL); file = fopen("test_obj_plane.obj", "w"); NCHECK(file, NULL); fwrite(plane_obj, sizeof(char), strlen(plane_obj), file); fclose(file); - file = fopen("test_obj_squares.obj", "w"); - NCHECK(file, NULL); - fwrite(squares_obj, sizeof(char), strlen(squares_obj), file); - fclose(file); - - file = fopen("test_obj_cube.obj", "w"); - NCHECK(file, NULL); - fwrite(cube_obj, sizeof(char), strlen(cube_obj), file); - fclose(file); - - mem_init_proxy_allocator(&allocator, &mem_default_allocator); - - CHECK(obj_create(NULL, NULL), OBJ_BAD_ARGUMENT); - CHECK(obj_create(&allocator, NULL), OBJ_BAD_ARGUMENT); - CHECK(obj_create(NULL, &obj), OBJ_OK); - - CHECK(obj_ref_get(NULL), OBJ_BAD_ARGUMENT); - CHECK(obj_ref_get(obj), OBJ_OK); - CHECK(obj_ref_put(NULL), OBJ_BAD_ARGUMENT); - CHECK(obj_ref_put(obj), OBJ_OK); - CHECK(obj_ref_put(obj), OBJ_OK); - - CHECK(obj_create(&allocator, &obj), OBJ_OK); - CHECK(obj_load(NULL, NULL), OBJ_BAD_ARGUMENT); CHECK(obj_load(obj, NULL), OBJ_BAD_ARGUMENT); - CHECK(obj_load(NULL, "test_obj_cube.obj"), OBJ_BAD_ARGUMENT); + CHECK(obj_load(NULL, "test_obj_plane.obj"), OBJ_BAD_ARGUMENT); CHECK(obj_load(obj, "none.obj"), OBJ_IO_ERROR); CHECK(obj_load(obj, "test_obj_plane.obj"), OBJ_OK); @@ -129,7 +48,58 @@ main(int argc, char** argv) CHECK(desc.usemtls_count, 1); CHECK(desc.mtllibs_count, 1); + CHECK(obj_face_get(NULL, SIZE_MAX, NULL), OBJ_BAD_ARGUMENT); + CHECK(obj_face_get(obj, SIZE_MAX, NULL), OBJ_BAD_ARGUMENT); + CHECK(obj_face_get(NULL, 0, NULL), OBJ_BAD_ARGUMENT); + CHECK(obj_face_get(obj, 0, NULL), OBJ_BAD_ARGUMENT); + CHECK(obj_face_get(NULL, SIZE_MAX, &face), OBJ_BAD_ARGUMENT); + CHECK(obj_face_get(obj, SIZE_MAX, &face), OBJ_BAD_ARGUMENT); + CHECK(obj_face_get(NULL, 0, &face), OBJ_BAD_ARGUMENT); + CHECK(obj_face_get(obj, 0, &face), OBJ_OK); + CHECK(face.vertex_id, 0); + CHECK(face.vertices_count, 4); + CHECK(face.group_id, OBJ_ID_NONE); + CHECK(face.smooth_group_id, OBJ_ID_NONE); + CHECK(face.mtl_id, 0); +} + +static void +test_squares(struct obj* obj) +{ + static const char* squares_obj = + "v 0.000000 2.000000 0.000000\n" + "v 0.000000 0.000000 0.000000\n" + "v 2.000000 0.000000 0.000000\n" + "v 2.000000 2.000000 0.000000\n" + "v 4.000000 0.000000 -1.255298\n" + "v 4.000000 2.000000 -1.255298\n" + "vn 0.000000 0.000000 1.000000\n" + "vn 0.000000 0.000000 1.000000\n" + "vn 0.276597 0.000000 0.960986\n" + "vn 0.276597 0.000000 0.960986\n" + "vn 0.531611 0.000000 0.846988\n" + "vn 0.531611 0.000000 0.846988\n" + "# 6 vertices\n" + "\n" + "# 6 normals\n" + "\n" + "g all\n" + "s 1\n" + "f 1//1 2//2 3//3 4//4\n" + "f 4//4 3//3 5//5 6//6\n" + "# 2 elements\n"; + struct obj_desc desc; + struct obj_face face; + FILE* file; + + NCHECK(obj, NULL); + + file = fopen("test_obj_squares.obj", "w"); + NCHECK(file, NULL); + fwrite(squares_obj, sizeof(char), strlen(squares_obj), file); + fclose(file); 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); @@ -137,7 +107,68 @@ main(int argc, char** argv) CHECK(desc.usemtls_count, 0); CHECK(desc.mtllibs_count, 0); + CHECK(obj_face_get(obj, 0, &face), OBJ_OK); + CHECK(face.vertex_id, 0); + CHECK(face.vertices_count, 4); + CHECK(face.group_id, 0); + CHECK(face.smooth_group_id, 0); + CHECK(face.mtl_id, OBJ_ID_NONE); + + CHECK(obj_face_get(obj, 1, &face), OBJ_OK); + CHECK(face.vertex_id, 4); + CHECK(face.vertices_count, 4); + CHECK(face.group_id, 0); + CHECK(face.smooth_group_id, 0); + CHECK(face.mtl_id, OBJ_ID_NONE); +} + +static void +test_cube(struct obj* obj) +{ + static const char* cube_obj = + "# Cube with a different material applied to each of its faces\n" + "mtllib master.mtl\n" + "v 0.0000 2.0000 2.0000\n" + "v 0.0000 0.0000 2.0000\n" + "v 2.0000 0.0000 2.0000\n" + "v 2.0000 2.0000 2.0000\n" + "v 0.0000 2.0000 0.0000\n" + "v 0.0000 0.0000 0.0000\n" + "v 2.0000 0.0000 0.0000\n" + "v 2.0000 2.0000 0.0000\n" + "# 8 vertices\n" + "g front\n" + "usemtl red\n" + "f 1 2 3 4\n" + "g back\n" + "usemtl blue\n" + "f 8 7 6 5\n" + "g right\n" + "usemtl green\n" + "f 4 3 7 8\n" + "g top\n" + "usemtl gold\n" + "f 5 1 4 8\n" + "g left\n" + "usemtl orange\n" + "f 5 6 2 1\n" + "g bottom\n" + "usemtl purple\n" + "f 2 6 7 3\n" + "# 6 elements\n"; + struct obj_desc desc; + struct obj_face face; + FILE* file; + size_t iface; + + NCHECK(obj, NULL); + + file = fopen("test_obj_cube.obj", "w"); + NCHECK(file, NULL); + fwrite(cube_obj, sizeof(char), strlen(cube_obj), file); + fclose(file); 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); @@ -145,6 +176,41 @@ main(int argc, char** argv) CHECK(desc.usemtls_count, 6); CHECK(desc.mtllibs_count, 1); + FOR_EACH(iface, 0, 6) { + CHECK(obj_face_get(obj, iface, &face), OBJ_OK); + CHECK(face.vertex_id, iface*4); + CHECK(face.vertices_count, 4); + CHECK(face.group_id, iface); + CHECK(face.smooth_group_id, OBJ_ID_NONE); + CHECK(face.mtl_id, iface); + } +} + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct obj* obj; + (void)argc, (void)argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + + CHECK(obj_create(NULL, NULL), OBJ_BAD_ARGUMENT); + CHECK(obj_create(&allocator, NULL), OBJ_BAD_ARGUMENT); + CHECK(obj_create(NULL, &obj), OBJ_OK); + + CHECK(obj_ref_get(NULL), OBJ_BAD_ARGUMENT); + CHECK(obj_ref_get(obj), OBJ_OK); + CHECK(obj_ref_put(NULL), OBJ_BAD_ARGUMENT); + CHECK(obj_ref_put(obj), OBJ_OK); + CHECK(obj_ref_put(obj), OBJ_OK); + + CHECK(obj_create(&allocator, &obj), OBJ_OK); + + test_plane(obj); + test_squares(obj); + test_cube(obj); + CHECK(obj_ref_put(obj), OBJ_OK); if(MEM_ALLOCATED_SIZE(&allocator)) {