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:
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 {