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 bb7813ddc4ec7b5e5bc58e7a092db4921b4d2159
parent aab81bd201bbfe8ea80a86f384efb71e2647a575
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed, 19 Jun 2024 15:02:04 +0200

Merge branch 'release_0.7.1'

Diffstat:
MREADME.md | 4++++
Mconfig.mk | 2+-
Msrc/senc3d_scene_analyze.c | 149+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
3 files changed, 93 insertions(+), 62 deletions(-)

diff --git a/README.md b/README.md @@ -37,6 +37,10 @@ Edit config.mk as needed, then run: ## Release notes +### Version 0.7.1 + +- Fixes a bug in the code that groups connex components to create enclosures. + ### Version 0.7 - Replace CMake by Makefile as build system. diff --git a/config.mk b/config.mk @@ -1,4 +1,4 @@ -VERSION = 0.7.0 +VERSION = 0.7.1 PREFIX = /usr/local LIB_TYPE = SHARED diff --git a/src/senc3d_scene_analyze.c b/src/senc3d_scene_analyze.c @@ -293,13 +293,12 @@ self_hit_filter trg_comp = darray_triangle_comp_cdata_get(ctx->triangles_comp); const component_id_t* hit_comp = trg_comp[hit->prim.prim_id].component; + const component_id_t oc = ctx->origin_component; ASSERT(hit->prim.prim_id < darray_triangle_comp_size_get(ctx->triangles_comp)); - if(hit_comp[SENC3D_FRONT] == ctx->origin_component - || hit_comp[SENC3D_BACK] == ctx->origin_component) - { + if(hit_comp[SENC3D_FRONT] == oc || hit_comp[SENC3D_BACK] == oc) { /* Self hit */ return 1; /* Reject */ } @@ -332,48 +331,49 @@ self_hit_filter * as a common vertex (they can also partially intersect, but this is invalid * and remains undetected by star enclosures). */ struct filter_ctx1* ctx = &fctx_->c.ctx1; - struct cc_descriptor* const* - comp_descriptors = darray_ptr_component_descriptor_cdata_get(ctx->components); + struct cc_descriptor* const* comp_descriptors + = darray_ptr_component_descriptor_cdata_get(ctx->components); const struct triangle_comp* trg_comp = darray_triangle_comp_cdata_get(ctx->triangles_comp); const component_id_t* hit_comp = trg_comp[hit->prim.prim_id].component; - const union double3* vertices = darray_position_cdata_get(&ctx->scn->vertices); + const union double3* + vertices = darray_position_cdata_get(&ctx->scn->vertices); enum senc3d_side hit_side; float s = 0, hit_normal[3], rdir[3]; 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)); if(log_components) { - printf("Component #%u: investigating hit (d=%g, n= %g %g %g).\n", - ctx->origin_component, hit->distance, SPLIT3(hit->normal)); + printf("Component #%u: investigating hit " + "(d=%g, n=%g,%g,%g, components: %u, %u)\n", + oc, hit->distance, SPLIT3(hit->normal), + hit_comp[SENC3D_FRONT], hit_comp[SENC3D_BACK]); } if(hit->distance > ctx->hit_dist) { /* No improvement */ if(log_components) { - printf("Component #%u: further away => reject.\n", ctx->origin_component); + printf("Component #%u: further away (%g): reject\n", + oc, ctx->hit_dist); } return 1; } - if(hit_comp[SENC3D_FRONT] == ctx->origin_component - || hit_comp[SENC3D_BACK] == ctx->origin_component) - { + if(hit_comp[SENC3D_FRONT] == oc || hit_comp[SENC3D_BACK] == oc) { /* Self hit */ if(log_components) { - printf("Component #%u: self hit => reject.\n", ctx->origin_component); - } - return 1; - } - - if(hit->distance > 0 && ray_dir[2] <= 0) { - /* Not upward */ - if(log_components) { - printf("Component #%u: not upward => reject.\n", ctx->origin_component); + printf("Component #%u: self hit: reject\n", oc); } return 1; } @@ -392,7 +392,8 @@ self_hit_filter /* Cannot change ctx->hit_component */ if(log_components) { printf("Component #%u: hit component #%u and already linked to it:" - " reject\n", ctx->origin_component, c); + " reject\n", + oc, c); } continue; } @@ -401,14 +402,13 @@ self_hit_filter /* The inner component we are trying to link can only be linked to * an outer component if it is inside */ if(log_components) { - printf("Component #%u: hit outer component #%u\n", - ctx->origin_component, c); + printf("Component #%u: hit outer component #%u\n", oc, c); } if(!is_component_inside(comp_descriptors[c], - comp_descriptors[ctx->origin_component], ctx)) + comp_descriptors[oc], ctx)) { if(log_components) { - printf("Component #%u: not inside: reject\n", ctx->origin_component); + printf("Component #%u: not inside: reject\n", oc); } continue; } @@ -427,36 +427,36 @@ self_hit_filter ctx->hit_prim = hit->prim; if(log_components) { if(v < ctx->current_6volume) { - printf("Component #%u: currently the smaller one: keep component" - " #%u\n", ctx->origin_component, ctx->hit_component); + printf("Component #%u: currently the smaller one: " + "keep component #%u\n", + oc, ctx->hit_component); } else { - printf("Component #%u: change from inner to outer: keep component" - " #%u\n", ctx->origin_component, ctx->hit_component); + printf("Component #%u: change from inner to outer: " + "keep component #%u\n", + oc, ctx->hit_component); } } } else { if(log_components) { - printf("Component #%u: not the smaller one: reject\n", - ctx->origin_component); + printf("Component #%u: not the smaller one: reject\n", oc); } continue; } } 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) { - printf("Component #%u: hit inner component #%u\n", - ctx->origin_component, c); + printf("Component #%u: hit inner component #%u\n", oc, c); } if(ctx->hit_component != COMPONENT_NULL__ && comp_descriptors[ctx->hit_component]->is_outer_border ) { if(log_components) { printf("Component #%u: already in an outer component: reject\n", - ctx->origin_component); + oc); } continue; } @@ -464,22 +464,19 @@ 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[ctx->origin_component]->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) { if(log_components) { - printf("Component #%u: not (even in part) above: reject\n", - ctx->origin_component); + printf("Component #%u: not (even in part) above: reject\n", oc); } continue; /* Not above */ } if(is_component_inside(comp_descriptors[c], - comp_descriptors[ctx->origin_component], ctx)) + comp_descriptors[oc], ctx)) { if(log_components) { - printf("Component #%u: not outside: reject\n", ctx->origin_component); + printf("Component #%u: not outside: reject\n", oc); } continue; /* Inside */ } @@ -493,13 +490,13 @@ self_hit_filter ctx->hit_dist = 0; ctx->hit_prim = hit->prim; if(log_components) { - printf("Component #%u: currently the bigger one: keep component" - " #%u\n", ctx->origin_component, ctx->hit_component); + printf("Component #%u: currently the bigger one: " + "keep component #%u\n", + oc, ctx->hit_component); } } else { if(log_components) { - printf("Component #%u: not the bigger one: reject\n", - ctx->origin_component); + printf("Component #%u: not the bigger one: reject\n", oc); } continue; } @@ -511,14 +508,24 @@ self_hit_filter 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); ctx->hit_dist = hit->distance; ctx->hit_prim = hit->prim; if(log_components) { - printf("Component #%u: 2 sides with same component: keep component" - " #%u\n", ctx->origin_component, ctx->hit_component); + printf("Component #%u: 2 sides with same component: " + "keep component #%u\n", + oc, ctx->hit_component); } return 1; } @@ -535,7 +542,7 @@ self_hit_filter s = f3_dot(rdir, hit_normal); ASSERT(!isnan(s)); if(log_components) { - printf("Component #%u: had to fix s (was NaN)\n", ctx->origin_component); + printf("Component #%u: had to fix s (was NaN)\n", oc); } } @@ -543,21 +550,32 @@ self_hit_filter /* Same distance with no s improvement: keep the previous hit */ if(log_components) { printf("Component #%u: not improving s (%g VS %g): reject\n", - ctx->origin_component, s, ctx->s); + oc, s, ctx->s); } return 1; } 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); ctx->hit_dist = hit->distance; ctx->hit_prim = hit->prim; if(log_components) { - printf("Component #%u: tiny s (%g): keep but don't know the component\n", - ctx->origin_component, s); + printf("Component #%u: tiny s (%g): " + "keep but don't know the component\n", + oc, s); } return 1; } @@ -569,14 +587,23 @@ 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", - ctx->origin_component, s, ctx->hit_component); + printf("Component #%u: standard s, (%g): keep component #%u\n", + oc, s, ctx->hit_component); } return 1; } @@ -1150,7 +1177,7 @@ group_connex_components const int output_normal_in = (scn->convention & SENC3D_CONVENTION_NORMAL_INSIDE) != 0; str_init(scn->dev->allocator, &name); - printf("Dumping components for scene #%u.\n", scene_cpt); + printf("Dumping components for scene #%u\n", scene_cpt); for(ccc = 0; ccc < (int64_t)cc_count; ccc++) { FILE* f; trg_id_t t; @@ -1187,7 +1214,7 @@ group_connex_components fprintf(f, " endfacet\n"); } } - printf("Dumped component #%u in file %s.\n", c, str_cget(&name)); + printf("Dumped component #%u in file %s\n", c, str_cget(&name)); fprintf(f, "endsolid %s\n", str_cget(&name)); fclose(f); } @@ -1294,7 +1321,7 @@ group_connex_components * FRONT/BACK discrimination was not reliable enough and should be done * differently. */ /* Could try something; now just report a failure */ - log_err(scn->dev, LIB_NAME": %s: %d: search failed.\n", FUNC_NAME, + log_err(scn->dev, LIB_NAME": %s: %d: search failed\n", FUNC_NAME, __LINE__ ); *res = RES_BAD_OP; continue; @@ -2039,7 +2066,7 @@ scene_analyze { if(res != RES_OK) { log_err(scn->dev, - LIB_NAME":%s: could not build neighbourhoods from scene.\n", + LIB_NAME":%s: could not build neighbourhoods from scene\n", FUNC_NAME); } else { res = res2; @@ -2062,7 +2089,7 @@ scene_analyze #pragma omp single nowait { log_err(scn->dev, - LIB_NAME":%s: could not extract connex components from scene.\n", + LIB_NAME":%s: could not extract connex components from scene\n", FUNC_NAME); } /* No barrier here */ goto error_; @@ -2086,7 +2113,7 @@ scene_analyze #pragma omp single nowait { log_err(scn->dev, - LIB_NAME":%s: could not group connex components from scene.\n", + LIB_NAME":%s: could not group connex components from scene\n", FUNC_NAME); } goto error_; @@ -2114,7 +2141,7 @@ scene_analyze #pragma omp single nowait { log_err(scn->dev, - LIB_NAME":%s: could not build result.\n", FUNC_NAME); + LIB_NAME":%s: could not build result\n", FUNC_NAME); } goto error_; }