commit 9c87673427c85a3940eb8cdaba15d0eb67b11956
parent 29812324a77e30c230a35f68b3ab7221d487affa
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Tue, 12 Mar 2019 15:43:36 +0100
Merge branch 'release_0.3.0'
Diffstat:
10 files changed, 280 insertions(+), 83 deletions(-)
diff --git a/README.md b/README.md
@@ -39,6 +39,12 @@ variable the install directories of its dependencies.
Release notes
-------------
+### Version 0.3
+
+- Add API calls to access to geometry frontiers.
+- Improve documentation in the header file.
+- BugFix: wrong data cleaning on computation canceling.
+
### Version 0.2.2
- BugFix when grouping components into enclosures.
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -47,8 +47,8 @@ endif()
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
-set(VERSION_MINOR 2)
-set(VERSION_PATCH 2)
+set(VERSION_MINOR 3)
+set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(SENC_FILES_SRC
diff --git a/src/senc.h b/src/senc.h
@@ -144,6 +144,7 @@ senc_device_ref_put
* StarEnclosures scene. A scene is a collection of triangles. Each triangle is
* defined with a medium on each side.
******************************************************************************/
+/* Creates an empty scene */
SENC_API res_T
senc_scene_create
(struct senc_device* device,
@@ -155,7 +156,8 @@ senc_scene_create
* Triangles can be duplicates as long as they constantly define the same
* medium on both sides (or an error will be reported) and are deduplicated.
* When deduplicating triangles, the first occurence is kept (with it original
- * global_id). */
+ * global_id). Users can provide their own global ids for triangles; these ids
+ * are not used by the library but are returned as-is by some API calls. */
SENC_API res_T
senc_scene_add_geometry
(struct senc_scene* scene,
@@ -168,31 +170,39 @@ senc_scene_add_geometry
void(*position)(const unsigned ivert, double pos[3], void* context),
void* context);
+/* Returns a descriptor of the scene that holds the analysis' result. */
SENC_API res_T
senc_scene_analyze
(struct senc_scene* scene,
struct senc_descriptor** descriptor);
+/* Returns the convention flags in use with the scene. */
SENC_API res_T
senc_scene_get_convention
(const struct senc_scene* scene,
enum senc_convention* convention);
+/* Returns the number of triangles in the scene. */
SENC_API res_T
senc_scene_get_triangles_count
(const struct senc_scene* scene,
unsigned* count);
+/* Returns the number of unique triangles in the scene (remaining
+ * triangles after deduplication). */
SENC_API res_T
senc_scene_get_unique_triangles_count
(const struct senc_scene* scene,
unsigned* count);
+/* Returns the number of vertices in the scene. */
SENC_API res_T
senc_scene_get_vertices_count
(const struct senc_scene* scene,
unsigned* count);
+/* Returns the number of unique vertices in the scene (remaining
+ * vertices after deduplication). */
SENC_API res_T
senc_scene_get_unique_vertices_count
(const struct senc_scene* scene,
@@ -209,28 +219,36 @@ senc_scene_ref_put
/*******************************************************************************
* StarEnclosures descriptor. It is an handle toward an analyze result.
******************************************************************************/
+/* Returns the greater medium id found in added geometry. In API calls using a
+ * medium, any value in the [0 max_medium_id[ range is valid. However there can
+ * be unused ids (no geometry refered to this medium id). */
SENC_API res_T
senc_descriptor_get_max_medium
(const struct senc_descriptor* descriptor,
unsigned* max_medium_id);
+/* Returns the number of enclosures. */
SENC_API res_T
senc_descriptor_get_enclosure_count
(const struct senc_descriptor* descriptor,
unsigned* count);
+/* Returns the number of enclosures that have some geometry refering to the
+ * imed_th medium. */
SENC_API res_T
senc_descriptor_get_enclosure_count_by_medium
(const struct senc_descriptor* descriptor,
- const unsigned imed, /* Must be in [0 max_medium_id] */
+ const unsigned imed,
unsigned* count);
+/* Returns the idx_th enclosure. */
SENC_API res_T
senc_descriptor_get_enclosure
(struct senc_descriptor* descriptor,
const unsigned idx,
struct senc_enclosure** enclosure);
+/* Returns the idx_th enclosure using the imed_th medium. */
SENC_API res_T
senc_descriptor_get_enclosure_by_medium
(struct senc_descriptor* descriptor,
@@ -238,46 +256,75 @@ senc_descriptor_get_enclosure_by_medium
const unsigned idx,
struct senc_enclosure** enclosure);
+/* Returns the number of unique triangles (no duplicates here) in the whole
+ * geometry. */
SENC_API res_T
senc_descriptor_get_global_triangles_count
(const struct senc_descriptor* descriptor,
- unsigned* count); /* Number of unique triangles. */
+ unsigned* count);
+/* Returns the number of unique vertices (no duplicates here) in the whole
+ * geometry. */
SENC_API res_T
senc_descriptor_get_global_vertices_count
(const struct senc_descriptor* descriptor,
unsigned* count); /* Number of unique vertices. */
+/* Returns the itri_th global unique triangles; the returned indices are global
+ * unique vertex indices. */
SENC_API res_T
senc_descriptor_get_global_triangle
(const struct senc_descriptor* descriptor,
const unsigned itri,
unsigned indices[3]);
+/* Returns the coordinates of the ivert_th global unique vertex. */
SENC_API res_T
senc_descriptor_get_global_vertex
(const struct senc_descriptor* descriptor,
const unsigned ivert,
double coord[3]);
+/* Returns the front and back media ids of the itri_th global unique
+ * triangles. */
SENC_API res_T
senc_descriptor_get_global_triangle_media
(const struct senc_descriptor* descriptor,
const unsigned itri,
unsigned media[2]);
+/* Returns the enclosures the itri_th global unique triangles front and back
+ * sides are member of. */
SENC_API res_T
senc_descriptor_get_global_triangle_enclosures
(const struct senc_descriptor* descriptor,
const unsigned itri,
unsigned enclosures[2]);
+/* Returns the global id of the itri_th global unique triangles, either the
+ * user provided one or the default one. */
SENC_API res_T
senc_descriptor_get_global_triangle_global_id
(const struct senc_descriptor* descriptor,
const unsigned itri,
unsigned* gid);
+/* Returns the number of segments that are frontier segments:
+ * - that have arity 1 (single triangle using the segment)
+ * - that connect 2 different media */
+SENC_API res_T
+senc_descriptor_get_frontier_segments_count
+ (const struct senc_descriptor* descriptor,
+ unsigned* count);
+
+/* Returns the iseg_th frontier segment; the returned indices are global unique
+ * vertex indices. */
+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);
@@ -293,39 +340,49 @@ senc_descriptor_ref_put
* An enclosure can list the "same" triangle twice if both sides are in. In this
* case the 2 occurences of the triangle have reversed vertices order and
* unique_triangle_count and triangle_count differ.
+ * Vertices and triangles numbering schemes are specific to each enclosure:
+ * the "same" item appearing in 2 different enclosures has no reason to get the
+ * same index twice or to have the same index in the global numbering scheme.
* By-index API accesses of triangles (or properties) visit unique triangles
- * for indexes in the [0 unique_triangle_count[ range and back-faces of the
- * doubly-listed triangles in the [unique_triangle_count triangle_count[ range.
+ * for indices in the [0 unique_triangle_count[ range and back-faces of the
+ * doubly-included triangles in the [unique_triangle_count triangle_count[ range.
******************************************************************************/
+/* Returns the header of an enclosure. */
SENC_API res_T
senc_enclosure_get_header
(const struct senc_enclosure* enclosure,
struct senc_enclosure_header* header);
+/* Returns the itri_th triangle of an enclosure. */
SENC_API res_T
senc_enclosure_get_triangle
(const struct senc_enclosure* enclosure,
const unsigned itri,
unsigned indices[3]);
+/* Returns the coordinates of the ivert_th vertex of an enclosure. */
SENC_API res_T
senc_enclosure_get_vertex
(const struct senc_enclosure* enclosure,
const unsigned ivert,
double coord[3]);
+/* Returns the front and back side media ids of the itri_th triangle of an
+ * enclosure. */
SENC_API res_T
senc_enclosure_get_triangle_media
(const struct senc_enclosure* enclosure,
const unsigned itri,
unsigned medium[2]);
+/* Returns the global id of the itri_th triangle of an enclosure. */
SENC_API res_T
senc_enclosure_get_triangle_global_id
(const struct senc_enclosure* enclosure,
const unsigned itri,
unsigned* gid);
+/* Returns the id of the imed_th medium of an enclosure. */
SENC_API res_T
senc_enclosure_get_medium
(const struct senc_enclosure* enclosure,
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"
@@ -143,7 +142,7 @@ extract_connex_components
struct s3d_scene_view** s3d_view,
ATOMIC* component_count,
/* Shared error status.
- * We accept to overwritte an error with a different error */
+ * We accept to overwrite an error with a different error */
res_T* p_res)
{
/* This function is called from an omp parallel block and executed
@@ -326,6 +325,18 @@ extract_connex_components
* associated with neighbour's medium). */
component_canceled = 1;
darray_side_id_clear(&stack);
+ /* Reverse the used flag for sides in cancelled component */
+ sz = darray_side_id_size_get(¤t_component);
+ FOR_EACH(ii, 0, sz) {
+ side_id_t used_side
+ = darray_side_id_cdata_get(¤t_component)[ii];
+ trg_id_t used_trg_id = TRGSIDE_2_TRG(used_side);
+ enum side_flag used_side_flag
+ = TRGSIDE_2_SIDEFLAG(used_side);
+ unsigned char* used = processed + used_trg_id;
+ ASSERT(*used & (unsigned char)used_side_flag);
+ *used &= 0xFF ^ (unsigned char)used_side_flag;
+ }
goto canceled;
}
/* Mark neighbour as processed and stack it */
@@ -367,7 +378,7 @@ extract_connex_components
/* Write component membership in the global structure
* No need for sync here as an unique thread write a given side */
- STATIC_ASSERT(sizeof(cc->cc_id) >= 4, Cannot_write_IDs_sync_free);
+ {STATIC_ASSERT(sizeof(cc->cc_id) >= 4, Cannot_write_IDs_sync_free);}
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(¤t_component)[ii];
@@ -380,6 +391,7 @@ extract_connex_components
/* Compute the normal at the max_z vertex. */
max_nz = 0;
sz = darray_side_id_size_get(&ids_of_sides_around_max_z_vertex);
+ ASSERT(sz > 0);
FOR_EACH(ii, 0, sz) {
const side_id_t side_id =
darray_side_id_cdata_get(&ids_of_sides_around_max_z_vertex)[ii];
@@ -395,7 +407,7 @@ 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 == x can be false). */
- ASSERT(trg_comp->component[s] == cc->cc_id);
+ ASSERT(trg_comp->component[s] == cc->cc_id); (void)s;
if(trg_comp->component[SIDE_FRONT] == trg_comp->component[SIDE_BACK])
continue;
@@ -524,7 +536,7 @@ group_connex_components
struct s3d_scene_view* s3d_view,
ATOMIC* next_enclosure_id,
/* Shared error status.
- * We accept to overwritte an error with a different error */
+ * We accept to overwrite an error with a different error */
res_T* res)
{
/* This function is called from an omp parallel block and executed
@@ -595,8 +607,9 @@ group_connex_components
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 */
+ /* Warning: following Embree 2 convention for geometrical normals,
+ * the Star3D hit normal is left-handed while star-enclosure uses
+ * right-handed convention */
? SIDE_BACK : SIDE_FRONT;
ASSERT(hit.normal[2] != 0);
ASSERT(hit_trg_id < desc->scene->nutris);
@@ -659,8 +672,9 @@ 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 overwritte an error with a different error */
+ * We accept to overwrite an error with a different error */
res_T* res)
{
/* This function is called from an omp parallel block and executed
@@ -684,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);
@@ -769,7 +783,7 @@ collect_and_link_neighbours
struct darray_neighbour* neighbour_list = &neighbourhood->neighbours;
side_id_t i, neighbour_count;
sz = darray_neighbour_size_get(neighbour_list);
- ASSERT(sz <= SIDE_MAX__);
+ ASSERT(sz > 0 && sz <= SIDE_MAX__);
neighbour_count = (side_id_t)sz;
ASSERT(neighbour_count);
v0 = neighbourhood->edge.vrtx0;
@@ -866,16 +880,23 @@ collect_and_link_neighbours
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);
+ "%s: found 2 overlying triangles (%lu & %lu).\n", FUNC_NAME,
+ (unsigned long)triangles_in[crt_id].global_id,
+ (unsigned long)triangles_in[prev_id].global_id);
tmp_res = RES_BAD_OP;
goto tmp_error;
}
a = current->angle;
/* Link sides */
+ ASSERT(p_crt_side->facing_side_id[crt_edge] == SIDE_NULL__);
+ ASSERT(p_ccw_side->facing_side_id[ccw_edge] == SIDE_NULL__);
p_crt_side->facing_side_id[crt_edge] = ccw_side_idx;
p_ccw_side->facing_side_id[ccw_edge] = crt_side_idx;
/* Record media */
+ ASSERT(p_crt_side->medium == MEDIUM_NULL__
+ || p_crt_side->medium == triangles_in[crt_id].medium[crt_side]);
+ ASSERT(p_ccw_side->medium == MEDIUM_NULL__
+ || p_ccw_side->medium == triangles_in[ccw_id].medium[ccw_side]);
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);
@@ -885,10 +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 %u.\n",
- FUNC_NAME, crt_id);
+ "%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);
}
}
}
@@ -904,8 +930,9 @@ 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 overwritte an error with a different error */
+ * We accept to overwrite an error with a different error */
res_T* res)
{
/* This function is called from an omp parallel block and executed
@@ -922,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;
@@ -930,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);
@@ -949,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];
@@ -1097,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 */
}
/*******************************************************************************
@@ -1113,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;
@@ -1137,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
@@ -1145,13 +1182,22 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
res = RES_MEM_ERR;
goto error;
}
+#ifndef NDEBUG
+ else {
+ /* Initialise trgsides to allow assert code */
+ size_t i;
+ FOR_EACH(i, 0, 2 * scn->nutris)
+ init_trgside(scn->dev->allocator, trgsides + i);
+ }
+#endif
/* The end of the analyze is multithreaded */
ASSERT(scn->dev->nthreads > 0);
#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 */
@@ -1239,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 */
@@ -1280,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,68 +18,21 @@
#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)
+init_trgside(struct mem_allocator* alloc, struct trgside* data)
{
- 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;
+ int i;
+ ASSERT(data); (void)alloc;
+ FOR_EACH(i, 0, 3) data->facing_side_id[i] = SIDE_NULL__;
+ data->medium = MEDIUM_NULL__;
}
-/* 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;
- /* The list containing the trgside; made of enum list_id flags */
- unsigned char list_id;
-
- /* 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 side_id
#define DARRAY_DATA side_id_t
#include <rsys/dynamic_array.h>
diff --git a/src/test_senc_descriptor.c b/src/test_senc_descriptor.c
@@ -164,6 +164,17 @@ main(int argc, char** argv)
CHK(enclosures[0] == 0
&& enclosures[1] == 1);
+ CHK(senc_descriptor_get_global_triangle_global_id(NULL, 0, indices)
+ == RES_BAD_ARG);
+ CHK(senc_descriptor_get_global_triangle_global_id(NULL, nvertices, indices)
+ == RES_BAD_ARG);
+ CHK(senc_descriptor_get_global_triangle_global_id(desc, 0, NULL)
+ == RES_BAD_ARG);
+ CHK(senc_descriptor_get_global_triangle_global_id(desc, 0, indices)
+ == RES_OK);
+ /* No duplicates and no custom id: user id is unique vertex id */
+ CHK(indices[0] == 0);
+
/* Add valid duplicate geometry */
CHK(senc_descriptor_ref_put(desc) == RES_OK);
desc = NULL;
@@ -188,10 +199,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);
diff --git a/src/test_senc_scene.c b/src/test_senc_scene.c
@@ -206,7 +206,7 @@ main(int argc, char** argv)
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
nvertices, get_position, &ctx) == RES_BAD_ARG);
- /* It is OK dd geometry after a failed add */
+ /* It is OK add geometry after a failed add */
ctx.back_media = medium1;
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
nvertices, get_position, &ctx) == RES_OK);