commit 76efa9c8e2723d16201ef21298e1c87974e3d142
parent 35fa61731b78a04536d6783526198eb9ae485a93
Author: vaplv <vaplv@free.fr>
Date: Sat, 5 Jul 2014 19:27:25 +0200
Add and test the vertex getter
Diffstat:
| M | src/obj.c | | | 71 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
| M | src/obj.h | | | 12 | ++++++++++++ |
| M | src/test_obj.c | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 129 insertions(+), 9 deletions(-)
diff --git a/src/obj.c b/src/obj.c
@@ -3,15 +3,21 @@
#include "obj.h"
#include <rsys/dynamic_array_float.h>
+#include <rsys/float3.h>
+#include <rsys/float4.h>
#include <rsys/mem_allocator.h>
#include <rsys/ref_count.h>
#include <rsys/str.h>
+#include <float.h>
+
struct vertex {
size_t iposition;
size_t inormal;
size_t itexcoord;
};
+static const struct vertex VERTEX_NULL =
+ { OBJ_ID_NONE, OBJ_ID_NONE, OBJ_ID_NONE };
struct named_group {
struct str name;
@@ -239,22 +245,39 @@ parse_face(struct obj* obj, char** word_tk)
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;
+
+ /* Note that the obj indexation starts at 1 rather than 0. We thus subtract 1
+ * to the vertex attribute indices in order to match the C memory layout */
while((word = strtok_r(NULL, " ", word_tk))) {
- char* id, *id_tk;
- struct vertex vert;
+ char* id, *id_tk, *id_pos;
+ struct vertex vert = VERTEX_NULL;
+
/* position index */
- id = strtok_r(word, "/", &id_tk);
- res = string_to_size_t(id, &vert.iposition);
+ id_pos = strtok_r(word, "/", &id_tk);
+ res = string_to_size_t(id_pos, &vert.iposition);
if(res != OBJ_OK)
goto error;
- /* texcoord index */
+ --vert.iposition; /* Match C memory layout */
if((id = strtok_r(NULL, "/", &id_tk))) {
- if(*id != '\0' && OBJ_OK != (res = string_to_size_t(id, &vert.itexcoord)))
+ id_pos += strlen(id_pos);
+ if( id > id_pos + 3) /* Unexpected N `/' separators with N > 2 */
goto error;
- /* normal index */
- if((id = strtok_r(NULL, "/", &id_tk))) {
+ if(id == id_pos + 2) { /* `//' separator => No tex */
+ /* normal index */
if(OBJ_OK != (res = string_to_size_t(id, &vert.inormal)))
goto error;
+ --vert.inormal; /* Match C memory layout */
+ } else {
+ /* texcoord index */
+ if(OBJ_OK != (res = string_to_size_t(id, &vert.itexcoord)))
+ goto error;
+ --vert.itexcoord; /* Match C memory latout */
+ /* normal index */
+ if((id = strtok_r(NULL, "/", &id_tk))) {
+ if(OBJ_OK != (res = string_to_size_t(id, &vert.inormal)))
+ goto error;
+ --vert.inormal; /* Match C memory layout */
+ }
}
}
if(darray_vertex_push_back(&obj->vertices, &vert)) {
@@ -263,7 +286,6 @@ parse_face(struct obj* obj, char** word_tk)
}
++face.vertices_count;
}
-
if(darray_face_push_back(&obj->faces, &face)) {
res = OBJ_MEMORY_ERROR;
goto error;
@@ -686,3 +708,34 @@ obj_mtl_get(const struct obj* obj, const size_t imtl, struct obj_mtl* mtl)
return OBJ_OK;
}
+enum obj_result
+obj_vertex_get
+ (const struct obj* obj, const size_t ivertex, struct obj_vertex* vertex)
+{
+ const struct vertex* vert;
+ const float* data;
+ if(!obj || !vertex || ivertex >= darray_vertex_size_get(&obj->vertices))
+ return OBJ_BAD_ARGUMENT;
+ vert = darray_vertex_cdata_get(&obj->vertices) + ivertex;
+
+ /* Fetch vertex position */
+ ASSERT(vert->iposition != VERTEX_NULL.iposition);
+ data = darray_float_cdata_get(&obj->positions) + vert->iposition * 4;
+ f4_set(vertex->position, data);
+ /* Setup vertex texcoord */
+ if(vert->itexcoord == VERTEX_NULL.itexcoord) {
+ f3_splat(vertex->texcoord, 0.f);
+ } else {
+ data = darray_float_cdata_get(&obj->texcoords) + vert->itexcoord * 3;
+ f3_set(vertex->texcoord, data);
+ }
+ /* Setup vertex normal */
+ if(vert->inormal == VERTEX_NULL.inormal) {
+ f3_splat(vertex->normal, 0.f);
+ } else {
+ data = darray_float_cdata_get(&obj->normals) + vert->inormal * 3;
+ f3_set(vertex->normal, data);
+ }
+ return OBJ_OK;
+}
+
diff --git a/src/obj.h b/src/obj.h
@@ -60,6 +60,12 @@ struct obj_mtl {
size_t faces_count;
};
+struct obj_vertex {
+ float position[4];
+ float normal[3];
+ float texcoord[3];
+};
+
struct obj;
struct mem_allocator;
@@ -112,6 +118,12 @@ obj_mtl_get
const size_t mtl_id,
struct obj_mtl* mtl);
+OBJ_API enum obj_result
+obj_vertex_get
+ (const struct obj* obj,
+ const size_t vertex_id,
+ struct obj_vertex* vertex);
+
END_DECLS
#endif /* OBJ_H */
diff --git a/src/test_obj.c b/src/test_obj.c
@@ -1,5 +1,9 @@
#include "obj.h"
+
+#include <rsys/float3.h>
+#include <rsys/float4.h>
#include <rsys/mem_allocator.h>
+
#include <string.h>
static void
@@ -21,9 +25,11 @@ test_plane(struct obj* obj)
"usemtl wood\n"
"f 1/1 2/2 3/3 4/4\n"
"# 1 element\n";
+ float v4[4];
struct obj_desc desc;
struct obj_face face;
struct obj_mtl mtl;
+ struct obj_vertex vertex;
FILE* file;
NCHECK(obj, NULL);
@@ -74,6 +80,27 @@ test_plane(struct obj* obj)
CHECK(strcmp(mtl.name, "wood"), 0);
CHECK(mtl.face_id, 0);
CHECK(mtl.faces_count, 1);
+
+ CHECK(obj_vertex_get(NULL, OBJ_ID_NONE, NULL), OBJ_BAD_ARGUMENT);
+ CHECK(obj_vertex_get(obj, OBJ_ID_NONE, NULL), OBJ_BAD_ARGUMENT);
+ CHECK(obj_vertex_get(NULL, 0, NULL), OBJ_BAD_ARGUMENT);
+ CHECK(obj_vertex_get(obj, 0, NULL), OBJ_BAD_ARGUMENT);
+ CHECK(obj_vertex_get(NULL, OBJ_ID_NONE, &vertex), OBJ_BAD_ARGUMENT);
+ CHECK(obj_vertex_get(obj, OBJ_ID_NONE, &vertex), OBJ_BAD_ARGUMENT);
+ CHECK(obj_vertex_get(NULL, 0, &vertex), OBJ_BAD_ARGUMENT);
+
+ CHECK(obj_vertex_get(obj, 0, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 0.f, 2.f, 0.f, 1.f)), 1);
+ CHECK(f3_eq(vertex.texcoord, f3(v4, 0.f, 1.f, 0.f)), 1);
+ CHECK(obj_vertex_get(obj, 1, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 0.f, 0.f, 0.f, 1.f)), 1);
+ CHECK(f3_eq(vertex.texcoord, f3(v4, 0.f, 0.f, 0.f)), 1);
+ CHECK(obj_vertex_get(obj, 2, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 2.f, 0.f, 0.f, 1.f)), 1);
+ CHECK(f3_eq(vertex.texcoord, f3(v4, 1.f, 0.f, 0.f)), 1);
+ CHECK(obj_vertex_get(obj, 3, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 2.f, 2.f, 0.f, 1.f)), 1);
+ CHECK(f3_eq(vertex.texcoord, f3(v4, 1.f, 1.f, 0.f)), 1);
}
static void
@@ -101,11 +128,13 @@ test_squares(struct obj* obj)
"f 1//1 2//2 3//3 4//4\n"
"f 4//4 3//3 5//5 6//6\n"
"# 2 elements\n";
+ float v4[4];
struct obj_desc desc;
struct obj_face face;
struct obj_group group;
struct obj_smooth_group sgroup;
struct obj_mtl mtl;
+ struct obj_vertex vertex;
FILE* file;
NCHECK(obj, NULL);
@@ -130,6 +159,19 @@ test_squares(struct obj* obj)
CHECK(face.smooth_group_id, 0);
CHECK(face.mtl_id, OBJ_ID_NONE);
+ CHECK(obj_vertex_get(obj, 0, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 0.f, 2.f, 0.f, 1.f)), 1);
+ CHECK(f3_eq(vertex.normal, f3(v4, 0.f, 0.f, 1.f)), 1);
+ CHECK(obj_vertex_get(obj, 1, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 0.f, 0.f, 0.f, 1.f)), 1);
+ CHECK(f3_eq(vertex.normal, f3(v4, 0.f, 0.f, 1.f)), 1);
+ CHECK(obj_vertex_get(obj, 2, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 2.f, 0.f, 0.f, 1.f)), 1);
+ CHECK(f3_eq(vertex.normal, f3(v4, 0.276597f, 0.f, 0.960986f)), 1);
+ CHECK(obj_vertex_get(obj, 3, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 2.f, 2.f, 0.f, 1.f)), 1);
+ CHECK(f3_eq(vertex.normal, f3(v4, 0.276597f, 0.f, 0.960986f)), 1);
+
CHECK(obj_face_get(obj, 1, &face), OBJ_OK);
CHECK(face.vertex_id, 4);
CHECK(face.vertices_count, 4);
@@ -137,6 +179,19 @@ test_squares(struct obj* obj)
CHECK(face.smooth_group_id, 0);
CHECK(face.mtl_id, OBJ_ID_NONE);
+ CHECK(obj_vertex_get(obj, 4, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 2.f, 2.f, 0.f, 1.f)), 1);
+ CHECK(f3_eq(vertex.normal, f3(v4, 0.276597f, 0.f, 0.960986f)), 1);
+ CHECK(obj_vertex_get(obj, 5, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 2.f, 0.f, 0.f, 1.f)), 1);
+ CHECK(f3_eq(vertex.normal, f3(v4, 0.276597f, 0.f, 0.960986f)), 1);
+ CHECK(obj_vertex_get(obj, 6, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 4.f, 0.f, -1.255298f, 1.f)), 1);
+ CHECK(f3_eq(vertex.normal, f3(v4, 0.531611f, 0.f, 0.846988f)), 1);
+ CHECK(obj_vertex_get(obj, 7, &vertex), OBJ_OK);
+ CHECK(f4_eq(vertex.position, f4(v4, 4.f, 2.f, -1.255298f, 1.f)), 1);
+ CHECK(f3_eq(vertex.normal, f3(v4, 0.531611f, 0.f, 0.846988f)), 1);
+
CHECK(obj_group_get(NULL, OBJ_ID_NONE, NULL), OBJ_BAD_ARGUMENT);
CHECK(obj_group_get(obj, OBJ_ID_NONE, NULL), OBJ_BAD_ARGUMENT);
CHECK(obj_group_get(NULL, 0, NULL), OBJ_BAD_ARGUMENT);