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 f2313c345c26c603c72e87a85369ec360f1aaf4b
parent 689860df4738b1b8633a6403548e04580545ef31
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 11 Jun 2020 11:20:50 +0200

Add reporting of overlapping triangles

Diffstat:
Msrc/senc3d.h | 21++++++++++++++++++++-
Msrc/senc3d_descriptor.c | 28++++++++++++++++++++++++++++
Msrc/senc3d_scene.c | 2++
Msrc/senc3d_scene_analyze.c | 48++++++++++++++++++++++++++++++++++++++++--------
Msrc/senc3d_scene_c.h | 6++++++
5 files changed, 96 insertions(+), 9 deletions(-)

diff --git a/src/senc3d.h b/src/senc3d.h @@ -109,7 +109,7 @@ struct senc3d_enclosure_header { * SENC3D_CONVENTION_NORMAL_FRONT => Ng points toward the front side, * SENC3D_CONVENTION_NORMAL_BACK => Ng points toward the back side. * - * Additionaly the user can set the convention used to output enclosures + * Additionally the user can set the convention used to output enclosures * so that Ng points toward the enclosure or on the opposite direction * (for a closed enclosure Ng points toward the inside or toward the outside) * by using the flags : @@ -302,6 +302,25 @@ senc3d_scene_get_frontier_segment unsigned vrtx_id[SENC3D_GEOMETRY_DIMENSION-1], unsigned* trg_id); +/* Returns the number of overlapping triangles. + * A model including overlapping triangles cannot be split into enclosures + * unequivocally and will probably be ruled invalid by most softwares. + * Additionally there is no garantee that 2 different scenes created from such + * a model give the same enclosures. + * The library currently only detects overlapping triangles that share an + * edge. */ +SENC3D_API res_T +senc3d_scene_get_overlapping_triangles_count + (const struct senc3d_scene* scene, + unsigned* count); + +/* Returns the idx_th overlapping triangle id. */ +SENC3D_API res_T +senc3d_scene_get_overlapping_triangle + (const struct senc3d_scene* scene, + const unsigned idx, + unsigned* id); + SENC3D_API res_T senc3d_scene_ref_get (struct senc3d_scene* scene); diff --git a/src/senc3d_descriptor.c b/src/senc3d_descriptor.c @@ -155,3 +155,30 @@ senc3d_scene_get_frontier_segment *trg_id = edge->trg; return RES_OK; } + +res_T +senc3d_scene_get_overlapping_triangles_count + (const struct senc3d_scene* scn, + vrtx_id_t* count) +{ + size_t tmp; + if(!scn || !count) + return RES_BAD_ARG; + tmp = darray_trg_id_size_get(&scn->analyze.overlapping_ids); + ASSERT(tmp <= VRTX_MAX__); + *count = (trg_id_t)tmp; /* Back to API type */ + return RES_OK; +} + +res_T +senc3d_scene_get_overlapping_triangle + (const struct senc3d_scene* scn, + const unsigned idx, + unsigned* trg_id) +{ + if (!scn || !trg_id + || idx >= darray_trg_id_size_get(&scn->analyze.overlapping_ids)) + return RES_BAD_ARG; + *trg_id = darray_trg_id_cdata_get(&scn->analyze.overlapping_ids)[idx]; + return RES_OK; +} +\ No newline at end of file diff --git a/src/senc3d_scene.c b/src/senc3d_scene.c @@ -43,6 +43,7 @@ scene_release(ref_T * ref) darray_enclosure_release(&scn->analyze.enclosures); darray_enc_ids_array_release(&scn->analyze.enc_ids_array_by_medium); darray_frontier_edge_release(&scn->analyze.frontiers); + darray_trg_id_release(&scn->analyze.overlapping_ids); MEM_RM(dev->allocator, scn); SENC3D(device_ref_put(dev)); @@ -114,6 +115,7 @@ senc3d_scene_create /* Enclosure 0 is always defined for infinite */ OK(darray_enclosure_resize(&scn->analyze.enclosures, 1)); scn->analyze.enclosures_count = 1; + darray_trg_id_init(scn->dev->allocator, &scn->analyze.overlapping_ids); OK(darray_position_reserve(&scn->vertices, scn->nverts)); OK(darray_triangle_in_reserve(&scn->triangles_in, scn->ntris)); diff --git a/src/senc3d_scene_analyze.c b/src/senc3d_scene_analyze.c @@ -61,6 +61,11 @@ struct filter_ctx { component_id_t hit_component; }; +#define HTABLE_NAME overlap +#define HTABLE_KEY trg_id_t +#define HTABLE_DATA char +#include <rsys/hash_table.h> + /****************************************************************************** * Helper function *****************************************************************************/ @@ -143,13 +148,14 @@ self_hit_filter 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); + /* Cannot go downwards */ if(pos.value[2] <= ray_org[2]) return 1; /* Reject */ /* In closest_point queries ray_dir is not informed */ @@ -158,6 +164,7 @@ self_hit_filter } if(s == 0) return 1; /* Reject */ + /* Determine which side was hit */ hit_side = ((s < 0) /* Facing geometrical normal of hit */ @@ -166,6 +173,7 @@ self_hit_filter * the Star3D hit normal is left-handed while star-enclosures-3d uses * right-handed convention */ ? SENC3D_BACK : SENC3D_FRONT; + filter_ctx->hit_component = hit_trg_comp->component[hit_side]; return 0; /* Keep */ } @@ -759,6 +767,8 @@ collect_and_link_neighbours const int rank = omp_get_thread_num(); /* Htable used to give an id to edges */ struct htable_edge_id edge_ids; + /* Htable used to store overlapping triangles */ + struct htable_overlap overlaps; /* Array to keep neighbourhood of edges * Resize/Push operations on neighbourhood_by_edge are valid in the * openmp block because a given neighbourhood is only processed @@ -775,6 +785,7 @@ collect_and_link_neighbours ASSERT((size_t)scn->nverts + (size_t)scn->ntris + 2 <= EDGE_MAX__); htable_edge_id_init(scn->dev->allocator, &edge_ids); + htable_overlap_init(scn->dev->allocator, &overlaps); darray_neighbourhood_init(scn->dev->allocator, &neighbourhood_by_edge); triangles_in = darray_triangle_in_cdata_get(&scn->triangles_in); @@ -946,17 +957,20 @@ collect_and_link_neighbours /* Check that angle is a discriminant property */ ASSERT(a <= current->angle); /* Is sorted */ if(a == current->angle) { - /* Two consecutive triangles with same angle! */ + /* Two consecutive triangles with same angle! Store them */ 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, - LIB_NAME":%s: found 2 overlying triangles ("PRTF_TRG" & "PRTF_TRG").\n", - FUNC_NAME, crt_id, prev_id); - tmp_res = RES_BAD_OP; - goto tmp_error; + #pragma omp critical + { + char one = 1; + tmp_res = htable_overlap_set(&overlaps, &crt_id, &one); + if(tmp_res == RES_OK) + tmp_res = htable_overlap_set(&overlaps, &prev_id, &one); + } + if(tmp_res != RES_OK) goto tmp_error; } a = current->angle; /* Link sides */ @@ -980,7 +994,7 @@ collect_and_link_neighbours * - different media on its sides */ if(neighbour_count == 1 && p_crt_side->medium != p_ccw_side->medium) -#pragma omp critical + #pragma omp critical { struct frontier_edge frontier_edge; frontier_edge.trg = crt_id; @@ -990,10 +1004,28 @@ collect_and_link_neighbours } } } + + #pragma omp barrier + #pragma omp single + { + /* Save all the overlapping triangles in a darray */ + struct htable_overlap_iterator it, end; + htable_overlap_begin(&overlaps, &it); + htable_overlap_end(&overlaps, &end); + darray_trg_id_reserve(&scn->analyze.overlapping_ids, + htable_overlap_size_get(&overlaps)); + while(!htable_overlap_iterator_eq(&it, &end)) { + darray_trg_id_push_back(&scn->analyze.overlapping_ids, + htable_overlap_iterator_key_get(&it)); + htable_overlap_iterator_next(&it); + } + } + tmp_error: if(tmp_res != RES_OK) *res = tmp_res; /* Threads are allowed to return whitout sync. */ htable_edge_id_release(&edge_ids); + htable_overlap_release(&overlaps); darray_neighbourhood_release(&neighbourhood_by_edge); } diff --git a/src/senc3d_scene_c.h b/src/senc3d_scene_c.h @@ -272,6 +272,10 @@ trg_key_eq(const union vrtx_id3* k1, const union vrtx_id3* k2) #define HTABLE_KEY_FUNCTOR_EQ trg_key_eq #include <rsys/hash_table.h> +#define DARRAY_NAME trg_id +#define DARRAY_DATA trg_id_t +#include <rsys/dynamic_array.h> + struct descriptor { enclosure_id_t enclosures_count; /* Store by-triangle enclosures */ @@ -281,6 +285,8 @@ struct descriptor { struct darray_enc_ids_array enc_ids_array_by_medium; /* Store frontiers */ struct darray_frontier_edge frontiers; + /* Store overlying triangles */ + struct darray_trg_id overlapping_ids; }; struct senc3d_scene {