commit 9e1ae5f08663305b09824130af2134c486b5ef90
parent 49facacc9e3231bce0050e470d4f0ccd9f509b31
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 11 Feb 2019 16:07:34 +0100
Merge branch 'feature_frontiers' into develop
Diffstat:
7 files changed, 164 insertions(+), 69 deletions(-)
diff --git a/src/senc.h b/src/senc.h
@@ -279,6 +279,17 @@ senc_descriptor_get_global_triangle_global_id
unsigned* gid);
SENC_API res_T
+senc_descriptor_get_frontier_segments_count
+ (const struct senc_descriptor* descriptor,
+ unsigned* count); /* Number of frontiers segments. */
+
+SENC_API res_T
+senc_descriptor_get_frontier_segment
+ (const struct senc_descriptor* descriptor,
+ const unsigned iseg,
+ unsigned vrtx_id[2]);
+
+SENC_API res_T
senc_descriptor_ref_get
(struct senc_descriptor* descriptor);
diff --git a/src/senc_descriptor.c b/src/senc_descriptor.c
@@ -37,6 +37,7 @@ descriptor_release(ref_T * ref)
darray_triangle_enc_release(&desc->triangles_enc);
darray_enclosure_release(&desc->enclosures);
darray_enc_ids_array_release(&desc->enc_ids_array_by_medium);
+ darray_frontier_edge_release(&desc->frontiers);
MEM_RM(scn->dev->allocator, desc);
SENC(scene_ref_put(scn));
@@ -61,6 +62,7 @@ descriptor_create(struct senc_scene* scn)
darray_enc_ids_array_init(scn->dev->allocator,
&desc->enc_ids_array_by_medium);
OK(darray_enc_ids_array_resize(&desc->enc_ids_array_by_medium, scn->nmeds));
+ darray_frontier_edge_init(scn->dev->allocator, &desc->frontiers);
/* Enclosure 0 is always defined for infinite */
OK(darray_enclosure_resize(&desc->enclosures, 1));
desc->enclosures_count = 1;
@@ -275,6 +277,36 @@ senc_descriptor_get_global_triangle_global_id
}
res_T
+senc_descriptor_get_frontier_segments_count
+ (const struct senc_descriptor* desc,
+ unsigned* count)
+{
+ size_t tmp;
+ if (!desc || !count)
+ return RES_BAD_ARG;
+ tmp = darray_frontier_edge_size_get(&desc->frontiers);
+ ASSERT(tmp < UINT_MAX);
+ *count = (unsigned)tmp;
+ return RES_OK;
+}
+
+res_T
+senc_descriptor_get_frontier_segment
+ (const struct senc_descriptor* desc,
+ const unsigned iseg,
+ unsigned vrtx_id[2])
+{
+ const struct trg_edge* edge;
+ if (!vrtx_id || !desc
+ || iseg >= darray_frontier_edge_size_get(&desc->frontiers))
+ return RES_BAD_ARG;
+ edge = darray_frontier_edge_cdata_get(&desc->frontiers) + iseg;
+ vrtx_id[0] = (unsigned)edge->vrtx0; /* Back to API type */
+ vrtx_id[1] = (unsigned)edge->vrtx1; /* Back to API type */
+ return RES_OK;
+}
+
+res_T
senc_descriptor_ref_get(struct senc_descriptor* desc)
{
if(!desc) return RES_BAD_ARG;
diff --git a/src/senc_descriptor_c.h b/src/senc_descriptor_c.h
@@ -84,6 +84,66 @@ triangle_enc_init(struct mem_allocator* alloc, struct triangle_enc* trg) {
#define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_enc_id_copy_and_release
#include <rsys/dynamic_array.h>
+/* Triangle edge struct and basic functions */
+struct trg_edge {
+ vrtx_id_t vrtx0, vrtx1;
+};
+
+static FINLINE int
+edge_ok(const struct trg_edge* edge) {
+ return(edge
+ && edge->vrtx0 <= VRTX_MAX__
+ && edge->vrtx1 <= VRTX_MAX__
+ && edge->vrtx0 < edge->vrtx1);
+}
+
+static FINLINE void
+set_edge
+(const vrtx_id_t vrtx0,
+ const vrtx_id_t vrtx1,
+ struct trg_edge* edge,
+ unsigned char* reversed)
+{
+ ASSERT(edge && reversed && vrtx0 != vrtx1);
+ ASSERT(*reversed == UCHAR_MAX); /* Should not be already set. */
+ if (vrtx0 < vrtx1) {
+ edge->vrtx0 = vrtx0;
+ edge->vrtx1 = vrtx1;
+ *reversed = 0; /* Non reversed edge */
+ }
+ else {
+ edge->vrtx0 = vrtx1;
+ edge->vrtx1 = vrtx0;
+ *reversed = 1; /* Reversed edge */
+ }
+ ASSERT(edge_ok(edge));
+}
+
+static FINLINE int
+edge_eq(const struct trg_edge* e1, const struct trg_edge* e2)
+{
+ ASSERT(edge_ok(e1) && edge_ok(e2));
+ return e1->vrtx0 == e2->vrtx0 && e1->vrtx1 == e2->vrtx1;
+}
+
+/* Information kept during the building of side groups. */
+struct trgside {
+ /* Rank of the trgside facing this trgside through its edges */
+ side_id_t facing_side_id[3];
+ /* Id of this trgside's medium */
+ medium_id_t medium;
+
+ /* Implicit information that we don't need to store:
+ * - triangle_id
+ * - side
+ * This is due to the memory layout of the elt darray:
+ * front(trg_0), back(trg_0), front(trg_1), back(trg_1), ... */
+};
+
+#define DARRAY_NAME frontier_edge
+#define DARRAY_DATA struct trg_edge
+#include <rsys/dynamic_array.h>
+
struct senc_descriptor {
struct senc_scene* scene;
enclosure_id_t enclosures_count;
@@ -94,6 +154,8 @@ struct senc_descriptor {
struct darray_enc_ids_array enc_ids_array_by_medium;
trg_id_t triangle_count;
vrtx_id_t vertices_count;
+ /* Store frontiers */
+ struct darray_frontier_edge frontiers;
ref_T ref;
};
diff --git a/src/senc_enclosure_data.h b/src/senc_enclosure_data.h
@@ -97,7 +97,7 @@ bool_array_of_media_to_darray_media
ASSERT(sz <= MEDIUM_MAX__);
darray_media_clear(dst);
if(res != RES_OK) goto error;
- FOR_EACH(i, 0, (medium_id_t) sz) {
+ FOR_EACH(i, 0, (medium_id_t)sz) {
if(!data[i]) continue;
res = darray_media_push_back(dst, &i);
if(res != RES_OK) goto error;
diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c
@@ -14,7 +14,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "senc.h"
-#include "senc_descriptor_c.h"
#include "senc_device_c.h"
#include "senc_scene_c.h"
#include "senc_scene_analyze_c.h"
@@ -673,6 +672,7 @@ collect_and_link_neighbours
(struct senc_scene* scn,
struct trgside* trgsides,
struct darray_triangle_tmp* triangles_tmp_array,
+ struct darray_frontier_edge* frontiers,
/* Shared error status.
* We accept to overwrite an error with a different error */
res_T* res)
@@ -698,7 +698,7 @@ collect_and_link_neighbours
size_t sz;
res_T tmp_res;
- ASSERT(scn && trgsides && triangles_tmp_array && res);
+ ASSERT(scn && trgsides && triangles_tmp_array && frontiers && res);
ASSERT((size_t)scn->nuverts + (size_t)scn->nutris + 2 <= EDGE_MAX__);
htable_edge_id_init(scn->dev->allocator, &edge_ids);
@@ -906,13 +906,15 @@ collect_and_link_neighbours
* - different media on its sides */
if(neighbour_count == 1
&& p_crt_side->medium != p_ccw_side->medium)
+#pragma omp critical
{
+ struct trg_edge disc;
log_warn(scn->dev,
- "%s: found possible hole involving triangle %lu.\n"
- " Edge: %g %g %g -- %g %g %g\n",
- FUNC_NAME, (unsigned long)triangles_in[crt_id].global_id,
- SPLIT3(vertices[v0].vec),
- SPLIT3(vertices[v1].vec));
+ "%s: found frontier involving triangle %lu.\n",
+ FUNC_NAME, (unsigned long)triangles_in[crt_id].global_id);
+ disc.vrtx0 = v0;
+ disc.vrtx1 = v1;
+ darray_frontier_edge_push_back(frontiers, &disc);
}
}
}
@@ -928,6 +930,7 @@ build_result
(struct senc_descriptor* desc,
const struct darray_ptr_component_descriptor* connex_components,
const struct darray_triangle_comp* triangles_comp_array,
+ struct darray_frontier_edge* frontiers,
/* Shared error status.
* We accept to overwrite an error with a different error */
res_T* res)
@@ -946,7 +949,7 @@ build_result
int64_t tt;
int64_t ee;
- ASSERT(desc && connex_components && triangles_comp_array);
+ ASSERT(desc && connex_components && triangles_comp_array && frontiers && res);
alloc = descriptor_get_allocator(desc);
scn = desc->scene;
@@ -954,7 +957,8 @@ build_result
normals_front = (scn->convention & SENC_CONVENTION_NORMAL_FRONT) != 0;
normals_back = (scn->convention & SENC_CONVENTION_NORMAL_BACK) != 0;
ASSERT(normals_back != normals_front);
- ASSERT(output_normal_in != ((scn->convention & SENC_CONVENTION_NORMAL_OUTSIDE) != 0));
+ ASSERT(output_normal_in
+ != ((scn->convention & SENC_CONVENTION_NORMAL_OUTSIDE) != 0));
ASSERT(darray_ptr_component_descriptor_size_get(connex_components)
<= COMPONENT_MAX__);
cc_descriptors = darray_ptr_component_descriptor_cdata_get(connex_components);
@@ -973,7 +977,7 @@ build_result
/* Build global enclosure information */
#pragma omp for
- for(tt = 0; tt < (int64_t) scn->nutris; tt++) {
+ for(tt = 0; tt < (int64_t)scn->nutris; tt++) {
trg_id_t t = (trg_id_t)tt;
const component_id_t cf_id = triangles_comp[t].component[SIDE_FRONT];
const component_id_t cb_id = triangles_comp[t].component[SIDE_BACK];
@@ -1121,6 +1125,10 @@ build_result
*res = tmp_res;
} /* No barrier here */
htable_vrtx_id_release(&vtable);
+ /* The first thread here copies frontiers into descriptor */
+#pragma omp single nowait
+ darray_frontier_edge_copy_and_clear(&desc->frontiers, frontiers);
+ /* No barrier here */
}
/*******************************************************************************
@@ -1137,6 +1145,9 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
* They are refered to by arrays of ids. */
struct darray_ptr_component_descriptor connex_components;
char connex_components_initialized = 0;
+ /* Array of frontiers edges */
+ struct darray_frontier_edge frontiers;
+ char frontiers_initialized = 0;
/* Store by-triangle components */
struct darray_triangle_comp triangles_comp;
char triangles_comp_initialized = 0;
@@ -1161,6 +1172,8 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
darray_triangle_tmp_init(scn->dev->allocator, &triangles_tmp);
triangles_tmp_initialized = 1;
+ darray_frontier_edge_init(scn->dev->allocator, &frontiers);
+ frontiers_initialized = 1;
OK(darray_triangle_tmp_resize(&triangles_tmp, scn->nutris));
trgsides
@@ -1183,7 +1196,8 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
#pragma omp parallel num_threads(scn->dev->nthreads)
{
/* Step 1: build neighbourhoods */
- collect_and_link_neighbours(scn, trgsides, &triangles_tmp, &res);
+ collect_and_link_neighbours(scn, trgsides, &triangles_tmp, &frontiers,
+ &res);
/* No barrier at the end of step 1: data used in step 1 cannot be
* released / data produced by step 1 cannot be used
* until next sync point */
@@ -1271,7 +1285,7 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
} /* No barrier here */
/* Step 4: Build result */
- build_result(desc, &connex_components, &triangles_comp, &res);
+ build_result(desc, &connex_components, &triangles_comp, &frontiers, &res);
/* No barrier at the end of step 4: data used in step 4 cannot be
* released / data produced by step 4 cannot be used
* until next sync point */
@@ -1312,6 +1326,8 @@ exit:
if(s3d_view) S3D(scene_view_ref_put(s3d_view));
if(triangles_tmp_initialized) darray_triangle_tmp_release(&triangles_tmp);
if(triangles_comp_initialized) darray_triangle_comp_release(&triangles_comp);
+ if(frontiers_initialized)
+ darray_frontier_edge_release(&frontiers);
if(trgsides) MEM_RM(scn->dev->allocator, trgsides);
if(desc) *out_desc = desc;
diff --git a/src/senc_scene_analyze_c.h b/src/senc_scene_analyze_c.h
@@ -18,66 +18,12 @@
#include "senc_scene_c.h"
#include "senc_internal_types.h"
+#include "senc_descriptor_c.h"
#include <rsys/mem_allocator.h>
#include <rsys/hash_table.h>
#include <rsys/double3.h>
-/* Triangle edge struct and basic functions */
-struct trg_edge {
- vrtx_id_t vrtx0, vrtx1;
-};
-
-static FINLINE int
-edge_ok(const struct trg_edge* edge) {
- return(edge
- && edge->vrtx0 <= VRTX_MAX__
- && edge->vrtx1 <= VRTX_MAX__
- && edge->vrtx0 < edge->vrtx1);
-}
-
-static FINLINE void
-set_edge
- (const vrtx_id_t vrtx0,
- const vrtx_id_t vrtx1,
- struct trg_edge* edge,
- unsigned char* reversed)
-{
- ASSERT(edge && reversed && vrtx0 != vrtx1);
- ASSERT(*reversed == UCHAR_MAX); /* Should not be already set. */
- if(vrtx0 < vrtx1) {
- edge->vrtx0 = vrtx0;
- edge->vrtx1 = vrtx1;
- *reversed = 0; /* Non reversed edge */
- } else {
- edge->vrtx0 = vrtx1;
- edge->vrtx1 = vrtx0;
- *reversed = 1; /* Reversed edge */
- }
- ASSERT(edge_ok(edge));
-}
-
-static FINLINE int
-edge_eq(const struct trg_edge* e1, const struct trg_edge* e2)
-{
- ASSERT(edge_ok(e1) && edge_ok(e2));
- return e1->vrtx0 == e2->vrtx0 && e1->vrtx1 == e2->vrtx1;
-}
-
-/* Information kept during the building of side groups. */
-struct trgside {
- /* Rank of the trgside facing this trgside through its edges */
- side_id_t facing_side_id[3];
- /* Id of this trgside's medium */
- medium_id_t medium;
-
- /* Implicit information that we don't need to store:
- * - triangle_id
- * - side
- * This is due to the memory layout of the elt darray:
- * front(trg_0), back(trg_0), front(trg_1), back(trg_1), ... */
-};
-
static FINLINE void
init_trgside(struct mem_allocator* alloc, struct trgside* data)
{
diff --git a/src/test_senc_descriptor.c b/src/test_senc_descriptor.c
@@ -188,10 +188,38 @@ main(int argc, char** argv)
nvertices, get_position, &ctx) == RES_BAD_ARG);
CHK(senc_scene_ref_put(scn) == RES_OK);
- CHK(senc_device_ref_put(dev) == RES_OK);
if(desc) CHK(senc_descriptor_ref_put(desc) == RES_OK);
+ desc = NULL;
CHK(senc_enclosure_ref_put(enc) == RES_OK);
+ /* Same cube with a hole (last triangle is missing) */
+ CHK(senc_scene_create(dev,
+ SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, &scn)
+ == RES_OK);
+
+ CHK(senc_scene_add_geometry(scn, ntriangles - 1, get_indices, get_media,
+ NULL, nvertices, get_position, &ctx) == RES_OK);
+
+ CHK(senc_scene_analyze(scn, &desc) == RES_OK);
+
+ CHK(senc_descriptor_get_frontier_segments_count(NULL, NULL) == RES_BAD_ARG);
+ CHK(senc_descriptor_get_frontier_segments_count(desc, NULL) == RES_BAD_ARG);
+ CHK(senc_descriptor_get_frontier_segments_count(NULL, &count) == RES_BAD_ARG);
+ CHK(senc_descriptor_get_frontier_segments_count(desc, &count) == RES_OK);
+
+ CHK(senc_descriptor_get_frontier_segment(NULL, count, NULL) == RES_BAD_ARG);
+ CHK(senc_descriptor_get_frontier_segment(desc, count, NULL) == RES_BAD_ARG);
+ CHK(senc_descriptor_get_frontier_segment(NULL, 0, NULL) == RES_BAD_ARG);
+ CHK(senc_descriptor_get_frontier_segment(NULL, count, indices) == RES_BAD_ARG);
+ CHK(senc_descriptor_get_frontier_segment(desc, 0, NULL) == RES_BAD_ARG);
+ CHK(senc_descriptor_get_frontier_segment(desc, count, indices) == RES_BAD_ARG);
+ CHK(senc_descriptor_get_frontier_segment(NULL, 0, indices) == RES_BAD_ARG);
+ CHK(senc_descriptor_get_frontier_segment(desc, 0, indices) == RES_OK);
+
+ CHK(senc_scene_ref_put(scn) == RES_OK);
+ CHK(senc_device_ref_put(dev) == RES_OK);
+ if(desc) CHK(senc_descriptor_ref_put(desc) == RES_OK);
+
check_memory_allocator(&allocator);
mem_shutdown_proxy_allocator(&allocator);
CHK(mem_allocated_size() == 0);