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