star-uvm

Spatial structuring of unstructured volumetric meshes
git clone git://git.meso-star.fr/star-uvm.git
Log | Files | Refs | README | LICENSE

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:
Msrc/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 */