commit 4451a5edc07f1d9b0c4295978720410c7d9cce73
parent 622e65069ef263a442ed9e3d0a1738d0e3f3ff56
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Thu, 17 Dec 2020 19:01:14 +0100
Automatically re-orient the tetrahedron
Diffstat:
| M | src/suvm_volume.c | | | 109 | +++++++++++++++++++++++++++++++++++++++++++++++++------------------------------ |
1 file changed, 68 insertions(+), 41 deletions(-)
diff --git a/src/suvm_volume.c b/src/suvm_volume.c
@@ -426,65 +426,92 @@ error:
}
static res_T
-check_tetrahedra_normals(const struct suvm_volume* vol)
+fixup_tetrahedra_normals(struct suvm_volume* vol)
{
size_t itetra, ntetra;
- res_T res = RES_OK;
+ int fixup = 0;
ASSERT(vol);
ntetra = volume_get_primitives_count(vol);
FOR_EACH(itetra, 0, ntetra) {
- const uint32_t* ids = NULL;
- const float* verts[4];
- float normals[4][3];
- float pt[3];
- float v0[3], v1[3];
-
+ uint32_t* ids = NULL;
+ const float* vert0 = NULL;
+ const float* vert3 = NULL;
+ float normal0[3];
+ float v0[3];
/* Fetch tetrahedron indices */
- ids = darray_u32_cdata_get(&vol->indices) + itetra*4;
+ ids = darray_u32_data_get(&vol->indices) + itetra*4;
ASSERT(ids[0] < volume_get_vertices_count(vol));
ASSERT(ids[1] < volume_get_vertices_count(vol));
ASSERT(ids[2] < volume_get_vertices_count(vol));
ASSERT(ids[3] < volume_get_vertices_count(vol));
/* Fetch the tetrahedron vertices */
- verts[0] = darray_float_cdata_get(&vol->positions) + ids[0]*3/*#coords*/;
- verts[1] = darray_float_cdata_get(&vol->positions) + ids[1]*3/*#coords*/;
- verts[2] = darray_float_cdata_get(&vol->positions) + ids[2]*3/*#coords*/;
- verts[3] = darray_float_cdata_get(&vol->positions) + ids[3]*3/*#coords*/;
+ vert0 = darray_float_cdata_get(&vol->positions) + ids[0]*3/*#coords*/;
+ vert3 = darray_float_cdata_get(&vol->positions) + ids[3]*3/*#coords*/;
+
+ /* Fetch the normal of the 1st facet */
+ volume_primitive_get_facet_normal(vol, itetra, 0, normal0);
+
+ /* Check that the normal of the 1st facet looks the fourth vertex */
+ if(f3_dot(normal0, f3_sub(v0, vert3, vert0)) < 0) {
+ fixup = 1;
+
+ /* Revert tetrahedron orientation, i.e. the vertices of the 1st facet*/
+ SWAP(uint32_t, ids[1], ids[2]);
+
+ /* Revert precomputed normals if any */
+ if(darray_float_size_get(&vol->normals)) {
+ size_t ifacet;
+ FOR_EACH(ifacet, 0, 4) {
+ const size_t id = (itetra*4/*#facets*/ + ifacet)*3/*#coords*/;
+ float* N = darray_float_data_get(&vol->normals) + id;
+ N[0] = -N[0];
+ N[1] = -N[1];
+ N[2] = -N[2];
+ }
+ }
+ }
- /* Fetch the tetrahedron normals */
- volume_primitive_get_facet_normal(vol, itetra, 0, normals[0]);
- volume_primitive_get_facet_normal(vol, itetra, 1, normals[1]);
- volume_primitive_get_facet_normal(vol, itetra, 2, normals[2]);
- volume_primitive_get_facet_normal(vol, itetra, 3, normals[3]);
-
- /* Compute the position at the center of the tetrahedron */
- pt[0] = (verts[0][0] + verts[1][0] + verts[2][0] + verts[3][0]) * 0.25f;
- pt[1] = (verts[0][1] + verts[1][1] + verts[2][1] + verts[3][1]) * 0.25f;
- pt[2] = (verts[0][2] + verts[1][2] + verts[2][2] + verts[3][2]) * 0.25f;
-
- /* Check that normals look toward the tetrahedron center */
- f3_sub(v0, pt, verts[0]);
- f3_sub(v1, pt, verts[3]);
- if(f3_dot(normals[0], v0) < 0
- || f3_dot(normals[1], v1) < 0
- || f3_dot(normals[2], v1) < 0
- || f3_dot(normals[3], v1) < 0) {
- log_err(vol->dev,
- "Invalid vertex orientation for the tetrahedron %lu.\n",
- (unsigned long)itetra);
- res = RES_BAD_ARG;
- goto error;
+#ifndef NDEBUG
+ {
+ const float* verts[4];
+ float normals[4][3];
+ float pt[3], v1[3];
+
+ verts[0] = vert0;
+ verts[1] = darray_float_cdata_get(&vol->positions) + ids[1]*3/*#coords*/;
+ verts[2] = darray_float_cdata_get(&vol->positions) + ids[2]*3/*#coords*/;
+ verts[3] = vert3;
+
+ /* Compute the position at the center of the tetrahedron */
+ pt[0] = (verts[0][0] + verts[1][0] + verts[2][0] + verts[3][0]) * 0.25f;
+ pt[1] = (verts[0][1] + verts[1][1] + verts[2][1] + verts[3][1]) * 0.25f;
+ pt[2] = (verts[0][2] + verts[1][2] + verts[2][2] + verts[3][2]) * 0.25f;
+
+ /* Fetch the tetrahedron normals */
+ volume_primitive_get_facet_normal(vol, itetra, 0, normals[0]);
+ volume_primitive_get_facet_normal(vol, itetra, 1, normals[1]);
+ volume_primitive_get_facet_normal(vol, itetra, 2, normals[2]);
+ volume_primitive_get_facet_normal(vol, itetra, 3, normals[3]);
+
+ /* Check normals orientation */
+ f3_sub(v0, pt, verts[0]);
+ f3_sub(v1, pt, verts[3]);
+ ASSERT(f3_dot(normals[0], v0) >= 0);
+ ASSERT(f3_dot(normals[1], v1) >= 0);
+ ASSERT(f3_dot(normals[2], v1) >= 0);
+ ASSERT(f3_dot(normals[3], v1) >= 0);
}
+#endif
}
-exit:
- return res;
-error:
- goto exit;
+ if(fixup) {
+ log_warn(vol->dev, "Tetrahedrals were not correctly orientated.\n");
+ }
+ return RES_OK;
}
static void
@@ -540,7 +567,7 @@ suvm_tetrahedral_mesh_create
/* Ensure that the vertices of the tetrahedra are well ordered regarding the
* normal convention */
- res = check_tetrahedra_normals(vol);
+ res = fixup_tetrahedra_normals(vol);
if(res != RES_OK) goto error;
/* Build the BVH of the volumetric mesh */