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:
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);