star-3d

Surface structuring for efficient 3D geometric queries
git clone git://git.meso-star.fr/star-3d.git
Log | Files | Refs | README | LICENSE

commit 4db84f7e8be9da2f7e3d30758523daba0fb6d9d9
parent 51546e35d5eec090a3474b1baea4f5dc939a52ed
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Mon, 15 Jun 2015 15:06:34 +0200

Add the s3d_shape_flip_surface function

This function flip the orientation of the geometric normals of the shape

Diffstat:
Msrc/s3d.h | 10++++++++--
Msrc/s3d_instance.h | 1+
Msrc/s3d_mesh.h | 2++
Msrc/s3d_primitive.c | 13++++++++++++-
Msrc/s3d_scene.c | 5+++++
Msrc/s3d_shape.c | 13+++++++++++++
Msrc/test_s3d_shape.c | 7+++++++
7 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/src/s3d.h b/src/s3d.h @@ -72,8 +72,8 @@ enum s3d_attrib_usage { S3D_ATTRIB_2, /* Generic attrib 2 */ S3D_ATTRIB_3, /* Generic attrib 3 */ S3D_ATTRIBS_COUNT__, - /* Unormalized world space face normal. Outward orientation defined with - * respect to the Clock Wise vertex ordering */ + /* Unormalized world space face normal. For triangular meshes, the outward + * orientation is defined with respect to the Clock Wise vertex ordering */ S3D_GEOMETRY_NORMAL }; @@ -304,6 +304,12 @@ s3d_shape_is_attached (struct s3d_shape* shape, char* is_attached); +/* Flip the surface orientation, i.e. flip the geometric normal of the surface */ +S3D_API res_T +s3d_shape_flip_surface + (struct s3d_shape* shape, + const char flip); + /******************************************************************************* * Sampler API ******************************************************************************/ diff --git a/src/s3d_instance.h b/src/s3d_instance.h @@ -39,6 +39,7 @@ struct instance { float transform[12]; /* local to world 3x4 column major matrix */ char update_transform; + char flip_surface; struct geometry geom; struct s3d_scene* scene; diff --git a/src/s3d_mesh.h b/src/s3d_mesh.h @@ -67,6 +67,8 @@ struct mesh { /* Triangular mesh */ struct geometry geom; + char flip_surface; + struct s3d_device* dev; ref_T ref; }; diff --git a/src/s3d_primitive.c b/src/s3d_primitive.c @@ -50,6 +50,7 @@ s3d_primitive_get_attrib const uint32_t* ids; struct mesh* mesh = NULL; const float* transform = NULL; + char flip_surface = 0; float w; res_T res = RES_OK; @@ -63,6 +64,7 @@ s3d_primitive_get_attrib if(prim->inst__ == NULL) { mesh = (struct mesh*)prim->mesh__; + flip_surface = mesh->flip_surface; } else { const struct instance* inst = (const struct instance*)prim->inst__; mesh = (struct mesh*)prim->mesh__; @@ -71,6 +73,7 @@ s3d_primitive_get_attrib res = RES_BAD_ARG; goto error; } + flip_surface = inst->flip_surface ^ mesh->flip_surface; } /* The mesh haven't the required mesh attrib */ @@ -98,7 +101,15 @@ s3d_primitive_get_attrib v2 = pos + ids[2] * 3; if(usage == S3D_GEOMETRY_NORMAL) { /* Compute the geometry normal */ float e0[3], e1[3]; - f3_cross(attrib->value, f3_sub(e0, v2, v0), f3_sub(e1, v1, v0)); + /* Build the geometric normal with respect to surface orientation. + * Default is Clock Wise */ + f3_sub(e0, v2, v0); + f3_sub(e1, v1, v0); + if(flip_surface) { + f3_cross(attrib->value, e1, e0); + } else { + f3_cross(attrib->value, e0, e1); + } if(transform) { /* Transform the normal from local to world space */ float transform_invtrans[9]; f33_invtrans(transform_invtrans, transform); diff --git a/src/s3d_scene.c b/src/s3d_scene.c @@ -224,6 +224,9 @@ scene_setup_shape_mesh scn->is_rtc_scn_outdated = 1; } + /* Update the cached mesh states */ + mesh->flip_surface = shape->data.mesh->flip_surface; + res = scene_build_register_mesh(scn, mesh); if(res != RES_OK) goto error; @@ -274,9 +277,11 @@ scene_setup_shape_instance(struct s3d_scene* scn, struct s3d_shape* shape) res = htable_inst_set(&scn->cached_instances, &shape, &inst); if(res != RES_OK) goto error; } + /* Update the cached instance states */ ASSERT(inst->scene == shape->data.instance->scene); f33_set(inst->transform, shape->data.instance->transform); f3_set(inst->transform + 9, shape->data.instance->transform + 9); + inst->flip_surface = shape->data.instance->flip_surface; /* The instance cannot contain instances */ if(darray_inst_size_get(&inst->scene->instances)) { diff --git a/src/s3d_shape.c b/src/s3d_shape.c @@ -202,6 +202,19 @@ s3d_shape_is_attached(struct s3d_shape* shape, char* is_attached) } res_T +s3d_shape_flip_surface(struct s3d_shape* shape, const char flip) +{ + if(!shape) + return RES_BAD_ARG; + switch(shape->type) { + case SHAPE_MESH: shape->data.mesh->flip_surface = flip; break; + case SHAPE_INSTANCE: shape->data.instance->flip_surface = flip; break; + default: FATAL("Unreachable code\n"); break; + } + return RES_OK; +} + +res_T s3d_instance_set_position (struct s3d_shape* shape, const float position[3]) { diff --git a/src/test_s3d_shape.c b/src/test_s3d_shape.c @@ -213,6 +213,10 @@ main(int argc, char** argv) CHECK(s3d_shape_is_enabled(shape, &c), RES_OK); CHECK(c, 0); + CHECK(s3d_shape_flip_surface(NULL, 0), RES_BAD_ARG); + CHECK(s3d_shape_flip_surface(shape, 0), RES_OK); + CHECK(s3d_shape_flip_surface(shape, 1), RES_OK); + CHECK(s3d_scene_attach_shape(scn, shape), RES_OK); CHECK(s3d_scene_instantiate(scn, &inst), RES_OK); @@ -234,6 +238,9 @@ main(int argc, char** argv) CHECK(s3d_instance_translate(inst, S3D_WORLD_TRANSFORM, pos), RES_OK); CHECK(s3d_instance_translate(shape, S3D_WORLD_TRANSFORM, pos), RES_BAD_ARG); + CHECK(s3d_shape_flip_surface(inst, 0), RES_OK); + CHECK(s3d_shape_flip_surface(inst, 1), RES_OK); + CHECK(s3d_shape_ref_get(NULL), RES_BAD_ARG); CHECK(s3d_shape_ref_get(shape), RES_OK); CHECK(s3d_shape_ref_put(NULL), RES_BAD_ARG);