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 29812324a77e30c230a35f68b3ab7221d487affa
parent 9de9cb0db670dbf069ca5111b9859ae95c184d6a
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue, 22 Jan 2019 09:57:48 +0100

Merge branch 'release_0.2.2'

Diffstat:
MREADME.md | 16++++++++++++----
Mcmake/CMakeLists.txt | 2+-
Msrc/senc_scene_analyze.c | 72+++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/test_senc_enclosure.c | 4++--
Msrc/test_senc_utils.h | 8++++----
5 files changed, 76 insertions(+), 26 deletions(-)

diff --git a/README.md b/README.md @@ -39,6 +39,13 @@ variable the install directories of its dependencies. Release notes ------------- +### Version 0.2.2 + +- BugFix when grouping components into enclosures. +- Add a warning message in log when triangles that could surround a + hole are found (triangles with at least one unshared edge and + different media on its sides). + ### Version 0.2.1 - BugFix: needed data cleaning on computation canceling. @@ -52,7 +59,8 @@ Release notes License ------- -StarEnclosures is Copyright (C) |Meso|Star&gt; 2018 -(<contact@meso-star.com>). It is free software released under the GPLv3+ -license. You are welcome to redistribute it under certain conditions; -refer to the COPYING files for details. +StarEnclosures is Copyright (C) \\\|Meso\\\|Star&gt; 2018 +(<a href="mailto:contact@meso-star.com" class="email">contact@meso-star.com</a>). +It is free software released under the GPLv3+ license. You are welcome +to redistribute it under certain conditions; refer to the COPYING files +for details. diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -48,7 +48,7 @@ endif() ################################################################################ set(VERSION_MAJOR 0) set(VERSION_MINOR 2) -set(VERSION_PATCH 1) +set(VERSION_PATCH 2) set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SENC_FILES_SRC diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c @@ -208,7 +208,8 @@ extract_connex_components const struct side_range* media_use = darray_side_range_cdata_get(&scn->media_use) + m; side_id_t first_side_not_in_component = media_use->first; - double max_z_nz; + double max_nz; + side_id_t max_nz_side_id = SIDE_NULL__; const side_id_t last_side = media_use->last; int component_canceled = 0; res_T tmp_res = RES_OK; @@ -370,16 +371,20 @@ extract_connex_components ASSERT(IS_ALIGNED(triangles_comp->component, sizeof(cc->cc_id))); FOR_EACH(ii, 0, sz) { const side_id_t s = darray_side_id_cdata_get(&current_component)[ii]; - triangles_comp[TRGSIDE_2_TRG(s)].component[TRGSIDE_2_SIDE(s)] = cc->cc_id; + ASSERT(triangles_comp[TRGSIDE_2_TRG(s)].component[TRGSIDE_2_SIDE(s)] + == COMPONENT_NULL__); + triangles_comp[TRGSIDE_2_TRG(s)].component[TRGSIDE_2_SIDE(s)] + = cc->cc_id; } /* Compute the normal at the max_z vertex. */ - max_z_nz = 0; + max_nz = 0; sz = darray_side_id_size_get(&ids_of_sides_around_max_z_vertex); FOR_EACH(ii, 0, sz) { const side_id_t side_id = darray_side_id_cdata_get(&ids_of_sides_around_max_z_vertex)[ii]; const trg_id_t trg_id = TRGSIDE_2_TRG(side_id); + enum side_id s = TRGSIDE_2_SIDE(side_id); const struct triangle_in* trg_in = darray_triangle_in_cdata_get(&scn->triangles_in) + trg_id; const struct triangle_comp* trg_comp = triangles_comp + trg_id; @@ -389,9 +394,8 @@ extract_connex_components /* To garanty that triangles with 2 sides in the component total to 0 * regardless of numeric accuracy, we need to prevent them to - * contribute (remember than x + y - y == 0 can be false). */ - ASSERT(trg_comp->component[SIDE_FRONT] == cc->cc_id - || trg_comp->component[SIDE_BACK] == cc->cc_id); + * contribute (remember than x + y - y == x can be false). */ + ASSERT(trg_comp->component[s] == cc->cc_id); if(trg_comp->component[SIDE_FRONT] == trg_comp->component[SIDE_BACK]) continue; @@ -403,15 +407,22 @@ extract_connex_components norm = d3_normalize(normal, normal); ASSERT(norm); (void)norm; - /* Orient the geometrical normal according to the convention */ - if(TRGSIDE_IS_FRONT(side_id) + if(fabs(max_nz) < fabs(normal[2])) { + max_nz_side_id = side_id; + max_nz = normal[2]; + } + } + if(max_nz == 0) cc->is_outer_border = 0; + else { + if(TRGSIDE_IS_FRONT(max_nz_side_id) == ((scn->convention & SENC_CONVENTION_NORMAL_FRONT) != 0)) { - max_z_nz += normal[2]; + /* Geom normal points towards the component */ + cc->is_outer_border = (max_nz < 0); } else { - max_z_nz -= normal[2]; + /* Geom normal points away from the component */ + cc->is_outer_border = (max_nz > 0); } } - cc->is_outer_border = (max_z_nz < 0); /* Need to synchronize connex_components growth as this global structure * is accessed by multipe threads */ @@ -581,8 +592,13 @@ group_connex_components 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 side_id hit_side = (hit.normal[2] > 0) ? SIDE_FRONT : SIDE_BACK; - + enum side_id hit_side = + ((hit.normal[2] < 0) /* Facing geometrical normal of hit */ + == ((desc->scene->convention & SENC_CONVENTION_NORMAL_FRONT) != 0)) + /* Warning: Embree 2 convention for geometrical normals is + * left-handed and star-enclosure uses right-handed convention */ + ? SIDE_BACK : SIDE_FRONT; + ASSERT(hit.normal[2] != 0); ASSERT(hit_trg_id < desc->scene->nutris); /* Not really the root until following links */ @@ -746,7 +762,7 @@ collect_and_link_neighbours ASSERT(sz <= EDGE_MAX__); edge_count = (edge_id_t)sz; FOR_EACH(e, 0, edge_count) { - double edge[3], common_edge[3], basis[9], norm, max_z, maxz_edge; + double edge[3], common_edge[3], basis[9], norm, max_z, maxz_edge, a; vrtx_id_t v0, v1, v2; struct edge_neighbourhood* neighbourhood = darray_neighbourhood_data_get(&neighbourhood_by_edge) + e; @@ -811,6 +827,7 @@ collect_and_link_neighbours sizeof(struct neighbour_info), neighbour_cmp); /* Link sides. * Create cycles of sides by neighbourhood around common edge. */ + a = -DBL_MAX; FOR_EACH(i, 0, neighbour_count) { /* Neighbourhood info for current pair of triangles */ const struct neighbour_info* current @@ -839,15 +856,40 @@ collect_and_link_neighbours /* Side ptrs */ struct trgside* const p_crt_side = trgsides + crt_side_idx; struct trgside* const p_ccw_side = trgsides + ccw_side_idx; + /* Check that angle is a discriminant property */ + ASSERT(a <= current->angle); /* Is sorted */ + if(a == current->angle) { + /* Two consecutive triangles with same angle! */ + const struct neighbour_info* previous; + trg_id_t prev_id; + ASSERT(i > 0); + previous = darray_neighbour_cdata_get(neighbour_list) + i - 1; + prev_id = previous->trg_id; + log_err(scn->dev, + "%s: found 2 overlying triangles (%u & %u).\n", + FUNC_NAME, prev_id, crt_id); + tmp_res = RES_BAD_OP; + goto tmp_error; + } + a = current->angle; /* Link sides */ p_crt_side->facing_side_id[crt_edge] = ccw_side_idx; p_ccw_side->facing_side_id[ccw_edge] = crt_side_idx; - /* Record media */ p_crt_side->medium = triangles_in[crt_id].medium[crt_side]; p_ccw_side->medium = triangles_in[ccw_id].medium[ccw_side]; ASSERT(p_crt_side->medium < scn->nmeds); ASSERT(p_ccw_side->medium < scn->nmeds); + /* Detect triangles that could surround a hole: + * - single triangle on (one of) its edge + * - different media on its sides */ + if(neighbour_count == 1 + && p_crt_side->medium != p_ccw_side->medium) + { + log_warn(scn->dev, + "%s: found possible hole involving triangle %u.\n", + FUNC_NAME, crt_id); + } } } tmp_error: diff --git a/src/test_senc_enclosure.c b/src/test_senc_enclosure.c @@ -213,7 +213,7 @@ test(enum senc_convention convention) ctx.scale = 1; d3(ctx.offset, 0, 0, 0); ctx.front_media = medium0; - ctx.back_media = medium0; + ctx.back_media = medium1; CHK(senc_scene_add_geometry(scn, ntriangles - 1, get_indices, get_media, NULL, nvertices, get_position, &ctx) == RES_OK); @@ -233,7 +233,7 @@ test(enum senc_convention convention) CHK(senc_enclosure_get_header(enclosure, &header) == RES_OK); CHK(header.enclosure_id == 0); - CHK(header.enclosed_media_count == 1); + CHK(header.enclosed_media_count == 2); CHK(header.triangle_count == 2 * header.unique_triangle_count); CHK(header.unique_triangle_count == ntriangles - 1); CHK(header.vertices_count == nvertices); diff --git a/src/test_senc_utils.h b/src/test_senc_utils.h @@ -270,19 +270,19 @@ cmp_trg } FOR_EACH(i, 0, 3) { FOR_EACH(j, 0, 3) { - if (d3_eq(t1[i], t2[j])) { + if(d3_eq(t1[i], t2[j])) { trg1_eq[i] = j; - if (i == 0) fst_vrtx = j; + if(i == 0) fst_vrtx = j; break; } } } FOR_EACH(i, 0, 3) { - if (trg1_eq[i] == 3) { + if(trg1_eq[i] == 3) { *trg_eq = 0; return; } - if (trg1_eq[i] == trg1_eq[(i + 1) % 3] + if(trg1_eq[i] == trg1_eq[(i + 1) % 3] || trg1_eq[i] == trg1_eq[(i + 2) % 3]) { *trg_eq = 0; return;