commit 2f347c293c77c9f1538d56ebcf4b4e840497c23e
parent d89475a09cd79c60cc0d1f872456273456b5084e
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Wed, 19 Jun 2024 11:32:26 +0200
BugFix: grouping of connex components
Grouping could associate a wrong component after rejecting the correct
one. The rejection was caused by same Z coordinate between origin and
hit on component, not meeting the "upward-only" rule for grouping.
This rule is in-place to avoid creating loops when grouping, and should
not be removed. Also one should avoid introducing different rules for
distant (d > 0) hits on inner and outer components.
The selected fix rely on using the max Z coordinate of the hit
components instead of hit.z, as this remains effictive in avoiding
loops, and is not affected by numerical accuracy concerns.
Diffstat:
1 file changed, 37 insertions(+), 12 deletions(-)
diff --git a/src/senc3d_scene_analyze.c b/src/senc3d_scene_analyze.c
@@ -344,6 +344,12 @@ self_hit_filter
const int log_components =
ctx->scn->convention & SENC3D_LOG_COMPONENTS_INFORMATION;
const component_id_t oc = ctx->origin_component;
+ /* Links must be upward to avoid creating loops
+ * Instead of comparing hit.z VS origin.z, compare max_Z of components
+ * Here we keep max_z of the origin component that will be used for these
+ * comparisons */
+ const double org_z = vertices[comp_descriptors[oc]->max_z_vrtx_id].pos.z;
+ vrtx_id_t other_id;
ASSERT(hit->prim.prim_id
< darray_triangle_comp_size_get(ctx->triangles_comp));
@@ -439,7 +445,7 @@ self_hit_filter
} else {
/* c is an inner component */
vrtx_id_t c_z_id;
- double org_z, v;
+ double v;
/* If we've already found a valid outer component, inner components
* should not be considered anymore */
if(log_components) {
@@ -458,7 +464,6 @@ self_hit_filter
* another inner component if (at least partly) above it and not
* inside */
c_z_id = comp_descriptors[c]->max_z_vrtx_id;
- org_z = vertices[comp_descriptors[oc]->max_z_vrtx_id].pos.z;
ASSERT(c_z_id < darray_position_size_get(&ctx->scn->vertices));
ASSERT(vertices[c_z_id].pos.z >= org_z);
if(vertices[c_z_id].pos.z == org_z) {
@@ -499,18 +504,19 @@ self_hit_filter
}
return 1;
}
- ASSERT(hit->distance > 0);
-
- if(ray_dir[2] <= 0) {
- /* Not upward */
- if(log_components) {
- printf("Component #%u: not upward => reject\n", oc);
- }
- return 1;
- }
+ ASSERT(hit->distance > 0);
if(hit_comp[SENC3D_FRONT] == hit_comp[SENC3D_BACK]) {
/* Easy case and hit component is known */
+ other_id = comp_descriptors[hit_comp[SENC3D_FRONT]]->max_z_vrtx_id;
+ ASSERT(other_id < darray_position_size_get(&ctx->scn->vertices));
+ if(vertices[other_id].pos.z <= org_z) {
+ if(log_components) {
+ printf("Component #%u: 2 sides, not (even in part) above: reject\n",
+ oc);
+ }
+ return 1;
+ }
ctx->hit_component = hit_comp[SENC3D_FRONT];
ctx->s = 1;
f3_set(ctx->hit_dir, ray_dir);
@@ -551,6 +557,16 @@ self_hit_filter
if(fabsf(s) < DOT_THRESHOLD) {
/* We cannot know for sure which side to consider */
+ vrtx_id_t i1 = comp_descriptors[hit_comp[SENC3D_FRONT]]->max_z_vrtx_id;
+ vrtx_id_t i2 = comp_descriptors[hit_comp[SENC3D_BACK]]->max_z_vrtx_id;
+ double possible_z = MMAX(vertices[i1].pos.z, vertices[i2].pos.z);
+ if(possible_z <= org_z) {
+ if(log_components) {
+ printf("Component #%u: tiny s, not (even in part) above: reject\n",
+ oc);
+ }
+ return 1;
+ }
ctx->hit_component = COMPONENT_NULL__;
ctx->s = s;
f3_set(ctx->hit_dir, ray_dir);
@@ -571,13 +587,22 @@ self_hit_filter
* the Star3D hit normal is left-handed while star-enclosures-3d uses
* right-handed convention */
? SENC3D_BACK : SENC3D_FRONT;
+ other_id = comp_descriptors[hit_comp[hit_side]]->max_z_vrtx_id;
+ ASSERT(other_id < darray_position_size_get(&ctx->scn->vertices));
+ if(vertices[other_id].pos.z <= org_z) {
+ if(log_components) {
+ printf("Component #%u: standard s, not (even in part) above: reject\n",
+ oc);
+ }
+ return 1;
+ }
ctx->hit_component = hit_comp[hit_side];
ctx->s = s;
f3_set(ctx->hit_dir, ray_dir);
ctx->hit_dist = hit->distance;
ctx->hit_prim = hit->prim;
if(log_components) {
- printf("Component #%u: standard s (%g): keep component #%u\n",
+ printf("Component #%u: standard s, (%g): keep component #%u\n",
oc, s, ctx->hit_component);
}
return 1;