star-enclosures-3d

Extract enclosures from 3D geometry
git clone git://git.meso-star.fr/star-enclosures-3d.git
Log | Files | Refs | README | LICENSE

commit 0e35cc739b2f59b408b68643d32813567cd2b78d
parent 9c7d44f46626f0ba1eb0ee245814e6bd1a55a432
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Sun, 19 Apr 2020 13:47:28 +0200

Switch from raytracing to closest point queries for numerical robustness

Diffstat:
Msrc/senc3d_scene_analyze.c | 88++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 56 insertions(+), 32 deletions(-)

diff --git a/src/senc3d_scene_analyze.c b/src/senc3d_scene_analyze.c @@ -53,6 +53,14 @@ const struct cc_descriptor CC_DESCRIPTOR_NULL = CC_DESCRIPTOR_NULL__; #define DARRAY_DATA component_id_t #include <rsys/dynamic_array.h> +struct filter_ctx { + struct senc3d_scene* scn; + component_id_t origin_component; + struct darray_triangle_comp* triangles_comp; + /* Result of hit */ + component_id_t hit_component; +}; + /****************************************************************************** * Helper function *****************************************************************************/ @@ -117,18 +125,49 @@ self_hit_filter void* ray_data, void* filter_data) { - const struct darray_triangle_comp* triangles_comp = filter_data; - const component_id_t* origin_component = ray_data; + struct filter_ctx* filter_ctx = ray_data; const struct triangle_comp* hit_trg_comp; - - (void)ray_org; (void)ray_dir; - ASSERT(hit && triangles_comp && origin_component); - ASSERT(hit->prim.prim_id < darray_triangle_comp_size_get(triangles_comp)); - hit_trg_comp = darray_triangle_comp_cdata_get(triangles_comp) + struct s3d_attrib pos; + float s, dir[3]; + enum senc3d_side hit_side; + + (void)ray_org; (void)ray_dir; (void)filter_data; + ASSERT(hit && filter_ctx); + ASSERT(hit->prim.prim_id + < darray_triangle_comp_size_get(filter_ctx->triangles_comp)); + ASSERT(hit->uv[0] == CLAMP(hit->uv[0], 0, 1)); + ASSERT(hit->uv[1] == CLAMP(hit->uv[1], 0, 1)); + hit_trg_comp = darray_triangle_comp_cdata_get(filter_ctx->triangles_comp) + hit->prim.prim_id; - return (hit_trg_comp->component[SENC3D_FRONT] == *origin_component - || hit_trg_comp->component[SENC3D_BACK] == *origin_component); + /* No self hit */ + if(hit_trg_comp->component[SENC3D_FRONT] == filter_ctx->origin_component + || hit_trg_comp->component[SENC3D_BACK] == filter_ctx->origin_component) + return 1; /* Reject */ + if(hit->distance == 0) { + /* dir = + z; s = dir . n; */ + s = hit->normal[2]; + } else { + /* Cannot go downwards */ + CHK(s3d_primitive_get_attrib(&hit->prim, S3D_POSITION, hit->uv, &pos) + == RES_OK); + if(pos.value[2] <= ray_org[2]) + return 1; /* Reject */ + /* In closest_point queries ray_dir is not informed */ + f3_sub(dir, pos.value, ray_org); + s = f3_dot(dir, hit->normal); + } + if(s == 0) return 1; /* Reject */ + /* Determine which side was hit */ + hit_side = + ((s < 0) /* Facing geometrical normal of hit */ + == ((filter_ctx->scn->convention & SENC3D_CONVENTION_NORMAL_FRONT) != 0)) + /* Warning: following Embree 2 convention for geometrical normals, + * the Star3D hit normal is left-handed while star-enclosure uses + * right-handed convention */ + ? SENC3D_BACK : SENC3D_FRONT; + filter_ctx->hit_component = hit_trg_comp->component[hit_side]; + return 0; /* Keep */ } static void @@ -507,8 +546,7 @@ extract_connex_components OK(s3d_mesh_setup_indexed_vertices(s3d_shp, (unsigned)scn->ntris, get_scn_indices, (unsigned)scn->nverts, &attribs, 1, scn)); - s3d_mesh_set_hit_filter_function(s3d_shp, self_hit_filter, - triangles_comp_array); + OK(s3d_mesh_set_hit_filter_function(s3d_shp, self_hit_filter, NULL)); OK(s3d_scene_attach_shape(s3d_scn, s3d_shp)); OK(s3d_scene_view_create(s3d_scn, S3D_TRACE, s3d_view)); error: @@ -561,6 +599,7 @@ group_connex_components size_t tmp; component_id_t cc_count; int64_t ccc; + struct filter_ctx filter_ctx; ASSERT(scn && triangles_comp && connex_components && s3d_view && next_enclosure_id && res); @@ -571,7 +610,8 @@ group_connex_components ASSERT(tmp <= COMPONENT_MAX__); cc_count = (component_id_t)tmp; positions = darray_position_cdata_get(&scn->vertices); - + filter_ctx.scn = scn; + filter_ctx.triangles_comp = triangles_comp; /* Cast rays to find links between connex components */ #pragma omp for for(ccc = 0; ccc < (int64_t)cc_count; ccc++) { @@ -579,10 +619,7 @@ group_connex_components component_id_t c = (component_id_t)ccc; struct s3d_hit hit = S3D_HIT_NULL; float origin[3]; - const float dir[3] = { 0, 0, 1 }; - const float range[2] = { 0, FLT_MAX }; struct cc_descriptor* const cc = descriptors[c]; - component_id_t self_hit_component = cc->cc_id; const double* max_vrtx; if(*res != RES_OK) continue; @@ -603,8 +640,9 @@ group_connex_components f3_set_d3(origin, max_vrtx); /* Self-hit data: self hit if hit this component "on the other side" */ - tmp_res = s3d_scene_view_trace_ray(s3d_view, origin, dir, range, - &self_hit_component, &hit); + filter_ctx.origin_component = cc->cc_id; + tmp_res = s3d_scene_view_closest_point(s3d_view, origin, FLT_MAX, + &filter_ctx, &hit); if(tmp_res != RES_OK) { *res = tmp_res; continue; @@ -615,21 +653,7 @@ group_connex_components cc->enclosure_id = 0; } else { /* If hit, group this component */ - const trg_id_t hit_trg_id = (trg_id_t)hit.prim.prim_id; - const struct triangle_comp* hit_trg_comp = - darray_triangle_comp_cdata_get(triangles_comp) + hit_trg_id; - enum senc3d_side hit_side = - ((hit.normal[2] < 0) /* Facing geometrical normal of hit */ - == ((scn->convention & SENC3D_CONVENTION_NORMAL_FRONT) != 0)) - /* Warning: following Embree 2 convention for geometrical normals, - * the Star3D hit normal is left-handed while star-enclosure uses - * right-handed convention */ - ? SENC3D_BACK : SENC3D_FRONT; - ASSERT(hit.normal[2] != 0); - ASSERT(hit_trg_id < scn->ntris); - - /* Not really the root until following links */ - cc->cc_group_root = hit_trg_comp->component[hit_side]; + cc->cc_group_root = filter_ctx.hit_component; ASSERT(cc->cc_group_root < cc_count); } }