commit cf7e02233ee52e2de9acfd037b8efe1576455d09
parent d8f9b28fbbd7a20a3f231db809b3dc8fa5ae595e
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Tue, 5 Nov 2019 11:22:05 +0100
Merge branch 'release_0.4.0'
Diffstat:
24 files changed, 1235 insertions(+), 432 deletions(-)
diff --git a/README.md b/README.md
@@ -39,6 +39,15 @@ variable the install directories of its dependencies.
Release notes
-------------
+### Version 0.4
+
+- Change signature of the senc_scene_add_geometry API. Thus this release
+ is **not compatible** with previous ones.
+ The global_id callback that was ill-defined is removed and 2 callbacks
+ are added to manage client-app data when deduplicating geometry.
+ These 2 callback allow a proper client-app management of global ids.
+- Remove execution time for analysis steps from the log.
+
### Version 0.3.1
- Performance Fix: when a connex component was canceled by a thread the
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -24,8 +24,8 @@ option(NO_TEST "Do not build tests" OFF)
# Check dependencies
################################################################################
find_package(RCMake 0.4 REQUIRED)
-find_package(Star3D 0.5 REQUIRED)
-find_package(RSys 0.6.1 REQUIRED)
+find_package(Star3D 0.6 REQUIRED)
+find_package(RSys 0.8.1 REQUIRED)
find_package(OpenMP 2.0 REQUIRED)
if(NOT NO_TEST)
@@ -47,8 +47,8 @@ endif()
# Configure and define targets
################################################################################
set(VERSION_MAJOR 0)
-set(VERSION_MINOR 3)
-set(VERSION_PATCH 1)
+set(VERSION_MINOR 4)
+set(VERSION_PATCH 0)
set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH})
set(SENC_FILES_SRC
@@ -131,6 +131,8 @@ if(NOT NO_TEST)
new_test(test_senc_many_triangles)
new_test(test_senc_sample_enclosure)
new_test(test_senc_scene)
+ new_test(test_senc_undefined_medium)
+ new_test(test_senc_undefined_medium_attr)
target_link_libraries(test_senc_sample_enclosure StarSP)
target_link_libraries(test_senc_many_enclosures Star3DUT)
diff --git a/src/senc.h b/src/senc.h
@@ -18,6 +18,8 @@
#include <rsys/rsys.h>
+#include <limits.h>
+
/* Library symbol management */
#if defined(SENC_SHARED_BUILD)
#define SENC_API extern EXPORT_SYM
@@ -40,6 +42,9 @@
* as CPU cores */
#define SENC_NTHREADS_DEFAULT (~0u)
+/* A constant to specify an undefined medium */
+#define SENC_UNDEFINED_MEDIUM UINT_MAX
+
/* Forward declaration of external opaque data types */
struct logger;
struct mem_allocator;
@@ -56,6 +61,12 @@ struct senc_device;
struct senc_scene;
struct senc_enclosure;
+/* A type to discriminate triangle sides */
+enum senc_side {
+ SENC_FRONT,
+ SENC_BACK
+};
+
/* Enclosure header type */
struct senc_enclosure_header {
/* The ID of the enclosure; 0, 1, ... */
@@ -66,7 +77,8 @@ struct senc_enclosure_header {
unsigned unique_triangle_count;
/* Number of vertices */
unsigned vertices_count;
- /* The number of media inside the enclosure */
+ /* The number of media inside the enclosure,
+ * SENC_UNDEFINED_MEDIUM included */
unsigned enclosed_media_count;
/* Is the enclosure open/infinite?
* Only the outermost enclosure is infinite. */
@@ -148,26 +160,55 @@ senc_device_ref_put
SENC_API res_T
senc_scene_create
(struct senc_device* device,
- const enum senc_convention convention,
+ const int convention,
struct senc_scene** scene);
+/* Reserve memory according to anticipated scene size. */
+SENC_API res_T
+senc_scene_reserve
+ (struct senc_scene* scene,
+ const unsigned vertices_count,
+ const unsigned triangles_count,
+ const unsigned media_count);
+
/* Add a new set of vertices and triangles to the scene.
* Vertices can be duplicates and are deduplicated on the fly.
* 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). 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. */
+ * medium on both sides (or an error will be reported, with the exception
+ * of SENC_UNDEFINED_MEDIUM that causes no error) and are deduplicated.
+ * The special value SENC_UNDEFINED_MEDIUM denotes an undefined medium.
+ * It can be used to define the 2 sides of a triangle at different times.
+ * When deduplicating triangles, the first occurence remains.
+ * The add_triangle and merge_triangle callbacks can be used for attributes
+ * management including triangle IDs; they allow the client app to store
+ * its own data. They can also fail and stop the add_geometry call. */
SENC_API res_T
senc_scene_add_geometry
(struct senc_scene* scene,
+ /* Number of added triangles */
const unsigned triangles_count,
+ /* User function that provides vertices ids for added triangles */
void(*indices)(const unsigned itri, unsigned ids[3], void* context),
- void(*media)(const unsigned itri, unsigned med[2], void* context),
- void(*global_id) /* May be NULL <=> use triangle rank */
- (const unsigned itri, unsigned* gid, void* context),
+ /* User function that provides media ids for added triangles */
+ void(*media) /* Can be NULL <=> SENC_UNDEFINED_MEDIUM medium used */
+ (const unsigned itri, unsigned med[2], void* context),
+ /* Number of added vertices */
const unsigned vertices_count,
+ /* User function that provides coordinates for added vertices */
void(*position)(const unsigned ivert, double pos[3], void* context),
+ /* Called for each new triangle so that the client app can manage its own
+ * triangle data/properties/attributes.
+ * If return is not RES_OK, add_geometry stops and fails. */
+ res_T(*add_triangle) /* Can be NULL */
+ (const unsigned global_id, const unsigned itri, void* context),
+ /* Called if the IVERTth triangle of the current add_geometry is equal to
+ * the global_id_th global triangle so that the client app can try to merge
+ * its own triangle data. The reversed_triangle arg indicates if the triangle
+ * vertices' order is the same it was when the triangle was first added.
+ * If return is not RES_OK, add_geometry stops and fails. */
+ res_T(*merge_triangle) /* Can be NULL */
+ (const unsigned global_id, const unsigned itri, const int reversed_triangle,
+ void* context),
void* context);
/* Returns a descriptor of the scene that holds the analysis' result. */
@@ -180,7 +221,7 @@ senc_scene_analyze
SENC_API res_T
senc_scene_get_convention
(const struct senc_scene* scene,
- enum senc_convention* convention);
+ int* convention);
/* Returns the number of triangles in the scene. */
SENC_API res_T
@@ -195,6 +236,30 @@ senc_scene_get_unique_triangles_count
(const struct senc_scene* scene,
unsigned* count);
+/* Returns the number of unique sides with SENC_UNDEFINED_MEDIUM medium. */
+SENC_API res_T
+senc_scene_get_unique_sides_without_medium_count
+ (const struct senc_scene* scene,
+ unsigned* count);
+
+/* Returns the itri_th unique triangle; the returned indices are
+ * unique vertex indices.
+ * Can be called anytime, before or after a call to analyze. */
+SENC_API res_T
+senc_scene_get_unique_triangle
+ (const struct senc_scene* scene,
+ const unsigned itri,
+ unsigned indices[3]);
+
+/* Returns the itri_th unique triangle; the returned indices are
+ * unique vertex indices.
+ * Can be called anytime, before or after a call to analyze. */
+SENC_API res_T
+senc_scene_get_unique_triangle_media
+ (const struct senc_scene* scene,
+ const unsigned itri,
+ unsigned media[2]);
+
/* Returns the number of vertices in the scene. */
SENC_API res_T
senc_scene_get_vertices_count
@@ -208,6 +273,14 @@ senc_scene_get_unique_vertices_count
(const struct senc_scene* scene,
unsigned* count);
+/* Returns the coordinates of the ivert_th unique vertex.
+ * Can be called anytime, before or after a call to analyze. */
+SENC_API res_T
+senc_scene_get_unique_vertex
+ (const struct senc_scene* scene,
+ const unsigned ivert,
+ double coord[3]);
+
SENC_API res_T
senc_scene_ref_get
(struct senc_scene* scene);
@@ -301,14 +374,6 @@ senc_descriptor_get_global_triangle_enclosures
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 */
@@ -353,7 +418,8 @@ senc_enclosure_get_header
(const struct senc_enclosure* enclosure,
struct senc_enclosure_header* header);
-/* Returns the itri_th triangle of an enclosure. */
+/* Returns the itri_th triangle of an enclosure.
+ * Indices are local to the enclosure. */
SENC_API res_T
senc_enclosure_get_triangle
(const struct senc_enclosure* enclosure,
@@ -367,20 +433,14 @@ senc_enclosure_get_vertex
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. */
+/* Returns the global id of the itri_th triangle of an enclosure
+ * and the involved side. */
SENC_API res_T
senc_enclosure_get_triangle_global_id
(const struct senc_enclosure* enclosure,
const unsigned itri,
- unsigned* gid);
+ unsigned* gid,
+ enum senc_side* side);
/* Returns the id of the imed_th medium of an enclosure. */
SENC_API res_T
diff --git a/src/senc_descriptor.c b/src/senc_descriptor.c
@@ -61,7 +61,8 @@ descriptor_create(struct senc_scene* scn)
darray_enclosure_init(scn->dev->allocator, &desc->enclosures);
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));
+ OK(darray_enc_ids_array_resize(&desc->enc_ids_array_by_medium,
+ 1 + scn->next_medium_idx)); /* +1 is for undef */
darray_frontier_edge_init(scn->dev->allocator, &desc->frontiers);
/* Enclosure 0 is always defined for infinite */
OK(darray_enclosure_resize(&desc->enclosures, 1));
@@ -91,8 +92,8 @@ senc_descriptor_get_max_medium
(const struct senc_descriptor* desc, unsigned* max_medium_id)
{
if(!desc || !max_medium_id) return RES_BAD_ARG;
- ASSERT(desc->scene->nmeds < UINT_MAX); /* API type */
- *max_medium_id = (unsigned)desc->scene->nmeds - 1;
+ ASSERT(desc->scene->next_medium_idx < UINT_MAX); /* API type */
+ *max_medium_id = (unsigned)desc->scene->next_medium_idx - 1;
return RES_OK;
}
@@ -115,13 +116,16 @@ senc_descriptor_get_enclosure_count_by_medium
const unsigned imed,
unsigned* count)
{
- size_t tmp;
+ size_t tmp, m_idx;
const struct darray_enc_id* enc_ids;
- if(!desc || !count || imed >= desc->scene->nmeds)
+ if(!desc || !count
+ || (imed != SENC_UNDEFINED_MEDIUM && imed >= desc->scene->next_medium_idx))
return RES_BAD_ARG;
ASSERT(darray_enc_ids_array_size_get(&desc->enc_ids_array_by_medium)
- == desc->scene->nmeds);
- enc_ids = darray_enc_ids_array_cdata_get(&desc->enc_ids_array_by_medium) + imed;
+ == 1 + desc->scene->next_medium_idx);
+ m_idx = (imed == SENC_UNDEFINED_MEDIUM) ? desc->scene->next_medium_idx : imed;
+ enc_ids = darray_enc_ids_array_cdata_get(&desc->enc_ids_array_by_medium)
+ + m_idx;
tmp = darray_enc_id_size_get(enc_ids);
ASSERT(tmp < UINT_MAX); /* API type */
*count = (unsigned)tmp;
@@ -150,11 +154,17 @@ senc_descriptor_get_enclosure_by_medium
const unsigned idx,
struct senc_enclosure** out_enc)
{
+ size_t m_idx;
const struct darray_enc_id* enc_ids;
unsigned index;
- if(!desc || imed >= desc->scene->nmeds || !out_enc) return RES_BAD_ARG;
+ if(!desc || !out_enc
+ || (imed != SENC_UNDEFINED_MEDIUM && imed >= desc->scene->next_medium_idx))
+ return RES_BAD_ARG;
+ ASSERT(darray_enc_ids_array_size_get(&desc->enc_ids_array_by_medium)
+ == 1 + desc->scene->next_medium_idx);
+ m_idx = (imed == SENC_UNDEFINED_MEDIUM) ? desc->scene->next_medium_idx : imed;
enc_ids =
- darray_enc_ids_array_cdata_get(&desc->enc_ids_array_by_medium) + imed;
+ darray_enc_ids_array_cdata_get(&desc->enc_ids_array_by_medium) + m_idx;
if(idx >= darray_enc_id_size_get(enc_ids)) return RES_BAD_ARG;
index = darray_enc_id_cdata_get(enc_ids)[idx];
return senc_descriptor_get_enclosure(desc, index, out_enc);
@@ -262,21 +272,6 @@ senc_descriptor_get_global_triangle_enclosures
}
res_T
-senc_descriptor_get_global_triangle_global_id
- (const struct senc_descriptor* desc,
- const unsigned itri,
- unsigned* gid)
-{
- const struct triangle_in* trg;
- if(!gid || !desc
- || itri >= darray_triangle_in_size_get(&desc->scene->triangles_in))
- return RES_BAD_ARG;
- trg = darray_triangle_in_cdata_get(&desc->scene->triangles_in) + itri;
- *gid = trg->global_id;
- return RES_OK;
-}
-
-res_T
senc_descriptor_get_frontier_segments_count
(const struct senc_descriptor* desc,
unsigned* count)
diff --git a/src/senc_enclosure.c b/src/senc_enclosure.c
@@ -81,17 +81,17 @@ senc_enclosure_get_triangle
const unsigned itri,
unsigned indices[3])
{
- const struct triangle_in* triangle;
+ const struct side_enc* side;
int i;
if(!enclosure || !indices
|| itri >= enclosure->data->header.triangle_count)
return RES_BAD_ARG;
- ASSERT(darray_triangle_in_size_get(&enclosure->data->sides)
+ ASSERT(darray_sides_enc_size_get(&enclosure->data->sides)
== enclosure->data->header.triangle_count);
- triangle = darray_triangle_in_cdata_get(&enclosure->data->sides) + itri;
+ side = darray_sides_enc_cdata_get(&enclosure->data->sides) + itri;
FOR_EACH(i, 0, 3) {
- ASSERT(triangle->vertice_id[i] < UINT_MAX);
- indices[i] = (unsigned)triangle->vertice_id[i]; /* Back to API type */
+ ASSERT(side->vertice_id[i] < UINT_MAX);
+ indices[i] = (unsigned)side->vertice_id[i]; /* Back to API type */
}
return RES_OK;
}
@@ -118,42 +118,21 @@ senc_enclosure_get_vertex
}
res_T
-senc_enclosure_get_triangle_media
- (const struct senc_enclosure* enclosure,
- const unsigned itri,
- unsigned medium[2])
-{
- const struct triangle_in* triangle;
- int i;
- if(!enclosure || !medium
- || itri >= enclosure->data->header.triangle_count)
- return RES_BAD_ARG;
- ASSERT(darray_triangle_in_size_get(&enclosure->data->sides)
- == enclosure->data->header.triangle_count);
- triangle = darray_triangle_in_cdata_get(&enclosure->data->sides) + itri;
- FOR_EACH(i, 0, 2) {
-#if (UINT_MAX < MEDIUM_MAX__)
- ASSERT(triangle->medium[i] < UINT_MAX);
-#endif
- medium[i] = (unsigned)triangle->medium[i]; /* Back to API type */
- }
- return RES_OK;
-}
-
-res_T
senc_enclosure_get_triangle_global_id
(const struct senc_enclosure* enclosure,
const unsigned itri,
- unsigned* gid)
+ unsigned* gid,
+ enum senc_side* sde)
{
- const struct triangle_in* triangle;
- if(!enclosure || !gid
+ const struct side_enc* side;
+ if(!enclosure || !gid || !sde
|| itri >= enclosure->data->header.triangle_count)
return RES_BAD_ARG;
- ASSERT(darray_triangle_in_size_get(&enclosure->data->sides)
+ ASSERT(darray_sides_enc_size_get(&enclosure->data->sides)
== enclosure->data->header.triangle_count);
- triangle = darray_triangle_in_cdata_get(&enclosure->data->sides) + itri;
- *gid = triangle->global_id;
+ side = darray_sides_enc_cdata_get(&enclosure->data->sides) + itri;
+ *gid = (unsigned)TRGSIDE_2_TRG(side->side_id);
+ *sde = TRGSIDE_2_SIDE(side->side_id);
return RES_OK;
}
diff --git a/src/senc_enclosure_data.h b/src/senc_enclosure_data.h
@@ -21,6 +21,21 @@
#include <rsys/hash_table.h>
#include <rsys/dynamic_array.h>
+#include "senc.h"
+#include "senc_scene_c.h"
+#include "senc_internal_types.h"
+
+#include <limits.h>
+
+struct side_enc {
+ vrtx_id_t vertice_id[3];
+ side_id_t side_id;
+};
+
+#define DARRAY_NAME sides_enc
+#define DARRAY_DATA struct side_enc
+#include <rsys/dynamic_array.h>
+
/* unsigned char array with init to zero */
static FINLINE void
zero_init_uchar
@@ -32,12 +47,6 @@ zero_init_uchar
#define DARRAY_FUNCTOR_INIT zero_init_uchar
#include <rsys/dynamic_array_uchar.h>
-#include "senc.h"
-#include "senc_scene_c.h"
-#include "senc_internal_types.h"
-
-#include <limits.h>
-
static void
init_header(struct senc_enclosure_header* header)
{
@@ -83,23 +92,24 @@ error:
static FINLINE res_T
bool_array_of_media_to_darray_media
(struct darray_media* dst,
- struct darray_uchar* src)
+ const struct darray_uchar* src,
+ const medium_id_t undef_idx)
{
res_T res = RES_OK;
medium_id_t i;
- size_t sz;
const unsigned char* data;
ASSERT(src && dst);
data = darray_uchar_cdata_get(src);
- sz = darray_uchar_size_get(src);
- ASSERT(sz <= MEDIUM_MAX__);
+ ASSERT(undef_idx + 1 == darray_uchar_size_get(src));
+ ASSERT(undef_idx < MEDIUM_MAX__);
darray_media_clear(dst);
if(res != RES_OK) goto error;
- FOR_EACH(i, 0, (medium_id_t)sz) {
+ FOR_EACH(i, 0, undef_idx + 1) {
+ medium_id_t v = (i == undef_idx) ? SENC_UNDEFINED_MEDIUM : i;
if(!data[i]) continue;
- res = darray_media_push_back(dst, &i);
+ res = darray_media_push_back(dst, &v);
if(res != RES_OK) goto error;
}
end:
@@ -111,7 +121,7 @@ error:
struct enclosure_data {
struct senc_enclosure_header header;
/* Same triangle can appear twice if both sides */
- struct darray_triangle_in sides;
+ struct darray_sides_enc sides;
/* Index of vertices in scene's unique vertices */
struct darray_vrtx_id vertices;
/* List of the enclosed media */
@@ -136,7 +146,7 @@ enclosure_data_init(struct mem_allocator* alloc, struct enclosure_data* enc) {
enc->side_range.first = SIDE_NULL__;
enc->side_range.last = 0;
enc->side_count = 0;
- darray_triangle_in_init(alloc, &enc->sides);
+ darray_sides_enc_init(alloc, &enc->sides);
darray_vrtx_id_init(alloc, &enc->vertices);
darray_uchar_init(alloc, &enc->tmp_enclosed_media);
darray_media_init(alloc, &enc->enclosed_media);
@@ -154,7 +164,7 @@ enclosure_data_copy
dst->first_component = src->first_component;
dst->side_range = src->side_range;
dst->side_count = src->side_count;
- OK(darray_triangle_in_copy(&dst->sides, &src->sides));
+ OK(darray_sides_enc_copy(&dst->sides, &src->sides));
OK(darray_vrtx_id_copy(&dst->vertices, &src->vertices));
OK(darray_uchar_copy(&dst->tmp_enclosed_media, &src->tmp_enclosed_media));
OK(darray_media_copy(&dst->enclosed_media, &src->enclosed_media));
@@ -165,7 +175,7 @@ error:
static FINLINE void
enclosure_data_release(struct enclosure_data* n) {
ASSERT(n);
- darray_triangle_in_release(&n->sides);
+ darray_sides_enc_release(&n->sides);
darray_vrtx_id_release(&n->vertices);
darray_uchar_release(&n->tmp_enclosed_media);
darray_media_release(&n->enclosed_media);
@@ -183,7 +193,7 @@ enclosure_data_copy_and_release
dst->first_component = src->first_component;
dst->side_range = src->side_range;
dst->side_count = src->side_count;
- OK(darray_triangle_in_copy_and_release(&dst->sides, &src->sides));
+ OK(darray_sides_enc_copy_and_release(&dst->sides, &src->sides));
OK(darray_vrtx_id_copy_and_release(&dst->vertices, &src->vertices));
OK(darray_uchar_copy_and_release(&dst->tmp_enclosed_media,
&src->tmp_enclosed_media));
diff --git a/src/senc_internal_types.h b/src/senc_internal_types.h
@@ -95,12 +95,6 @@ enum side_flag {
FLAG_BACK = BIT(1)
};
-/* This one is used as an index to arrays */
-enum side_id {
- SIDE_FRONT = 0,
- SIDE_BACK = 1
-};
-
/* Utility macros */
static FINLINE trg_id_t
TRGSIDE_2_TRG(side_id_t s) {
@@ -113,9 +107,9 @@ TRGSIDE_IS_FRONT(side_id_t s) {
return (s & 1) == 0;
}
-static FINLINE enum side_id
+static FINLINE enum senc_side
TRGSIDE_2_SIDE(side_id_t s) {
- return (s & 1) ? SIDE_BACK : SIDE_FRONT;
+ return (s & 1) ? SENC_BACK : SENC_FRONT;
}
static FINLINE enum side_flag
@@ -123,22 +117,23 @@ TRGSIDE_2_SIDEFLAG(side_id_t s) {
return (s & 1) ? FLAG_BACK : FLAG_FRONT;
}
-static FINLINE enum side_flag
+static FINLINE unsigned char
SIDE_CANCELED_FLAG(enum side_flag f) {
- return ((unsigned char)f) << 4;
+ ASSERT((f << 4) <= UCHAR_MAX);
+ return (unsigned char)(f << 4);
}
static FINLINE side_id_t
-TRGIDxSIDE_2_TRGSIDE(trg_id_t t, enum side_id i) {
- ASSERT((((size_t)t << 1) | (i == SIDE_BACK)) < SIDE_MAX__);
- ASSERT(i == SIDE_FRONT || i == SIDE_BACK);
- return (side_id_t)((t << 1) | (i == SIDE_BACK));
+TRGIDxSIDE_2_TRGSIDE(trg_id_t t, enum senc_side i) {
+ ASSERT((((size_t)t << 1) | (i == SENC_BACK)) < SIDE_MAX__);
+ ASSERT(i == SENC_FRONT || i == SENC_BACK);
+ return (side_id_t)((t << 1) | (i == SENC_BACK));
}
static FINLINE side_id_t
TRGSIDE_OPPOSITE(side_id_t s) {
return TRGIDxSIDE_2_TRGSIDE(TRGSIDE_2_TRG(s),
- TRGSIDE_IS_FRONT(s) ? SIDE_BACK : SIDE_FRONT);
+ TRGSIDE_IS_FRONT(s) ? SENC_BACK : SENC_FRONT);
}
#endif /* SENC_INTERNAL_TYPES_H */
diff --git a/src/senc_s3d_wrapper.h b/src/senc_s3d_wrapper.h
@@ -21,7 +21,7 @@
#include <rsys/rsys.h>
#include <rsys/float3.h>
-FINLINE void
+static FINLINE void
senc_descriptor_get_global_indices__
(const unsigned itri,
unsigned indices[3],
@@ -49,7 +49,7 @@ senc_descriptor_get_global_vertices__
f3_set_d3(coord, tmp);
}
-FINLINE void
+static FINLINE void
senc_enclosure_get_triangle__
(const unsigned itri,
unsigned indices[3],
diff --git a/src/senc_scene.c b/src/senc_scene.c
@@ -18,6 +18,7 @@
#include "senc_scene_c.h"
#include <rsys/rsys.h>
+#include <rsys/double3.h>
#include <rsys/mem_allocator.h>
#include <limits.h>
@@ -42,13 +43,22 @@ scene_release(ref_T * ref)
SENC(device_ref_put(dev));
}
+static INLINE int
+compatible_medium
+ (const medium_id_t m1,
+ const medium_id_t m2)
+{
+ if(m1 == SENC_UNDEFINED_MEDIUM || m2 == SENC_UNDEFINED_MEDIUM) return 1;
+ return (m1 == m2);
+}
+
/*******************************************************************************
* Exported functions
******************************************************************************/
res_T
senc_scene_create
(struct senc_device* dev,
- const enum senc_convention conv,
+ const int conv,
struct senc_scene** out_scn)
{
struct senc_scene* scn = NULL;
@@ -73,9 +83,10 @@ senc_scene_create
scn->ngeoms = 0;
scn->ntris = 0;
scn->nutris = 0;
- scn->nmeds = 0;
+ scn->next_medium_idx = 0;
scn->nverts = 0;
scn->nuverts = 0;
+ scn->sides_with_defined_medium_count = 0;
darray_triangle_in_init(dev->allocator, &scn->triangles_in);
darray_position_init(dev->allocator, &scn->vertices);
htable_vrtx_init(dev->allocator, &scn->unique_vertices);
@@ -94,14 +105,37 @@ error:
}
res_T
+senc_scene_reserve
+ (struct senc_scene* scn,
+ const unsigned vertices_count,
+ const unsigned triangles_count,
+ const unsigned media_count)
+{
+ res_T res = RES_OK;
+ if(!scn) return RES_BAD_ARG;
+
+ OK(darray_position_reserve(&scn->vertices, vertices_count));
+ OK(darray_triangle_in_reserve(&scn->triangles_in, triangles_count));
+ OK(htable_vrtx_reserve(&scn->unique_vertices, vertices_count));
+ OK(htable_trg_reserve(&scn->unique_triangles, triangles_count));
+ OK(darray_side_range_reserve(&scn->media_use, media_count));
+
+end:
+ return res;
+error:
+ goto end;
+}
+
+res_T
senc_scene_add_geometry
(struct senc_scene* scn,
const unsigned ntris,
- void(*indices)(const unsigned itri, unsigned ids[3], void* ctx),
- void(*media)(const unsigned itri, unsigned med[2], void* ctx),
- void(*global_id)(const unsigned itri, unsigned* gid, void* context),
+ void(*indices)(const unsigned, unsigned*, void*),
+ void(*media)(const unsigned, unsigned*, void*),
const unsigned nverts,
- void(*position)(const unsigned ivert, double pos[3], void* ctx),
+ void(*position)(const unsigned, double*, void* ctx),
+ res_T(*add_triangle)(const unsigned, const unsigned, void*),
+ res_T(*merge_triangle)(const unsigned, const unsigned, const int, void*),
void* ctx)
{
struct darray_vrtx_id unique_vertice_ids;
@@ -114,7 +148,7 @@ senc_scene_add_geometry
res_T res = RES_OK;
if(!scn
- || !indices || !media || !position
+ || !indices || !position
|| !nverts || ((size_t)scn->nverts + (size_t)nverts) > VRTX_MAX__
|| !ntris || ((size_t)scn->ntris + (size_t)ntris) > TRG_MAX__)
return RES_BAD_ARG;
@@ -147,8 +181,8 @@ senc_scene_add_geometry
} else {
/* New vertex */
unique_v = scn->nuverts + actual_nuverts;
- OK(darray_position_push_back(&scn->vertices, &tmp));
ASSERT(unique_v == htable_vrtx_size_get(&scn->unique_vertices));
+ OK(darray_position_push_back(&scn->vertices, &tmp));
OK(htable_vrtx_set(&scn->unique_vertices, &tmp, &unique_v));
++actual_nuverts;
}
@@ -160,18 +194,13 @@ senc_scene_add_geometry
FOR_EACH(i, 0, ntris) {
int j;
- unsigned med[2];
+ unsigned med[2] = { SENC_UNDEFINED_MEDIUM, SENC_UNDEFINED_MEDIUM };
unsigned ind[3];
union vrtx_id3 trg_key;
- struct triangle_in tmp;
+ struct triangle_in tmp, *range_adjust_ptr = NULL;
trg_id_t* p_trg;
char reversed;
- if(global_id) {
- global_id(i, &tmp.global_id, ctx);
- } else {
- tmp.global_id = (unsigned)(scn->ntris + i);
- }
- indices(i, ind, ctx); /* API: indices needs an unsigned */
+ indices(i, ind, ctx); /* API: indices need unsigneds */
FOR_EACH(j, 0, 3) {
if(ind[j] >= nverts) {
res = RES_BAD_ARG;
@@ -187,7 +216,7 @@ senc_scene_add_geometry
const union double3* positions
= darray_position_cdata_get(&scn->vertices);
log_err(scn->dev, "%s: triangle %lu is degenerate.\n",
- FUNC_NAME, (unsigned long)tmp.global_id);
+ FUNC_NAME, (unsigned long)(scn->ntris + i));
log_err(scn->dev, " (%g %g %g)\n (%g %g %g)\n (%g %g %g)\n",
SPLIT3(positions[trg[i].vertice_id[0]].vec),
SPLIT3(positions[trg[i].vertice_id[1]].vec),
@@ -196,12 +225,12 @@ senc_scene_add_geometry
goto error;
}
/* Get media */
- media(i, med, ctx); /* API: media needs an unsigned */
+ if(media) media(i, med, ctx); /* API: media needs an unsigned */
FOR_EACH(j, 0, 2) {
- if(med[j] >= scn->nmeds) {
- ASSERT(med[j] <= MEDIUM_MAX__);
- scn->nmeds = med[j] + 1;
- darray_side_range_resize(&scn->media_use, scn->nmeds);
+ if(med[j] != SENC_UNDEFINED_MEDIUM && med[j] >= scn->next_medium_idx) {
+ ASSERT(med[j] < MEDIUM_MAX__);
+ scn->next_medium_idx = med[j] + 1;
+ darray_side_range_resize(&scn->media_use, scn->next_medium_idx);
}
tmp.medium[j] = (medium_id_t)med[j];
}
@@ -215,57 +244,81 @@ senc_scene_add_geometry
const medium_id_t* umed;
/* Duplicate triangle. Need to check duplicate validity */
ASSERT(trg_key_eq(&trg_key, &utrg_key));
+ if(!same) SWAP(unsigned, tmp.medium[0], tmp.medium[1]);
umed = trg[*p_trg].medium;
- if(umed[0] != (same ? med[0] : med[1])
- || umed[1] != (same ? med[1] : med[0])) {
+ if(!compatible_medium(umed[0], tmp.medium[0])
+ || !compatible_medium(umed[1], tmp.medium[1]))
+ {
/* Same triangles with different media: invalid! */
const union double3* positions
= darray_position_cdata_get(&scn->vertices);
log_err(scn->dev, "%s: triangle %lu is a duplicate"
" of triangle %lu with incoherent media.\n",
- FUNC_NAME, (unsigned long)tmp.global_id,
- (unsigned long)trg[*p_trg].global_id);
+ FUNC_NAME, (unsigned long)(scn->ntris + i), (unsigned long)*p_trg);
log_err(scn->dev,
"Triangle %lu:\n (%g %g %g)\n (%g %g %g)\n (%g %g %g)\n",
- (unsigned long)trg[*p_trg].global_id,
+ (unsigned long)*p_trg,
SPLIT3(positions[trg[*p_trg].vertice_id[0]].vec),
SPLIT3(positions[trg[*p_trg].vertice_id[1]].vec),
SPLIT3(positions[trg[*p_trg].vertice_id[2]].vec));
log_err(scn->dev, "Media: (%lu, %lu) VS (%lu, %lu)\n",
(unsigned long)umed[ureversed? 1 : 0],
(unsigned long)umed[ureversed ? 0 : 1],
- (unsigned long)med[reversed ? 1 : 0],
- (unsigned long)med[reversed ? 0 : 1]);
+ (unsigned long)tmp.medium[reversed ? 1 : 0],
+ (unsigned long)tmp.medium[reversed ? 0 : 1]);
res = RES_BAD_ARG;
goto error;
} else {
/* Legit duplicate */
- log_warn(scn->dev, "%s: triangle %lu is a duplicate of triangle %lu.\n",
- FUNC_NAME, (unsigned long)tmp.global_id,
- (unsigned long)trg[*p_trg].global_id);
- if(!same) {
- FOR_EACH(j, 0, 2) {
- tmp.medium[j] = (medium_id_t)med[1-j];
+ range_adjust_ptr = darray_triangle_in_data_get(&scn->triangles_in) + *p_trg;
+ /* Replace possible undefined media */
+ FOR_EACH(j, 0, 2) {
+ if(range_adjust_ptr->medium[j] == SENC_UNDEFINED_MEDIUM
+ && tmp.medium[j] != SENC_UNDEFINED_MEDIUM) {
+ range_adjust_ptr->medium[j] = tmp.medium[j];
+ scn->sides_with_defined_medium_count++;
}
}
+ if(merge_triangle) {
+ OK(merge_triangle((unsigned)*p_trg, i, same, ctx));
+ } else {
+ log_warn(scn->dev,
+ "%s: triangle %lu is a duplicate of triangle %lu.\n",
+ FUNC_NAME, (unsigned long)(scn->ntris + i), (unsigned long)*p_trg);
+ }
}
} else {
/* New triangle */
trg_id_t u = scn->nutris + actual_nutris;
- struct side_range* media_use;
ASSERT(u == htable_trg_size_get(&scn->unique_triangles));
OK(htable_trg_set(&scn->unique_triangles, &trg_key, &u));
OK(darray_triangle_in_push_back(&scn->triangles_in, &tmp));
+ range_adjust_ptr = darray_triangle_in_data_get(&scn->triangles_in) + u;
+ FOR_EACH(j, 0, 2) {
+ if(tmp.medium[j] != SENC_UNDEFINED_MEDIUM)
+ scn->sides_with_defined_medium_count++;
+ }
+ if(add_triangle) {
+ OK(add_triangle((unsigned)u, i, ctx));
+ }
+ ++actual_nutris;
+ }
+ if(range_adjust_ptr) {
+ ptrdiff_t u = range_adjust_ptr - trg;
+ ASSERT(u < scn->nutris + actual_nutris && u < TRG_MAX__);
FOR_EACH(j, 0, 2) {
- ASSERT(tmp.medium[j] < scn->nmeds);
+ struct side_range* media_use;
+ if(tmp.medium[j] == SENC_UNDEFINED_MEDIUM) continue;
+ ASSERT(tmp.medium[j] < scn->next_medium_idx);
media_use = darray_side_range_data_get(&scn->media_use) + tmp.medium[j];
- media_use->first = MMIN(media_use->first, TRGIDxSIDE_2_TRGSIDE(u, j));
+ media_use->first =
+ MMIN(media_use->first, TRGIDxSIDE_2_TRGSIDE((trg_id_t)u, j));
ASSERT(media_use->first < 2 * (scn->nutris + actual_nutris + 1));
- media_use->last = MMAX(media_use->last, TRGIDxSIDE_2_TRGSIDE(u, j));
+ media_use->last =
+ MMAX(media_use->last, TRGIDxSIDE_2_TRGSIDE((trg_id_t)u, j));
ASSERT(media_use->last < 2 * (scn->nutris + actual_nutris + 1));
ASSERT(media_use->first <= media_use->last);
}
- ++actual_nutris;
}
++actual_ntris;
}
@@ -288,7 +341,7 @@ error:
res_T
senc_scene_get_convention
(const struct senc_scene* scn,
- enum senc_convention* convention)
+ int* convention)
{
if(!scn || !convention) return RES_BAD_ARG;
*convention = scn->convention;
@@ -317,6 +370,57 @@ senc_scene_get_unique_triangles_count
}
res_T
+senc_scene_get_unique_sides_without_medium_count
+ (const struct senc_scene* scn,
+ unsigned* count)
+{
+ if(!scn || !count) return RES_BAD_ARG;
+ ASSERT(2 * scn->nutris >= scn->sides_with_defined_medium_count);
+ *count = 2 * scn->nutris - scn->sides_with_defined_medium_count;
+ return RES_OK;
+}
+
+res_T
+senc_scene_get_unique_triangle
+ (const struct senc_scene* scn,
+ const unsigned itri,
+ unsigned indices[3])
+{
+ const struct triangle_in* trg;
+ int i;
+ if(!scn || !indices
+ || itri >= darray_triangle_in_size_get(&scn->triangles_in))
+ return RES_BAD_ARG;
+ trg = darray_triangle_in_cdata_get(&scn->triangles_in) + itri;
+
+ FOR_EACH(i, 0, 3) {
+ ASSERT(trg->vertice_id[i] < UINT_MAX);
+ indices[i] = (unsigned)trg->vertice_id[i]; /* Back to API type */
+ }
+ return RES_OK;
+}
+
+res_T
+senc_scene_get_unique_triangle_media
+ (const struct senc_scene* scn,
+ const unsigned itri,
+ unsigned media[2])
+{
+ const struct triangle_in* trg;
+ int i;
+ if(!scn || !media
+ || itri >= darray_triangle_in_size_get(&scn->triangles_in))
+ return RES_BAD_ARG;
+ trg = darray_triangle_in_cdata_get(&scn->triangles_in) + itri;
+
+ FOR_EACH(i, 0, 2) {
+ ASSERT(trg->vertice_id[i] < UINT_MAX);
+ media[i] = (unsigned)trg->medium[i]; /* Back to API type */
+ }
+ return RES_OK;
+}
+
+res_T
senc_scene_get_vertices_count
(const struct senc_scene* scn,
unsigned* count)
@@ -337,6 +441,23 @@ senc_scene_get_unique_vertices_count
}
res_T
+senc_scene_get_unique_vertex
+ (const struct senc_scene* scn,
+ const unsigned ivert,
+ double coord[3])
+{
+
+ const union double3* v;
+ if(!scn || !coord
+ || ivert >= darray_position_size_get(&scn->vertices))
+ return RES_BAD_ARG;
+
+ v = darray_position_cdata_get(&scn->vertices) + ivert;
+ d3_set(coord, v->vec);
+ return RES_OK;
+}
+
+res_T
senc_scene_ref_get(struct senc_scene* scn)
{
if(!scn) return RES_BAD_ARG;
diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c
@@ -108,16 +108,16 @@ get_scn_position(const unsigned ivert, float pos[3], void* ctx) {
static int
self_hit_filter
-(const struct s3d_hit* hit,
- const float ray_org[3],
- const float ray_dir[3],
- void* ray_data,
- void* filter_data)
+ (const struct s3d_hit* hit,
+ const float ray_org[3],
+ const float ray_dir[3],
+ void* ray_data,
+ void* filter_data)
{
const struct darray_triangle_comp* triangles_comp = filter_data;
const component_id_t* origin_component = ray_data;
const struct triangle_comp* hit_trg_comp;
- enum side_id hit_side;
+ enum senc_side hit_side;
component_id_t hit_component;
(void)ray_org; (void)ray_dir;
@@ -125,7 +125,7 @@ self_hit_filter
ASSERT(hit->prim.prim_id < darray_triangle_comp_size_get(triangles_comp));
hit_trg_comp = darray_triangle_comp_cdata_get(triangles_comp)
+ hit->prim.prim_id;
- hit_side = (hit->normal[2] > 0) ? SIDE_FRONT : SIDE_BACK;
+ hit_side = (hit->normal[2] > 0) ? SENC_FRONT : SENC_BACK;
hit_component = hit_trg_comp->component[hit_side];
/* Not self hit or distance should be small */
@@ -148,9 +148,9 @@ extract_connex_components
{
/* This function is called from an omp parallel block and executed
* concurrently. */
- const struct senc_scene* scn;
+ struct senc_scene* scn;
struct mem_allocator* alloc;
- int64_t mm;
+ int64_t mm, undefs;
struct darray_side_id stack;
struct darray_side_id ids_of_sides_around_max_z_vertex;
const union double3* positions;
@@ -180,6 +180,19 @@ extract_connex_components
return;
}
+ /* If there are sides with undefined medium, its like another medium */
+ undefs = (scn->sides_with_defined_medium_count < 2 * scn->nutris) ? 1 : 0;
+#pragma omp single
+ {
+ if(undefs) {
+ /* Range is unknown, process each side */
+ struct side_range und;
+ und.first = 0;
+ und.last = 2 * scn->nutris - 1;
+ darray_side_range_push_back(&scn->media_use, &und);
+ }
+ } /* Implicit barrier here */
+
#ifndef NDEBUG
#pragma omp single
{
@@ -192,7 +205,8 @@ extract_connex_components
= darray_side_range_cdata_get(&scn->media_use);
FOR_EACH(mm, 0, 2) {
const side_id_t side = TRGIDxSIDE_2_TRGSIDE(t_, mm);
- const medium_id_t medium = trg_in->medium[mm];
+ medium_id_t medium = trg_in->medium[mm];
+ if(medium == SENC_UNDEFINED_MEDIUM) medium = scn->next_medium_idx;
ASSERT(media_use[medium].first <= side && side
<= media_use[medium].last);
}
@@ -202,11 +216,14 @@ extract_connex_components
/* We loop on sides to build connex components. */
#pragma omp for schedule(dynamic) nowait
- for(mm = 0; mm < (int64_t)scn->nmeds; mm++) { /* Process all media */
- const medium_id_t m = (medium_id_t)mm;
+ /* Process all media, including undef */
+ for(mm = 0; mm < undefs + (int64_t)scn->next_medium_idx; mm++) {
+ const medium_id_t m_idx = (medium_id_t)mm;
+ const medium_id_t m = (mm == scn->next_medium_idx)
+ ? SENC_UNDEFINED_MEDIUM : (medium_id_t)mm;
/* Any not-already-used side is used as a starting point */
const struct side_range* media_use =
- darray_side_range_cdata_get(&scn->media_use) + m;
+ darray_side_range_cdata_get(&scn->media_use) + m_idx;
side_id_t first_side_not_in_component = media_use->first;
double max_nz;
side_id_t max_nz_side_id = SIDE_NULL__;
@@ -240,7 +257,7 @@ extract_connex_components
#ifndef NDEBUG
{
trg_id_t tid = TRGSIDE_2_TRG(start_side_id);
- enum side_id s = TRGSIDE_2_SIDE(start_side_id);
+ enum senc_side s = TRGSIDE_2_SIDE(start_side_id);
medium_id_t side_med
= darray_triangle_in_data_get(&desc->scene->triangles_in)[tid].medium[s];
ASSERT(side_med == m);
@@ -249,15 +266,15 @@ extract_connex_components
/* Reuse array if possible, or create a new one */
if(current_media) {
- memset(current_media, 0, scn->nmeds);
+ memset(current_media, 0, 1 + scn->next_medium_idx); /* +1 for possible undef */
} else {
- current_media = MEM_CALLOC(alloc, scn->nmeds, sizeof(unsigned char));
+ current_media = MEM_CALLOC(alloc, 1 + scn->next_medium_idx, sizeof(unsigned char));
if(!current_media) {
*p_res = RES_MEM_ERR;
continue;
}
}
- current_media[m] = 1;
+ current_media[m_idx] = 1;
for(;;) { /* Process all sides of this component */
int i;
enum side_flag crt_side_flag = TRGSIDE_2_SIDEFLAG(crt_side_id);
@@ -308,7 +325,7 @@ extract_connex_components
/* Record crt_side both as component and triangle level */
if((*trg_used & crt_side_flag) == 0) {
OK2(darray_side_id_push_back(¤t_component, &crt_side_id));
- *trg_used |= (unsigned char)crt_side_flag;
+ *trg_used = *trg_used | (unsigned char)crt_side_flag;
}
/* Store neighbour's sides in a waiting stack */
@@ -318,8 +335,10 @@ extract_connex_components
enum side_flag nbour_side_id = TRGSIDE_2_SIDEFLAG(neighbour_id);
unsigned char* nbour_used = processed + nbour_trg_id;
const struct trgside* neighbour = trgsides + neighbour_id;
+ medium_id_t nbour_med_idx = (neighbour->medium == SENC_UNDEFINED_MEDIUM)
+ ? scn->next_medium_idx : neighbour->medium;
if(neighbour->medium < m
- || (*nbour_used & (unsigned char)SIDE_CANCELED_FLAG(nbour_side_id)))
+ || (*nbour_used & SIDE_CANCELED_FLAG(nbour_side_id)))
{
/* 1) Not the same medium.
* Neighbour's medium id is less than current medium: the whole
@@ -344,7 +363,7 @@ extract_connex_components
ASSERT(*used & (unsigned char)used_side_flag);
/* Set the used flag for sides in cancelled component as leading
* to further cancellations */
- *used |= (unsigned char)SIDE_CANCELED_FLAG(used_side_flag);
+ *used |= SIDE_CANCELED_FLAG(used_side_flag);
}
goto canceled;
@@ -354,7 +373,7 @@ extract_connex_components
*nbour_used |= (unsigned char)nbour_side_id;
OK2(darray_side_id_push_back(&stack, &neighbour_id));
OK2(darray_side_id_push_back(¤t_component, &neighbour_id));
- current_media[neighbour->medium] = 1;
+ current_media[nbour_med_idx] = 1;
}
sz = darray_side_id_size_get(&stack);
if(sz == 0) break; /* Empty stack => component is done! */
@@ -394,7 +413,7 @@ extract_connex_components
FOR_EACH(ii, 0, sz) {
const side_id_t s = darray_side_id_cdata_get(¤t_component)[ii];
trg_id_t tid = TRGSIDE_2_TRG(s);
- enum side_id sid = TRGSIDE_2_SIDE(s);
+ enum senc_side sid = TRGSIDE_2_SIDE(s);
component_id_t* cmp = triangles_comp[tid].component;
ASSERT(cmp[sid] == COMPONENT_NULL__);
ASSERT(trgsides[s].medium >= m);
@@ -409,7 +428,7 @@ extract_connex_components
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);
+ enum senc_side 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;
@@ -421,7 +440,7 @@ extract_connex_components
* 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); (void)s;
- if(trg_comp->component[SIDE_FRONT] == trg_comp->component[SIDE_BACK])
+ if(trg_comp->component[SENC_FRONT] == trg_comp->component[SENC_BACK])
continue;
d3_sub(edge0, vertices[trg_in->vertice_id[1]].vec,
@@ -502,7 +521,7 @@ extract_connex_components
ASSERT(desc->scene->nuverts < UINT_MAX);
OK(s3d_mesh_setup_indexed_vertices(s3d_shp,
(unsigned)desc->scene->nutris, get_scn_indices,
- (unsigned)desc->scene->nuverts, &attribs, 1, desc->scene));
+ (unsigned)desc->scene->nuverts, &attribs, 1, scn));
s3d_mesh_set_hit_filter_function(s3d_shp, self_hit_filter,
triangles_comp_array);
OK(s3d_scene_attach_shape(s3d_scn, s3d_shp));
@@ -527,8 +546,8 @@ extract_connex_components
FOR_EACH(t_, 0, scn->nutris) {
struct triangle_comp* trg_comp =
darray_triangle_comp_data_get(triangles_comp_array) + t_;
- ASSERT(trg_comp->component[SIDE_FRONT] != COMPONENT_NULL__);
- ASSERT(trg_comp->component[SIDE_BACK] != COMPONENT_NULL__);
+ ASSERT(trg_comp->component[SENC_FRONT] != COMPONENT_NULL__);
+ ASSERT(trg_comp->component[SENC_BACK] != COMPONENT_NULL__);
}
FOR_EACH(c, 0, ATOMIC_GET(component_count)) {
struct cc_descriptor** components =
@@ -617,13 +636,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 =
+ enum senc_side hit_side =
((hit.normal[2] < 0) /* Facing geometrical normal of hit */
== ((desc->scene->convention & SENC_CONVENTION_NORMAL_FRONT) != 0))
/* 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;
+ ? SENC_BACK : SENC_FRONT;
ASSERT(hit.normal[2] != 0);
ASSERT(hit_trg_id < desc->scene->nutris);
@@ -669,7 +688,7 @@ group_connex_components
enc->side_range.last = MMAX(enc->side_range.last, cc->side_range.last);
enc->side_count += cc->side_count;
tmp_res = bool_array_of_media_merge(&enc->tmp_enclosed_media, cc->media,
- desc->scene->nmeds);
+ desc->scene->next_medium_idx + 1);
if(tmp_res != RES_OK) {
*res = tmp_res;
break;
@@ -692,8 +711,8 @@ collect_and_link_neighbours
{
/* This function is called from an omp parallel block and executed
* concurrently. */
- const struct triangle_in *triangles_in;
- struct triangle_tmp *triangles_tmp;
+ const struct triangle_in* triangles_in;
+ struct triangle_tmp* triangles_tmp;
const union double3* vertices;
const int thread_count = omp_get_num_threads();
const int rank = omp_get_thread_num();
@@ -743,7 +762,7 @@ collect_and_link_neighbours
const vrtx_id_t v0 = triangles_in[t].vertice_id[ee];
const vrtx_id_t v1 = triangles_in[t].vertice_id[(ee + 1) % 3];
/* Process only "my" edges! */
- const int64_t h =
+ const int64_t h =
/* v0,v1 and v1,v0 must give the same hash!!! */
v0 + v1 + (int64_t)MMIN(v0, v1);
if(h % thread_count != rank) continue;
@@ -872,11 +891,11 @@ collect_and_link_neighbours
const trg_id_t ccw_id = ccw_neighbour->trg_id;
/* Facing sides of triangles */
const int front = ((scn->convention & SENC_CONVENTION_NORMAL_FRONT) != 0);
- const enum side_id crt_side
- = current->normal_toward_next_neighbour == front ? SIDE_FRONT : SIDE_BACK;
- const enum side_id ccw_side
+ const enum senc_side crt_side
+ = current->normal_toward_next_neighbour == front ? SENC_FRONT : SENC_BACK;
+ const enum senc_side ccw_side
= ccw_neighbour->normal_toward_next_neighbour == front ?
- SIDE_BACK : SIDE_FRONT;
+ SENC_BACK : SENC_FRONT;
/* Index of sides in trgsides */
const side_id_t crt_side_idx = TRGIDxSIDE_2_TRGSIDE(crt_id, crt_side);
const side_id_t ccw_side_idx = TRGIDxSIDE_2_TRGSIDE(ccw_id, ccw_side);
@@ -894,8 +913,7 @@ collect_and_link_neighbours
prev_id = previous->trg_id;
log_err(scn->dev,
"%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);
+ (unsigned long)crt_id, (unsigned long)prev_id);
tmp_res = RES_BAD_OP;
goto tmp_error;
}
@@ -912,8 +930,10 @@ collect_and_link_neighbours
|| 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);
- ASSERT(p_ccw_side->medium < scn->nmeds);
+ ASSERT(p_crt_side->medium == SENC_UNDEFINED_MEDIUM
+ || p_crt_side->medium < scn->next_medium_idx);
+ ASSERT(p_ccw_side->medium == SENC_UNDEFINED_MEDIUM
+ || p_ccw_side->medium < scn->next_medium_idx);
/* Detect triangles that could surround a hole:
* - single triangle on (one of) its edge
* - different media on its sides */
@@ -924,7 +944,7 @@ collect_and_link_neighbours
struct trg_edge disc;
log_warn(scn->dev,
"%s: found frontier involving triangle %lu.\n",
- FUNC_NAME, (unsigned long)triangles_in[crt_id].global_id);
+ FUNC_NAME, (unsigned long)crt_id);
disc.vrtx0 = v0;
disc.vrtx1 = v1;
darray_frontier_edge_push_back(frontiers, &disc);
@@ -992,16 +1012,16 @@ build_result
#pragma omp for
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];
+ const component_id_t cf_id = triangles_comp[t].component[SENC_FRONT];
+ const component_id_t cb_id = triangles_comp[t].component[SENC_BACK];
const struct cc_descriptor* cf = cc_descriptors[cf_id];
const struct cc_descriptor* cb = cc_descriptors[cb_id];
const enclosure_id_t ef_id = cf->enclosure_id;
const enclosure_id_t eb_id = cb->enclosure_id;
- ASSERT(triangles_enc[t].enclosure[SIDE_FRONT] == ENCLOSURE_NULL__);
- triangles_enc[t].enclosure[SIDE_FRONT] = ef_id;
- ASSERT(triangles_enc[t].enclosure[SIDE_BACK] == ENCLOSURE_NULL__);
- triangles_enc[t].enclosure[SIDE_BACK] = eb_id;
+ ASSERT(triangles_enc[t].enclosure[SENC_FRONT] == ENCLOSURE_NULL__);
+ triangles_enc[t].enclosure[SENC_FRONT] = ef_id;
+ ASSERT(triangles_enc[t].enclosure[SENC_BACK] == ENCLOSURE_NULL__);
+ triangles_enc[t].enclosure[SENC_BACK] = eb_id;
}
/* Implicit barrier here */
@@ -1032,9 +1052,9 @@ build_result
enc->header.is_infinite = (e == 0);
ASSERT(darray_uchar_size_get(&enc->tmp_enclosed_media) <= UINT_MAX);
- ASSERT(enc->header.enclosed_media_count <= scn->nmeds);
+ ASSERT(enc->header.enclosed_media_count < 1 + scn->next_medium_idx);
OK2(bool_array_of_media_to_darray_media
- (&enc->enclosed_media, &enc->tmp_enclosed_media));
+ (&enc->enclosed_media, &enc->tmp_enclosed_media, scn->next_medium_idx));
enc->header.enclosed_media_count
= (unsigned)darray_media_size_get(&enc->enclosed_media);
darray_uchar_purge(&enc->tmp_enclosed_media);
@@ -1042,8 +1062,14 @@ build_result
/* Add this enclosure in relevant by-medium lists */
FOR_EACH(m, 0, enc->header.enclosed_media_count) {
medium_id_t medium = darray_media_data_get(&enc->enclosed_media)[m];
- struct darray_enc_id* enc_ids_by_medium =
- darray_enc_ids_array_data_get(&desc->enc_ids_array_by_medium) + medium;
+ size_t m_idx = (medium == SENC_UNDEFINED_MEDIUM)
+ ? scn->next_medium_idx : medium;
+ struct darray_enc_id* enc_ids_by_medium;
+ ASSERT(medium == SENC_UNDEFINED_MEDIUM || medium < scn->next_medium_idx);
+ ASSERT(darray_enc_ids_array_size_get(&desc->enc_ids_array_by_medium)
+ == 1 + scn->next_medium_idx);
+ enc_ids_by_medium =
+ darray_enc_ids_array_data_get(&desc->enc_ids_array_by_medium) + m_idx;
#pragma omp critical
{
tmp_res = darray_enc_id_push_back(enc_ids_by_medium, &e);
@@ -1056,7 +1082,7 @@ build_result
if(*res != RES_OK) continue;
/* Build side and vertex lists. */
- OK2(darray_triangle_in_resize(&enc->sides, enc->side_count));
+ OK2(darray_sides_enc_resize(&enc->sides, enc->side_count));
/* Size is just a int */
OK2(darray_vrtx_id_reserve(&enc->vertices,
(size_t)(enc->side_count * 0.6)));
@@ -1070,11 +1096,11 @@ build_result
t++)
{
const struct triangle_in* trg_in = triangles_in + t;
- struct triangle_in* trg;
+ struct side_enc* side_enc;
unsigned vertice_id[3];
int i;
- if(triangles_enc[t].enclosure[SIDE_FRONT] != e
- && triangles_enc[t].enclosure[SIDE_BACK] != e)
+ if(triangles_enc[t].enclosure[SENC_FRONT] != e
+ && triangles_enc[t].enclosure[SENC_BACK] != e)
continue;
++enc->header.unique_triangle_count;
@@ -1094,41 +1120,33 @@ build_result
++enc->header.vertices_count;
}
}
- ASSERT(triangles_enc[t].enclosure[SIDE_FRONT] == e
- || triangles_enc[t].enclosure[SIDE_BACK] == e);
- if(triangles_enc[t].enclosure[SIDE_FRONT] == e) {
+ ASSERT(triangles_enc[t].enclosure[SENC_FRONT] == e
+ || triangles_enc[t].enclosure[SENC_BACK] == e);
+ if(triangles_enc[t].enclosure[SENC_FRONT] == e) {
/* Front side of the original triangle is member of the enclosure */
int input_normal_in = normals_front;
int revert_triangle = (input_normal_in != output_normal_in);
++enc->header.triangle_count;
- trg = darray_triangle_in_data_get(&enc->sides) + fst_idx++;
- FOR_EACH(i, 0, 2) {
- int ii = revert_triangle ? 1 - i : i;
- trg->medium[i] = trg_in->medium[ii];
- }
- trg->global_id = trg_in->global_id;
+ side_enc = darray_sides_enc_data_get(&enc->sides) + fst_idx++;
FOR_EACH(i, 0, 3) {
int ii = revert_triangle ? 2 - i : i;
- trg->vertice_id[i] = vertice_id[ii];
+ side_enc->vertice_id[i] = vertice_id[ii];
}
+ side_enc->side_id = TRGIDxSIDE_2_TRGSIDE(t, SENC_FRONT);
}
- if(triangles_enc[t].enclosure[SIDE_BACK] == e) {
+ if(triangles_enc[t].enclosure[SENC_BACK] == e) {
/* Back side of the original triangle is member of the enclosure */
int input_normal_in = normals_back;
int revert_triangle = (input_normal_in != output_normal_in);
++enc->header.triangle_count;
/* If both sides are in the enclosure, put the second side at the end */
- trg = darray_triangle_in_data_get(&enc->sides) +
- ((triangles_enc[t].enclosure[SIDE_FRONT] == e) ? --sgd_idx : fst_idx++);
- FOR_EACH(i, 0, 2) {
- int ii = revert_triangle ? 1 - i : i;
- trg->medium[i] = trg_in->medium[ii];
- }
- trg->global_id = trg_in->global_id;
+ side_enc = darray_sides_enc_data_get(&enc->sides) +
+ ((triangles_enc[t].enclosure[SENC_FRONT] == e) ? --sgd_idx : fst_idx++);
FOR_EACH(i, 0, 3) {
int ii = revert_triangle ? 2 - i : i;
- trg->vertice_id[i] = vertice_id[ii];
+ side_enc->vertice_id[i] = vertice_id[ii];
}
+ side_enc->side_id = TRGIDxSIDE_2_TRGSIDE(t, SENC_BACK);
}
if(fst_idx == sgd_idx) break;
}
@@ -1148,7 +1166,9 @@ build_result
* Exported functions
******************************************************************************/
res_T
-senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
+senc_scene_analyze
+ (struct senc_scene* scn,
+ struct senc_descriptor** out_desc)
{
struct senc_descriptor* desc = NULL;
/* By triangle tmp data */
@@ -1170,8 +1190,6 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
/* Atomic counters to share beetwen threads */
ATOMIC component_count = 0;
ATOMIC next_enclosure_id = 1;
- char dump[64];
- struct time t0, t1;
res_T res = RES_OK;
res_T res2 = RES_OK;
@@ -1185,11 +1203,6 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
if(!scn->nutris) goto exit;
-#pragma omp single nowait
- if(scn->dev->verbose) {
- time_current(&t0);
- }
-
darray_triangle_tmp_init(scn->dev->allocator, &triangles_tmp);
triangles_tmp_initialized = 1;
darray_frontier_edge_init(scn->dev->allocator, &frontiers);
@@ -1232,7 +1245,7 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
connex_components_initialized = 1;
/* Just a hint; to limit contention */
OK2(darray_ptr_component_descriptor_reserve(&connex_components,
- 2 * scn->nmeds));
+ 2 + 2 * scn->next_medium_idx));
darray_triangle_comp_init(scn->dev->allocator, &triangles_comp);
triangles_comp_initialized = 1;
OK2(darray_triangle_comp_resize(&triangles_comp, scn->nutris));
@@ -1254,15 +1267,6 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
goto error_;
}
- #pragma omp single nowait
- if(scn->dev->verbose) {
- time_sub(&t1, time_current(&t1), &t0);
- time_current(&t0);
- time_dump(&t1, TIME_MSEC | TIME_SEC | TIME_MIN, NULL, dump, sizeof(dump));
- log_info(scn->dev,
- "senc_scene_analyze: collect_and_link_neighbours step in %s\n", dump);
- }
-
/* Step 2: extract triangle connex components */
extract_connex_components(desc, trgsides, &connex_components,
&triangles_tmp, &triangles_comp, &s3d_view, &component_count, &res);
@@ -1290,15 +1294,6 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
triangles_tmp_initialized = 0;
} /* No barrier here */
- #pragma omp single nowait
- if(scn->dev->verbose) {
- time_sub(&t1, time_current(&t1), &t0);
- time_current(&t0);
- time_dump(&t1, TIME_MSEC | TIME_SEC | TIME_MIN, NULL, dump, sizeof(dump));
- log_info(scn->dev,
- "senc_scene_analyze: extract_connex_components step in %s\n", dump);
- }
-
/* Step 3: group components */
group_connex_components(desc, trgsides, &triangles_comp,
&connex_components, s3d_view, &next_enclosure_id, &res);
@@ -1322,15 +1317,6 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
s3d_view = NULL;
} /* No barrier here */
- #pragma omp single nowait
- if(scn->dev->verbose) {
- time_sub(&t1, time_current(&t1), &t0);
- time_current(&t0);
- time_dump(&t1, TIME_MSEC | TIME_SEC | TIME_MIN, NULL, dump, sizeof(dump));
- log_info(scn->dev,
- "senc_scene_analyze: group_connex_components step in %s\n", dump);
- }
-
/* Step 4: Build result */
build_result(desc, &connex_components, &triangles_comp, &frontiers, &res);
/* No barrier at the end of step 4: data used in step 4 cannot be
@@ -1363,15 +1349,6 @@ senc_scene_analyze(struct senc_scene* scn, struct senc_descriptor** out_desc)
}
} /* No barrier here */
- #pragma omp single nowait
- if(scn->dev->verbose) {
- time_sub(&t1, time_current(&t1), &t0);
- time_current(&t0);
- time_dump(&t1, TIME_MSEC | TIME_SEC | TIME_MIN, NULL, dump, sizeof(dump));
- log_info(scn->dev,
- "senc_scene_analyze: build_result step in %s\n", dump);
- }
-
error_:
;
} /* Implicit barrier here */
diff --git a/src/senc_scene_c.h b/src/senc_scene_c.h
@@ -48,25 +48,20 @@ struct triangle_in {
vrtx_id_t vertice_id[3];
/* Ids of this triangle's media */
medium_id_t medium[2];
- /* Triangle index in user world (that is regardless of deduplication). */
- unsigned global_id;
};
-#ifndef NDEBUG
static FINLINE void
triangle_in_init(struct mem_allocator* alloc, struct triangle_in* trg) {
int i;
(void)alloc;
ASSERT(trg);
FOR_EACH(i, 0, 3) trg->vertice_id[i] = VRTX_NULL__;
- FOR_EACH(i, 0, 2) trg->medium[i] = MEDIUM_NULL__;
- trg->global_id = 0;
+ FOR_EACH(i, 0, 2) trg->medium[i] = SENC_UNDEFINED_MEDIUM;
}
-#define DARRAY_FUNCTOR_INIT triangle_in_init
-#endif
#define DARRAY_NAME triangle_in
#define DARRAY_DATA struct triangle_in
+#define DARRAY_FUNCTOR_INIT triangle_in_init
#include <rsys/dynamic_array.h>
static FINLINE void
@@ -197,7 +192,7 @@ side_range_init(struct mem_allocator* alloc, struct side_range* data)
struct senc_scene {
/* Front / Back sides convention */
- enum senc_convention convention;
+ int convention;
/* Triangle information as given by user; no duplicates here */
struct darray_triangle_in triangles_in;
@@ -219,8 +214,9 @@ struct senc_scene {
unsigned ngeoms; /* Not used yet (just counted). */
trg_id_t ntris, nutris; /* Trg count, unique trg count */
vrtx_id_t nverts, nuverts; /* Vrtx count, unique vrtx count */
- medium_id_t nmeds;
+ medium_id_t next_medium_idx;
struct darray_side_range media_use;
+ side_id_t sides_with_defined_medium_count;
ref_T ref;
struct senc_device* dev;
diff --git a/src/test_senc_cube_behind_cube.c b/src/test_senc_cube_behind_cube.c
@@ -47,8 +47,8 @@ main(int argc, char** argv)
ctx.back_media = medium1;
/* First cube */
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
/* +Z from the first cube,
* big enough to prevent rays from the first cube to miss this one */
@@ -56,8 +56,8 @@ main(int argc, char** argv)
ctx.scale = 5;
/* Second cube */
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
@@ -85,8 +85,8 @@ main(int argc, char** argv)
ctx.back_media = medium0;
/* Third cube */
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
if(desc) CHK(senc_descriptor_ref_put(desc) == RES_OK);
desc = NULL;
diff --git a/src/test_senc_cube_in_cube.c b/src/test_senc_cube_in_cube.c
@@ -49,8 +49,8 @@ main(int argc, char** argv)
ctx.back_media = medium1;
/* First cube */
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
d3(ctx.offset, -1, -1, -1);
ctx.scale = 3;
@@ -59,8 +59,8 @@ main(int argc, char** argv)
ctx.reverse_vrtx = 1;
/* Second cube */
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
@@ -91,8 +91,8 @@ main(int argc, char** argv)
ctx.back_media = medium0;
/* Third cube */
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
if(desc) CHK(senc_descriptor_ref_put(desc) == RES_OK);
desc = NULL;
diff --git a/src/test_senc_cube_on_cube.c b/src/test_senc_cube_on_cube.c
@@ -74,7 +74,7 @@ main(int argc, char** argv)
/* Add cube #1 */
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
- NULL, nvertices, get_position, &ctx) == RES_OK);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
d3(ctx.offset, 1, 1, 1);
ctx.scale = 1;
@@ -86,7 +86,7 @@ main(int argc, char** argv)
/* Add cube #2 (has a duplicate face with cube #1) */
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
- NULL, nvertices, get_position, &ctx) == RES_OK);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
ctx.positions = box_vertices; /* Can use distorded cube for cube #3 */
d3(ctx.offset, 0, 0, 0);
@@ -100,7 +100,7 @@ main(int argc, char** argv)
/* Add cube #3 */
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
- NULL, nvertices, get_position, &ctx) == RES_OK);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
diff --git a/src/test_senc_descriptor.c b/src/test_senc_descriptor.c
@@ -52,8 +52,8 @@ main(int argc, char** argv)
ctx.front_media = medium0;
ctx.back_media = medium1;
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
@@ -164,22 +164,11 @@ 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;
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
- NULL, nvertices, get_position, &ctx) == RES_OK);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
CHK(senc_descriptor_get_global_vertices_count(desc, &count) == RES_OK);
@@ -195,8 +184,8 @@ main(int argc, char** argv)
desc = NULL;
ctx.front_media = medium1;
ctx.back_media = medium0;
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_BAD_ARG);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_BAD_ARG);
CHK(senc_scene_ref_put(scn) == RES_OK);
if(desc) CHK(senc_descriptor_ref_put(desc) == RES_OK);
@@ -209,7 +198,7 @@ main(int argc, char** argv)
== RES_OK);
CHK(senc_scene_add_geometry(scn, ntriangles - 1, get_indices, get_media,
- NULL, nvertices, get_position, &ctx) == RES_OK);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
diff --git a/src/test_senc_enclosure.c b/src/test_senc_enclosure.c
@@ -22,7 +22,7 @@
#include <star/s3d.h>
static void
-test(enum senc_convention convention)
+test(const int convention)
{
struct mem_allocator allocator;
struct senc_descriptor* desc = NULL;
@@ -36,13 +36,15 @@ test(enum senc_convention convention)
struct s3d_shape* s3d_shp = NULL;
struct s3d_vertex_data s3d_attribs;
unsigned indices[2][3];
- unsigned medium, media[2];
+ unsigned medium;
unsigned gid;
+ enum senc_side side;
double vrtx[3];
struct context ctx;
unsigned i, n, t, ecount;
- enum senc_convention conv;
- int is_front, is_in;
+ int conv;
+ const int conv_front = (convention & SENC_CONVENTION_NORMAL_FRONT) != 0;
+ const int conv_in = (convention & SENC_CONVENTION_NORMAL_INSIDE) != 0;
CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK);
CHK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)
@@ -52,8 +54,6 @@ test(enum senc_convention convention)
CHK(senc_scene_get_convention(scn, &conv) == RES_OK);
CHK(conv == convention);
- is_front = (conv & SENC_CONVENTION_NORMAL_FRONT) != 0;
- is_in = (conv & SENC_CONVENTION_NORMAL_INSIDE) != 0;
s3d_attribs.type = S3D_FLOAT3;
s3d_attribs.usage = S3D_POSITION;
@@ -76,7 +76,7 @@ test(enum senc_convention convention)
ctx.back_media = medium1;
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
- NULL, nvertices, get_position, &ctx) == RES_OK);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
@@ -112,32 +112,38 @@ test(enum senc_convention convention)
CHK(senc_enclosure_get_vertex(NULL, nvertices, NULL) == RES_BAD_ARG);
CHK(senc_enclosure_get_vertex(enclosure, 0, vrtx) == RES_OK);
- CHK(senc_enclosure_get_triangle_media(NULL, 0, media) == RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_media(enclosure, ntriangles, media)
+ CHK(senc_enclosure_get_triangle_global_id(NULL, 0, &gid, NULL)
== RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_media(enclosure, 0, NULL) == RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_media(NULL, ntriangles, media)
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, ntriangles, &gid, NULL)
== RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_media(NULL, 0, NULL) == RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_media(enclosure, ntriangles, NULL)
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, 0, NULL, NULL)
== RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_media(NULL, ntriangles, NULL)
+ CHK(senc_enclosure_get_triangle_global_id(NULL, ntriangles, &gid, NULL)
== RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_media(enclosure, 0, media) == RES_OK);
-
- CHK(senc_enclosure_get_triangle_global_id(NULL, 0, &gid) == RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_global_id(enclosure, ntriangles, &gid)
+ CHK(senc_enclosure_get_triangle_global_id(NULL, 0, NULL, NULL)
+ == RES_BAD_ARG);
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, ntriangles, NULL, NULL)
+ == RES_BAD_ARG);
+ CHK(senc_enclosure_get_triangle_global_id(NULL, ntriangles, NULL, NULL)
+ == RES_BAD_ARG);
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, 0, &gid, NULL)
+ == RES_BAD_ARG);
+ CHK(senc_enclosure_get_triangle_global_id(NULL, 0, &gid, &side)
== RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_global_id(enclosure, 0, NULL)
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, ntriangles, &gid, &side)
== RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_global_id(NULL, ntriangles, &gid)
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, 0, NULL, &side)
== RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_global_id(NULL, 0, NULL) == RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_global_id(enclosure, ntriangles, NULL)
+ CHK(senc_enclosure_get_triangle_global_id(NULL, ntriangles, &gid, &side)
== RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_global_id(NULL, ntriangles, NULL)
+ CHK(senc_enclosure_get_triangle_global_id(NULL, 0, NULL, &side)
== RES_BAD_ARG);
- CHK(senc_enclosure_get_triangle_global_id(enclosure, 0, &gid) == RES_OK);
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, ntriangles, NULL, &side)
+ == RES_BAD_ARG);
+ CHK(senc_enclosure_get_triangle_global_id(NULL, ntriangles, NULL, &side)
+ == RES_BAD_ARG);
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, 0, &gid, &side)
+ == RES_OK);
CHK(senc_enclosure_get_medium(NULL, 0, &medium) == RES_BAD_ARG);
CHK(senc_enclosure_get_medium(enclosure, 2, &medium) == RES_BAD_ARG);
@@ -164,15 +170,16 @@ test(enum senc_convention convention)
/* Geometrical normals point outside the cube in input triangles:
* if convention is front, front medium (0) is outside,
* that is medium 0's enclosure is infinite */
- CHK(is_front == ((medium == 0) == header.is_infinite));
+ CHK(conv_front == ((medium == 0) == header.is_infinite));
CHK(header.triangle_count == ntriangles);
CHK(header.unique_triangle_count == ntriangles);
CHK(header.vertices_count == nvertices);
CHK(header.is_infinite == (i == 0));
FOR_EACH(t, 0, header.triangle_count) {
- CHK(senc_enclosure_get_triangle_global_id(enclosure, t, &gid) == RES_OK);
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, t, &gid, &side) == RES_OK);
CHK(gid == t);
+ CHK(side == (medium == 0) ? SENC_FRONT : SENC_BACK);
}
CHK(senc_enclosure_ref_put(enclosure) == RES_OK);
@@ -192,9 +199,9 @@ test(enum senc_convention convention)
* of input triangles for enclosure 0 iff convention is inside.
* The opposite holds for enclosure 1. */
cmp_trg(n, enclosures[0], box_indices + 3 * n, box_vertices, &same, &reversed);
- CHK((same && !reversed) == is_in);
+ CHK((same && !reversed) == conv_in);
cmp_trg(n, enclosures[1], box_indices + 3 * n, box_vertices, &same, &reversed);
- CHK(same && reversed == is_in);
+ CHK(same && reversed == conv_in);
}
FOR_EACH(i, 0, 2)
CHK(senc_enclosure_ref_put(enclosures[i]) == RES_OK);
@@ -205,8 +212,7 @@ test(enum senc_convention convention)
/* Same 3D cube, but with a hole (incomplete).
* 1 single enclosure including both sides of triangles */
- CHK(senc_scene_create(dev,
- SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_INSIDE, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, convention, &scn) == RES_OK);
ctx.positions = box_vertices;
ctx.indices = box_indices;
@@ -216,7 +222,7 @@ test(enum senc_convention convention)
ctx.back_media = medium1;
CHK(senc_scene_add_geometry(scn, ntriangles - 1, get_indices, get_media,
- NULL, nvertices, get_position, &ctx) == RES_OK);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
@@ -239,11 +245,12 @@ test(enum senc_convention convention)
CHK(header.vertices_count == nvertices);
CHK(header.is_infinite == 1);
- FOR_EACH(t, 0, header.unique_triangle_count) {
+ FOR_EACH(t, 0, header.triangle_count) {
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, t, &gid, &side) == RES_OK);
/* The first unique_triangle_count triangles of an enclosure
* are unique triangles */
- CHK(senc_enclosure_get_triangle_global_id(enclosure, t, &gid) == RES_OK);
- CHK(gid == t);
+ if (t < header.unique_triangle_count) CHK(gid == t);
+ CHK(side == (t < header.unique_triangle_count) ? SENC_FRONT : SENC_BACK);
}
FOR_EACH(n, 0, header.unique_triangle_count) {
diff --git a/src/test_senc_inconsistant_cube.c b/src/test_senc_inconsistant_cube.c
@@ -49,7 +49,7 @@ static const unsigned
inconsistant_medium_back[12] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
static void
-test(enum senc_convention convention)
+test(const int convention)
{
struct mem_allocator allocator;
struct senc_descriptor* desc = NULL;
@@ -57,7 +57,7 @@ test(enum senc_convention convention)
struct senc_scene* scn = NULL;
struct senc_enclosure* enclosure;
struct senc_enclosure_header header;
- enum senc_convention conv;
+ int conv;
int conv_front, conv_in;
struct context ctx;
unsigned i, e, ecount;
@@ -83,7 +83,7 @@ test(enum senc_convention convention)
ctx.back_media = inconsistant_medium_back;
CHK(senc_scene_add_geometry(scn, inconsistant_box_ntriangles, get_indices,
- get_media, NULL, nvertices, get_position, &ctx) == RES_OK);
+ get_media, nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
@@ -98,8 +98,8 @@ test(enum senc_convention convention)
FOR_EACH(e, 0, ecount) {
unsigned medium, expected_external_medium, expected_medium;
char name[128];
- int front_inside;
- int expected_side;
+ enum senc_side side, expected_side;
+ unsigned gid;
CHK(senc_descriptor_get_enclosure(desc, e, &enclosure) == RES_OK);
CHK(senc_enclosure_get_header(enclosure, &header) == RES_OK);
CHK(header.enclosed_media_count == 1);
@@ -110,9 +110,6 @@ test(enum senc_convention convention)
expected_medium = (header.is_infinite ?
expected_external_medium : !expected_external_medium);
CHK(medium == expected_medium);
- /* Common media, for non input triangles */
- front_inside = (conv_front == conv_in);
- expected_side = front_inside ? 0 : 1;
sprintf(name, "test_inconsistant_cube_%s_%s_%u.obj",
conv_front ? "front" : "back", conv_in ? "in" : "out", e);
@@ -120,16 +117,17 @@ test(enum senc_convention convention)
FOR_EACH(i, 0, header.triangle_count) {
int same, reversed, fst_reversed;
- unsigned med[2];
- fst_reversed = (e == 0) == conv_in;
- CHK(senc_enclosure_get_triangle_media(enclosure, i, med) == RES_OK);
- CHK(med[expected_side] == medium);
+ fst_reversed = ((e == 0) == conv_in);
+ expected_side = (inconsistant_medium_front[i] == expected_medium)
+ ? SENC_FRONT : SENC_BACK;
cmp_trg(i, enclosure,
inconsistant_box_indices + (3 * i), box_vertices,
&same, &reversed);
/* Should be made of the same triangles */
CHK(same);
CHK(i ? reversed != fst_reversed : reversed == fst_reversed);
+ CHK(senc_enclosure_get_triangle_global_id(enclosure, i, &gid, &side) == RES_OK);
+ CHK(side == expected_side);
}
SENC(enclosure_ref_put(enclosure));
}
diff --git a/src/test_senc_many_enclosures.c b/src/test_senc_many_enclosures.c
@@ -106,6 +106,8 @@ main(int argc, char** argv)
ASSERT(ctx.data.nvertices < UINT_MAX);
cyl_trg_count = (unsigned)ctx.data.nprimitives;
cyl_vrtx_count = (unsigned)ctx.data.nvertices;
+ CHK(senc_scene_reserve(scn, NB_CYL * cyl_vrtx_count, NB_CYL * cyl_trg_count, 0)
+ == RES_OK);
FOR_EACH(i, 0, NB_CYL_1) {
double center_x = 2 * (1 + NB_CYL_1) * (i - NB_CYL_1 / 2);
FOR_EACH(j, 0, NB_CYL_1) {
@@ -121,7 +123,7 @@ main(int argc, char** argv)
misalignment *= -1;
d3(ctx.ctx.offset, center_x + misalignment, center_y + misalignment, 0);
CHK(senc_scene_add_geometry(scn, cyl_trg_count, get_s3dut_indices,
- get_s3dut_media, NULL, cyl_vrtx_count, get_s3dut_position, &ctx)
+ get_s3dut_media, cyl_vrtx_count, get_s3dut_position, NULL, NULL, &ctx)
== RES_OK);
}
}
diff --git a/src/test_senc_many_triangles.c b/src/test_senc_many_triangles.c
@@ -104,11 +104,13 @@ main(int argc, char** argv)
ASSERT(ctx.data.nvertices < UINT_MAX);
cyl_trg_count = (unsigned)ctx.data.nprimitives;
cyl_vrtx_count = (unsigned)ctx.data.nvertices;
+ CHK(senc_scene_reserve(scn, NB_CYL * cyl_vrtx_count, NB_CYL * cyl_trg_count, 0)
+ == RES_OK);
FOR_EACH(i, 0, NB_CYL) {
m1 = i;
d3(ctx.ctx.offset, 0, 0, i * 10);
CHK(senc_scene_add_geometry(scn, cyl_trg_count, get_s3dut_indices,
- get_s3dut_media, NULL, cyl_vrtx_count, get_s3dut_position, &ctx)
+ get_s3dut_media, cyl_vrtx_count, get_s3dut_position, NULL, NULL, &ctx)
== RES_OK);
}
S3DUT(mesh_ref_put(cyl));
diff --git a/src/test_senc_sample_enclosure.c b/src/test_senc_sample_enclosure.c
@@ -72,7 +72,7 @@ main(int argc, char** argv)
ctx.back_media = medium0;
CHK(senc_scene_add_geometry(scn, ntriangles - 1, get_indices,
- get_media, NULL, nvertices, get_position, &ctx) == RES_OK);
+ get_media, nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
diff --git a/src/test_senc_scene.c b/src/test_senc_scene.c
@@ -29,9 +29,10 @@ main(int argc, char** argv)
struct senc_enclosure* enc = NULL;
struct senc_enclosure_header header;
struct context ctx;
- unsigned medfront[2], medback[2];
+ unsigned medfront[2], medback[2], ind[3];
+ double vrtx[3];
unsigned count, i, maxm;
- enum senc_convention convention;
+ int convention;
(void)argc, (void)argv;
CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK);
@@ -51,6 +52,9 @@ main(int argc, char** argv)
CHK(senc_scene_create(dev,
SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, &scn) == RES_OK);
+ CHK(senc_scene_reserve(NULL, 0, 0, 0) == RES_BAD_ARG);
+ CHK(senc_scene_reserve(scn, 0, 0, 0) == RES_OK);
+
CHK(senc_scene_get_convention(NULL, &convention) == RES_BAD_ARG);
CHK(senc_scene_get_convention(scn, NULL) == RES_BAD_ARG);
CHK(senc_scene_get_convention(NULL, NULL) == RES_BAD_ARG);
@@ -81,6 +85,16 @@ main(int argc, char** argv)
CHK(senc_scene_get_unique_vertices_count(scn, &count) == RES_OK);
CHK(count == 0);
+ CHK(senc_scene_get_unique_sides_without_medium_count(NULL, &count)
+ == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_sides_without_medium_count(scn, NULL)
+ == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_sides_without_medium_count(NULL, NULL)
+ == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_sides_without_medium_count(scn, &count)
+ == RES_OK);
+ CHK(count == 0);
+
/* A 3D cube.
* With this geometry front is inside with NORMAL_BACK convention,
* outside with NORMAL_FRONT convention */
@@ -92,22 +106,19 @@ main(int argc, char** argv)
d3(ctx.offset, 0, 0, 0);
ctx.front_media = medium0;
ctx.back_media = medium1;
- ctx.global_ids = gid_face;
CHK(senc_scene_add_geometry(NULL, ntriangles, get_indices, get_media,
- get_global_id, nvertices, get_position, &ctx) == RES_BAD_ARG);
- CHK(senc_scene_add_geometry(scn, 0, get_indices, get_media, get_global_id,
- nvertices, get_position, &ctx) == RES_BAD_ARG);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_BAD_ARG);
+ CHK(senc_scene_add_geometry(scn, 0, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_BAD_ARG);
CHK(senc_scene_add_geometry(scn, ntriangles, NULL, get_media,
- get_global_id, nvertices, get_position, &ctx) == RES_BAD_ARG);
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, NULL,
- get_global_id, nvertices, get_position, &ctx) == RES_BAD_ARG);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_BAD_ARG);
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
- get_global_id, 0, get_position, &ctx) == RES_BAD_ARG);
+ 0, get_position, NULL, NULL, &ctx) == RES_BAD_ARG);
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
- get_global_id, nvertices, NULL, &ctx) == RES_BAD_ARG);
+ nvertices, NULL, NULL, NULL, &ctx) == RES_BAD_ARG);
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
- get_global_id, nvertices, get_position, &ctx) == RES_OK);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_get_triangles_count(scn, &count) == RES_OK);
CHK(count == ntriangles);
@@ -118,6 +129,33 @@ main(int argc, char** argv)
CHK(senc_scene_get_unique_vertices_count(scn, &count) == RES_OK);
CHK(count == nvertices);
+ CHK(senc_scene_get_unique_triangle(NULL, 0, ind) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle(scn, UINT_MAX, ind) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle(scn, 0, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle(NULL, UINT_MAX, ind) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle(NULL, 0, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle(scn, UINT_MAX, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle(NULL, UINT_MAX, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle(scn, 0, ind) == RES_OK);
+
+ CHK(senc_scene_get_unique_triangle_media(NULL, 0, ind) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle_media(scn, UINT_MAX, ind) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle_media(scn, 0, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle_media(NULL, UINT_MAX, ind) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle_media(NULL, 0, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle_media(scn, UINT_MAX, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle_media(NULL, UINT_MAX, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_triangle_media(scn, 0, ind) == RES_OK);
+
+ CHK(senc_scene_get_unique_vertex(NULL, 0, vrtx) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_vertex(scn, UINT_MAX, vrtx) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_vertex(scn, 0, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_vertex(NULL, UINT_MAX, vrtx) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_vertex(NULL, 0, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_vertex(scn, UINT_MAX, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_vertex(NULL, UINT_MAX, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_get_unique_vertex(scn, 0, vrtx) == RES_OK);
+
CHK(senc_scene_analyze(NULL, NULL) == RES_BAD_ARG);
CHK(senc_scene_analyze(scn, NULL) == RES_BAD_ARG);
CHK(senc_scene_analyze(NULL, &desc) == RES_BAD_ARG);
@@ -136,7 +174,7 @@ main(int argc, char** argv)
CHK(senc_scene_get_convention(scn, &convention) == RES_OK);
CHK(convention == (SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_INSIDE));
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
- get_global_id, nvertices, get_position, &ctx) == RES_OK);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
/* Check that medium 0 is inside */
CHK(senc_descriptor_get_enclosure_by_medium(desc, 0, 0, &enc) == RES_OK);
@@ -144,21 +182,14 @@ main(int argc, char** argv)
CHK(!header.is_infinite);
CHK(senc_enclosure_ref_put(enc) == RES_OK);
- FOR_EACH(i, 0, ntriangles) {
- unsigned gid;
- CHK(senc_descriptor_get_global_triangle_global_id(desc, i, &gid) == RES_OK);
- /* gid has been set to gid_face. */
- CHK(gid == gid_face[i]);
- }
CHK(senc_descriptor_get_global_triangle_media(desc, 0, medback) == RES_OK);
-
ctx.front_media = medium1_3;
CHK(senc_scene_ref_put(scn) == RES_OK);
CHK(senc_descriptor_ref_put(desc) == RES_OK);
CHK(senc_scene_create(dev,
SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, &scn) == RES_OK);
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
- get_global_id, nvertices, get_position, &ctx) == RES_OK);
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
/* Medium mismatch between neighbour segments, but OK */
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
@@ -179,8 +210,8 @@ main(int argc, char** argv)
CHK(senc_descriptor_ref_put(desc) == RES_OK);
CHK(senc_scene_create(dev,
SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, &scn) == RES_OK);
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_analyze(scn, &desc) == RES_OK);
/* Check that medium 0 is outside */
CHK(senc_descriptor_get_enclosure_by_medium(desc, 0, 0, &enc) == RES_OK);
@@ -188,46 +219,40 @@ main(int argc, char** argv)
CHK(header.is_infinite);
CHK(senc_enclosure_ref_put(enc) == RES_OK);
- FOR_EACH(i, 0, ntriangles) {
- unsigned gid;
- CHK(senc_descriptor_get_global_triangle_global_id(desc, i, &gid) == RES_OK);
- /* Default gid: triangle rank. */
- CHK(gid == i);
- }
CHK(senc_descriptor_get_global_triangle_media(desc, 0, medfront) == RES_OK);
FOR_EACH(i, 0, 2) CHK(medback[i] == medfront[i]);
/* Invalid vertex ID */
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices - 1, get_position, &ctx) == RES_BAD_ARG);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices - 1, get_position, NULL, NULL, &ctx) == RES_BAD_ARG);
/* Incoherent medium on a duplicate triangle */
ctx.back_media = medium1_3;
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_BAD_ARG);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_BAD_ARG);
/* 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);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
/* Coherent medium on duplicate triangle */
ctx.back_media = medium1;
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
/* Coherent medium on duplicate triangle V2 */
ctx.reverse_med = 1;
ctx.front_media = medium1;
ctx.back_media = medium0;
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
/* Coherent medium on duplicate triangle V3 */
ctx.reverse_med = 0;
ctx.reverse_vrtx = 1;
- CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
- nvertices, get_position, &ctx) == RES_OK);
+ CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx) == RES_OK);
CHK(senc_scene_ref_put(scn) == RES_OK);
CHK(senc_device_ref_put(dev) == RES_OK);
diff --git a/src/test_senc_undefined_medium.c b/src/test_senc_undefined_medium.c
@@ -0,0 +1,277 @@
+/* Copyright (C) |Meso|Star> 2016-2018 (contact@meso-star.com)
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "senc.h"
+#include "senc_s3d_wrapper.h"
+#include "test_senc_utils.h"
+
+#include <rsys/double3.h>
+
+static void
+test(const int convention)
+{
+ struct mem_allocator allocator;
+ struct senc_descriptor* desc = NULL;
+ struct senc_device* dev = NULL;
+ struct senc_scene* scn = NULL;
+ struct senc_enclosure* enclosure;
+ struct senc_enclosure_header header;
+ unsigned medium, expected_external_medium, expected_internal_medium;
+ unsigned gid;
+ enum senc_side side;
+ struct context ctx;
+ unsigned i, t, ecount, vcount, tcount, scount;
+ unsigned media[12];
+ unsigned rev_box_indices[sizeof(box_indices) / sizeof(*box_indices)];
+ const int conv_front = (convention & SENC_CONVENTION_NORMAL_FRONT) != 0;
+
+ /* Create a box with reversed triangles */
+ FOR_EACH(i, 0, sizeof(rev_box_indices) / sizeof(*rev_box_indices)) {
+ switch (i % 3) {
+ case 0: rev_box_indices[i] = box_indices[i]; break;
+ case 1: rev_box_indices[i] = box_indices[i + 1]; break;
+ case 2: rev_box_indices[i] = box_indices[i - 1]; break;
+ }
+ }
+ OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator));
+ OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev));
+
+ OK(senc_scene_create(dev, convention, &scn));
+
+ /* A 3D cube.
+ * 2 enclosures (inside, outside) sharing the same triangles,
+ * but opposite sides */
+ ctx.positions = box_vertices;
+ ctx.indices = box_indices;
+ ctx.scale = 1;
+ ctx.reverse_vrtx = 0;
+ ctx.reverse_med = 0;
+ d3(ctx.offset, 0, 0, 0);
+ ctx.front_media = media;
+ ctx.back_media = medium1;
+
+ /* Can add the same triangles again defined/undefined media in any order */
+
+ /* Add geometry with no media information on both sides */
+ for (i = 0; i < sizeof(media) / sizeof(*media); i++)
+ media[i] = SENC_UNDEFINED_MEDIUM;
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, NULL,
+ nvertices, get_position, NULL, NULL, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == 2 * ntriangles);
+
+ /* Add geometry with no media information on the front sides */
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == ntriangles);
+
+ /* Analyze with undefined media on the front sides */
+ OK(senc_scene_analyze(scn, &desc));
+ OK(senc_descriptor_get_enclosure_count(desc, &ecount));
+ CHK(ecount == 2);
+
+ FOR_EACH(i, 0, ecount) {
+ struct senc_enclosure* ee;
+ struct senc_enclosure_header hh;
+ unsigned cc;
+ OK(senc_descriptor_get_enclosure(desc, i, &enclosure));
+ OK(senc_enclosure_get_header(enclosure, &header));
+
+ CHK(header.enclosure_id == i);
+ CHK(header.enclosed_media_count == 1);
+
+ OK(senc_enclosure_get_medium(enclosure, 0, &medium));
+ /* Geometrical normals point outside the cube in input triangles:
+ * if convention is front, front medium (undef) is outside,
+ * that is medium 0's enclosure is infinite */
+ expected_external_medium = conv_front ? SENC_UNDEFINED_MEDIUM : 1;
+ expected_internal_medium = conv_front ? 1 :SENC_UNDEFINED_MEDIUM;
+
+ CHK(medium == (header.is_infinite
+ ? expected_external_medium : expected_internal_medium));
+ CHK(header.triangle_count == ntriangles);
+ CHK(header.unique_triangle_count == ntriangles);
+ CHK(header.vertices_count == nvertices);
+ CHK(header.is_infinite == (i == 0));
+
+ OK(senc_descriptor_get_enclosure_count_by_medium(desc, medium, &cc));
+ CHK(cc == 1);
+ OK(senc_descriptor_get_enclosure_by_medium(desc, medium, 0, &ee));
+ OK(senc_enclosure_get_header(ee, &hh));
+ CHK(header.enclosure_id == hh.enclosure_id);
+ OK(senc_enclosure_ref_put(ee));
+
+ FOR_EACH(t, 0, header.triangle_count) {
+ unsigned ind[3];
+ OK(senc_enclosure_get_triangle_global_id(enclosure, t, &gid, &side));
+ CHK(gid == t);
+ CHK(side == (medium == 1) ? SENC_BACK :SENC_FRONT);
+ OK(senc_enclosure_get_triangle(enclosure, t, ind));
+ }
+ OK(senc_enclosure_ref_put(enclosure));
+ }
+ OK(senc_descriptor_ref_put(desc));
+
+ /* Same geometry, front media are defined for odd triangles */
+ for (i = 0; i < sizeof(media) / sizeof(*media); i++)
+ media[i] = (i % 2) ? 0 : SENC_UNDEFINED_MEDIUM;
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == ntriangles / 2);
+
+ /* Analyze with undefined media */
+ OK(senc_scene_analyze(scn, &desc));
+ OK(senc_descriptor_ref_put(desc));
+
+ /* Get the deduplicated geometry without (successful) analyze */
+ OK(senc_scene_get_unique_vertices_count(scn, &vcount));
+ CHK(vcount == nvertices);
+ OK(senc_scene_get_unique_triangles_count(scn, &tcount));
+ CHK(tcount == ntriangles);
+ FOR_EACH(i, 0, tcount) {
+ int j;
+ unsigned med[2], ids[3];
+ OK(senc_scene_get_unique_triangle(scn, i, ids));
+ OK(senc_scene_get_unique_triangle_media(scn, i, med));
+ CHK(med[0] == ((i % 2) ? 0 : SENC_UNDEFINED_MEDIUM) && med[1] == 1);
+ FOR_EACH(j, 0, 3) {
+ double pos[3];
+ CHK(ids[j] < vcount);
+ OK(senc_scene_get_unique_vertex(scn, ids[j], pos));
+ }
+ }
+
+ /* Same information again, using a reversed box */
+ ctx.indices = rev_box_indices;
+ SWAP(const unsigned*, ctx.front_media, ctx.back_media);
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == ntriangles / 2);
+
+ /* Analyze with undefined media */
+ OK(senc_scene_analyze(scn, &desc));
+ OK(senc_descriptor_ref_put(desc));
+
+ /* Define media for remaining triangles, using reversed box */
+ for (i = 0; i < sizeof(media) / sizeof(*media); i++)
+ media[i] = (i % 2) ? SENC_UNDEFINED_MEDIUM : 0;
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == 0);
+
+ /* Get the deduplicated geometry without (successful) analyze */
+ OK(senc_scene_get_unique_vertices_count(scn, &vcount));
+ CHK(vcount == nvertices);
+ OK(senc_scene_get_unique_triangles_count(scn, &tcount));
+ CHK(tcount == ntriangles);
+ FOR_EACH(i, 0, tcount) {
+ int j;
+ unsigned med[2], ids[3];
+ OK(senc_scene_get_unique_triangle(scn, i, ids));
+ OK(senc_scene_get_unique_triangle_media(scn, i, med));
+ CHK(med[0] == 0 && med[1] == 1);
+ FOR_EACH(j, 0, 3) {
+ double pos[3];
+ CHK(ids[j] < vcount);
+ OK(senc_scene_get_unique_vertex(scn, ids[j], pos));
+ }
+ }
+
+ /* Analyze with all media defined */
+ OK(senc_scene_analyze(scn, &desc));
+ OK(senc_descriptor_ref_put(desc));
+
+ /* Define media for all triangles, nothing new here */
+ for (i = 0; i < sizeof(media) / sizeof(*media); i++)
+ media[i] = 0;
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == 0);
+
+ /* Define incoherent media for some triangles */
+ for (i = 0; i < sizeof(media) / sizeof(*media); i++)
+ media[i] = (i % 2);
+ BA(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, NULL, NULL, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == 0);
+
+ /* Scene is still OK and can be analyzed */
+ OK(senc_scene_analyze(scn, &desc));
+
+ OK(senc_descriptor_get_global_triangles_count(desc, &tcount));
+ CHK(tcount == sizeof(media) / sizeof(*media));
+
+ OK(senc_descriptor_get_enclosure_count(desc, &ecount));
+ CHK(ecount == 2);
+
+ FOR_EACH(i, 0, ecount) {
+ struct senc_enclosure* ee;
+ struct senc_enclosure_header hh;
+ unsigned cc;
+ OK(senc_descriptor_get_enclosure(desc, i, &enclosure));
+ OK(senc_enclosure_get_header(enclosure, &header));
+
+ CHK(header.enclosure_id == i);
+ CHK(header.enclosed_media_count == 1);
+ OK(senc_enclosure_get_medium(enclosure, 0, &medium));
+ /* Geometrical normals point outside the cube in input triangles:
+ * if convention is front, front medium (0) is outside,
+ * that is medium 0's enclosure is infinite */
+ CHK(conv_front == ((medium == 0) == header.is_infinite));
+ CHK(header.triangle_count == ntriangles);
+ CHK(header.unique_triangle_count == ntriangles);
+ CHK(header.vertices_count == nvertices);
+ CHK(header.is_infinite == (i == 0));
+
+ OK(senc_descriptor_get_enclosure_count_by_medium(desc, medium, &cc));
+ CHK(cc == 1);
+ OK(senc_descriptor_get_enclosure_by_medium(desc, medium, 0, &ee));
+ OK(senc_enclosure_get_header(ee, &hh));
+ CHK(header.enclosure_id == hh.enclosure_id);
+ OK(senc_enclosure_ref_put(ee));
+
+ FOR_EACH(t, 0, header.triangle_count) {
+ OK(senc_enclosure_get_triangle_global_id(enclosure, t, &gid, &side));
+ CHK(gid == t);
+ CHK(side == (medium == 1) ? SENC_BACK : SENC_FRONT);
+ }
+ OK(senc_enclosure_ref_put(enclosure));
+ }
+
+ SENC(scene_ref_put(scn));
+ SENC(device_ref_put(dev));
+ SENC(descriptor_ref_put(desc));
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHK(mem_allocated_size() == 0);
+}
+
+int
+main(int argc, char** argv)
+{
+ (void) argc, (void) argv;
+ test(SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE);
+ test(SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_INSIDE);
+ test(SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_OUTSIDE);
+ test(SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_OUTSIDE);
+ return 0;
+}
diff --git a/src/test_senc_undefined_medium_attr.c b/src/test_senc_undefined_medium_attr.c
@@ -0,0 +1,366 @@
+/* Copyright (C) |Meso|Star> 2016-2018 (contact@meso-star.com)
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "senc.h"
+#include "senc_s3d_wrapper.h"
+#include "test_senc_utils.h"
+
+#include <rsys/double3.h>
+#include <limits.h>
+
+#define INVALID_INTFACE_ID UINT_MAX
+
+static FINLINE void
+set_null_id(struct mem_allocator* alloc, unsigned* data)
+{
+ ASSERT(data); (void)alloc;
+ *data = INVALID_INTFACE_ID;
+}
+
+#include <rsys/dynamic_array.h>
+#define DARRAY_NAME intface_id
+#define DARRAY_FUNCTOR_INIT set_null_id
+#define DARRAY_DATA unsigned
+#include <rsys/dynamic_array.h>
+
+/* Manage interface properties */
+struct merge_ctx {
+ struct darray_intface_id global_interf_data;
+ const unsigned* current_add_interf_data;
+};
+
+static res_T
+add_trg
+ (const unsigned global_id,
+ const unsigned itri,
+ void* context)
+{
+ res_T res = RES_OK;
+ struct context* ctx = context;
+ struct merge_ctx* merge_ctx;
+ unsigned interf;
+ ASSERT(ctx);
+ merge_ctx = ctx->custom;
+ /* Get interface information from ctx */
+ interf = merge_ctx->current_add_interf_data[itri];
+ /* Keep data */
+ res = darray_intface_id_resize(&merge_ctx->global_interf_data, global_id + 1);
+ if(res != RES_OK) return res;
+ darray_intface_id_data_get(&merge_ctx->global_interf_data)[global_id] = interf;
+ return res;
+}
+
+static res_T
+merge_trg
+ (const unsigned global_id,
+ const unsigned itri,
+ const int reversed_triangle,
+ void* context)
+{
+ res_T res = RES_OK;
+ struct context* ctx = context;
+ struct merge_ctx* merge_ctx;
+ int need_merge;
+ unsigned interf;
+ unsigned* interf_data;
+ ASSERT(ctx); (void)reversed_triangle;
+ merge_ctx = ctx->custom;
+ res = darray_intface_id_resize(&merge_ctx->global_interf_data, global_id + 1);
+ if(res != RES_OK) return res;
+ /* Get interface information from ctx */
+ interf = merge_ctx->current_add_interf_data[itri];
+
+ interf_data = darray_intface_id_data_get(&merge_ctx->global_interf_data);
+
+ need_merge = (interf_data[global_id] != INVALID_INTFACE_ID);
+ if (need_merge) {
+ if (interf_data[global_id] != interf)
+ /* Previous interface id is different: no possible merge */
+ return RES_BAD_ARG;
+ } else {
+ /* Triangle is known, but without interface information: create */
+ interf_data[global_id] = interf;
+ }
+ return RES_OK;
+}
+
+static void
+test(const int convention)
+{
+ struct mem_allocator allocator;
+ struct senc_descriptor* desc = NULL;
+ struct senc_device* dev = NULL;
+ struct senc_scene* scn = NULL;
+ struct senc_enclosure* enclosure;
+ struct senc_enclosure_header header;
+ unsigned medium, expected_external_medium, expected_internal_medium;
+ unsigned gid;
+ enum senc_side side;
+ struct context ctx;
+ unsigned i, t, ecount, vcount, tcount, scount;
+ unsigned media[12], interface_ids[12] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
+ unsigned rev_box_indices[sizeof(box_indices) / sizeof(*box_indices)];
+ struct merge_ctx merge_ctx;
+ const int conv_front = (convention & SENC_CONVENTION_NORMAL_FRONT) != 0;
+
+ darray_intface_id_init(&allocator, &merge_ctx.global_interf_data);
+ merge_ctx.current_add_interf_data = interface_ids;
+
+ /* Create a box with reversed triangles */
+ FOR_EACH(i, 0, sizeof(rev_box_indices) / sizeof(*rev_box_indices)) {
+ switch (i % 3) {
+ case 0: rev_box_indices[i] = box_indices[i]; break;
+ case 1: rev_box_indices[i] = box_indices[i + 1]; break;
+ case 2: rev_box_indices[i] = box_indices[i - 1]; break;
+ }
+ }
+ OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator));
+ OK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev));
+
+ OK(senc_scene_create(dev, convention, &scn));
+
+ /* A 3D cube.
+ * 2 enclosures (inside, outside) sharing the same triangles,
+ * but opposite sides */
+ ctx.positions = box_vertices;
+ ctx.indices = box_indices;
+ ctx.scale = 1;
+ ctx.reverse_vrtx = 0;
+ ctx.reverse_med = 0;
+ d3(ctx.offset, 0, 0, 0);
+ ctx.front_media = media;
+ ctx.back_media = medium1;
+ ctx.custom = &merge_ctx;
+
+ /* Can add the same triangles again defined/undefined media in any order */
+
+ /* Add geometry with no media information on both sides */
+ for (i = 0; i < sizeof(media) / sizeof(*media); i++)
+ media[i] = SENC_UNDEFINED_MEDIUM;
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, NULL,
+ nvertices, get_position, add_trg, merge_trg, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == 2 * ntriangles);
+
+ /* If merge fails, add geometry fails */
+ interface_ids[0] = 6;
+ BA(senc_scene_add_geometry(scn, ntriangles, get_indices, NULL,
+ nvertices, get_position, add_trg, merge_trg, &ctx));
+ interface_ids[0] = 0;
+
+ /* Add geometry with no media information on the front sides */
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, add_trg, merge_trg, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == ntriangles);
+
+ /* Analyze with undefined media on the front sides */
+ OK(senc_scene_analyze(scn, &desc));
+ OK(senc_descriptor_get_enclosure_count(desc, &ecount));
+ CHK(ecount == 2);
+
+ FOR_EACH(i, 0, ecount) {
+ struct senc_enclosure* ee;
+ struct senc_enclosure_header hh;
+ unsigned cc;
+ OK(senc_descriptor_get_enclosure(desc, i, &enclosure));
+ OK(senc_enclosure_get_header(enclosure, &header));
+
+ CHK(header.enclosure_id == i);
+ CHK(header.enclosed_media_count == 1);
+
+ OK(senc_enclosure_get_medium(enclosure, 0, &medium));
+ /* Geometrical normals point outside the cube in input triangles:
+ * if convention is front, front medium (undef) is outside,
+ * that is medium 0's enclosure is infinite */
+ expected_external_medium = conv_front ? SENC_UNDEFINED_MEDIUM : 1;
+ expected_internal_medium = conv_front ? 1 :SENC_UNDEFINED_MEDIUM;
+
+ CHK(medium == (header.is_infinite
+ ? expected_external_medium : expected_internal_medium));
+ CHK(header.triangle_count == ntriangles);
+ CHK(header.unique_triangle_count == ntriangles);
+ CHK(header.vertices_count == nvertices);
+ CHK(header.is_infinite == (i == 0));
+
+ OK(senc_descriptor_get_enclosure_count_by_medium(desc, medium, &cc));
+ CHK(cc == 1);
+ OK(senc_descriptor_get_enclosure_by_medium(desc, medium, 0, &ee));
+ OK(senc_enclosure_get_header(ee, &hh));
+ CHK(header.enclosure_id == hh.enclosure_id);
+ OK(senc_enclosure_ref_put(ee));
+
+ FOR_EACH(t, 0, header.triangle_count) {
+ unsigned ind[3];
+ OK(senc_enclosure_get_triangle_global_id(enclosure, t, &gid, &side));
+ CHK(gid == t);
+ CHK(side == (medium == 1) ? SENC_BACK : SENC_FRONT);
+ OK(senc_enclosure_get_triangle(enclosure, t, ind));
+ }
+ OK(senc_enclosure_ref_put(enclosure));
+ }
+ OK(senc_descriptor_ref_put(desc));
+
+ /* Same geometry, front media are defined for odd triangles */
+ for (i = 0; i < sizeof(media) / sizeof(*media); i++)
+ media[i] = (i % 2) ? 0 : SENC_UNDEFINED_MEDIUM;
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, add_trg, merge_trg, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == ntriangles / 2);
+
+ /* Analyze with undefined media */
+ OK(senc_scene_analyze(scn, &desc));
+ OK(senc_descriptor_ref_put(desc));
+
+ /* Get the deduplicated geometry without (successful) analyze */
+ OK(senc_scene_get_unique_vertices_count(scn, &vcount));
+ CHK(vcount == nvertices);
+ OK(senc_scene_get_unique_triangles_count(scn, &tcount));
+ CHK(tcount == ntriangles);
+ FOR_EACH(i, 0, tcount) {
+ int j;
+ unsigned med[2], ids[3];
+ OK(senc_scene_get_unique_triangle(scn, i, ids));
+ OK(senc_scene_get_unique_triangle_media(scn, i, med));
+ CHK(med[0] == ((i % 2) ? 0 : SENC_UNDEFINED_MEDIUM) && med[1] == 1);
+ FOR_EACH(j, 0, 3) {
+ double pos[3];
+ CHK(ids[j] < vcount);
+ OK(senc_scene_get_unique_vertex(scn, ids[j], pos));
+ }
+ }
+
+ /* Same information again, using a reversed box */
+ ctx.indices = rev_box_indices;
+ SWAP(const unsigned*, ctx.front_media, ctx.back_media);
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, add_trg, merge_trg, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == ntriangles / 2);
+
+ /* Analyze with undefined media */
+ OK(senc_scene_analyze(scn, &desc));
+ OK(senc_descriptor_ref_put(desc));
+
+ /* Define media for remaining triangles, using reversed box */
+ for (i = 0; i < sizeof(media) / sizeof(*media); i++)
+ media[i] = (i % 2) ? SENC_UNDEFINED_MEDIUM : 0;
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, add_trg, merge_trg, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == 0);
+
+ /* Get the deduplicated geometry without (successful) analyze */
+ OK(senc_scene_get_unique_vertices_count(scn, &vcount));
+ CHK(vcount == nvertices);
+ OK(senc_scene_get_unique_triangles_count(scn, &tcount));
+ CHK(tcount == ntriangles);
+ FOR_EACH(i, 0, tcount) {
+ int j;
+ unsigned med[2], ids[3];
+ OK(senc_scene_get_unique_triangle(scn, i, ids));
+ OK(senc_scene_get_unique_triangle_media(scn, i, med));
+ CHK(med[0] == 0 && med[1] == 1);
+ FOR_EACH(j, 0, 3) {
+ double pos[3];
+ CHK(ids[j] < vcount);
+ OK(senc_scene_get_unique_vertex(scn, ids[j], pos));
+ }
+ }
+
+ /* Analyze with all media defined */
+ OK(senc_scene_analyze(scn, &desc));
+ OK(senc_descriptor_ref_put(desc));
+
+ /* Define media for all triangles, nothing new here */
+ for (i = 0; i < sizeof(media) / sizeof(*media); i++)
+ media[i] = 0;
+ OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, add_trg, merge_trg, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == 0);
+
+ /* Define incoherent media for some triangles */
+ for (i = 0; i < sizeof(media) / sizeof(*media); i++)
+ media[i] = (i % 2);
+ BA(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
+ nvertices, get_position, add_trg, merge_trg, &ctx));
+ OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount));
+ CHK(scount == 0);
+
+ /* Scene is still OK and can be analyzed */
+ OK(senc_scene_analyze(scn, &desc));
+
+ OK(senc_descriptor_get_global_triangles_count(desc, &tcount));
+ CHK(tcount == sizeof(media) / sizeof(*media));
+
+ OK(senc_descriptor_get_enclosure_count(desc, &ecount));
+ CHK(ecount == 2);
+
+ FOR_EACH(i, 0, ecount) {
+ struct senc_enclosure* ee;
+ struct senc_enclosure_header hh;
+ unsigned cc;
+ OK(senc_descriptor_get_enclosure(desc, i, &enclosure));
+ OK(senc_enclosure_get_header(enclosure, &header));
+
+ CHK(header.enclosure_id == i);
+ CHK(header.enclosed_media_count == 1);
+ OK(senc_enclosure_get_medium(enclosure, 0, &medium));
+ /* Geometrical normals point outside the cube in input triangles:
+ * if convention is front, front medium (0) is outside,
+ * that is medium 0's enclosure is infinite */
+ CHK(conv_front == ((medium == 0) == header.is_infinite));
+ CHK(header.triangle_count == ntriangles);
+ CHK(header.unique_triangle_count == ntriangles);
+ CHK(header.vertices_count == nvertices);
+ CHK(header.is_infinite == (i == 0));
+
+ OK(senc_descriptor_get_enclosure_count_by_medium(desc, medium, &cc));
+ CHK(cc == 1);
+ OK(senc_descriptor_get_enclosure_by_medium(desc, medium, 0, &ee));
+ OK(senc_enclosure_get_header(ee, &hh));
+ CHK(header.enclosure_id == hh.enclosure_id);
+ OK(senc_enclosure_ref_put(ee));
+
+ FOR_EACH(t, 0, header.triangle_count) {
+ OK(senc_enclosure_get_triangle_global_id(enclosure, t, &gid, &side));
+ CHK(gid == t);
+ CHK(side == (medium == 1) ? SENC_BACK : SENC_FRONT);
+ }
+ OK(senc_enclosure_ref_put(enclosure));
+ }
+
+ SENC(scene_ref_put(scn));
+ SENC(device_ref_put(dev));
+ SENC(descriptor_ref_put(desc));
+ darray_intface_id_release(&merge_ctx.global_interf_data);
+
+ check_memory_allocator(&allocator);
+ mem_shutdown_proxy_allocator(&allocator);
+ CHK(mem_allocated_size() == 0);
+}
+
+int
+main(int argc, char** argv)
+{
+ (void) argc, (void) argv;
+ test(SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE);
+ test(SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_INSIDE);
+ test(SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_OUTSIDE);
+ test(SENC_CONVENTION_NORMAL_BACK | SENC_CONVENTION_NORMAL_OUTSIDE);
+ return 0;
+}
diff --git a/src/test_senc_utils.h b/src/test_senc_utils.h
@@ -22,6 +22,9 @@
#include <stdio.h>
+#define OK(Expr) CHK((Expr) == RES_OK)
+#define BA(Expr) CHK((Expr) == RES_BAD_ARG)
+
/*******************************************************************************
* Geometry
******************************************************************************/
@@ -78,7 +81,7 @@ struct context {
const unsigned* indices;
const unsigned* front_media;
const unsigned* back_media;
- const unsigned* global_ids;
+ void* custom;
double offset[3];
double scale;
char reverse_vrtx, reverse_med;
@@ -91,12 +94,10 @@ static const unsigned medium1_3[12] = { 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1 };
static const unsigned medium1_back0[12] = { 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 };
static const unsigned medium1_front0[12] = { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
-static const unsigned gid_face[12] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5 };
-
static INLINE void
get_indices(const unsigned itri, unsigned ids[3], void* context)
{
- struct context* ctx = context;
+ const struct context* ctx = context;
ASSERT(ids && ctx);
ids[0] = ctx->indices[itri * 3 + 0];
ids[ctx->reverse_vrtx ? 2 : 1] = ctx->indices[itri * 3 + 1];
@@ -106,7 +107,7 @@ get_indices(const unsigned itri, unsigned ids[3], void* context)
static INLINE void
get_position(const unsigned ivert, double pos[3], void* context)
{
- struct context* ctx = context;
+ const struct context* ctx = context;
ASSERT(pos && ctx);
pos[0] = ctx->positions[ivert * 3 + 0] * ctx->scale + ctx->offset[0];
pos[1] = ctx->positions[ivert * 3 + 1] * ctx->scale + ctx->offset[1];
@@ -116,20 +117,12 @@ get_position(const unsigned ivert, double pos[3], void* context)
static INLINE void
get_media(const unsigned itri, unsigned medium[2], void* context)
{
- struct context* ctx = context;
+ const struct context* ctx = context;
ASSERT(medium && ctx);
medium[ctx->reverse_med ? 1 : 0] = ctx->front_media[itri];
medium[ctx->reverse_med ? 0 : 1] = ctx->back_media[itri];
}
-static INLINE void
-get_global_id(const unsigned itri, unsigned* gid, void* context)
-{
- struct context* ctx = context;
- ASSERT(gid && context);
- *gid = ctx->global_ids[itri];
-}
-
/*******************************************************************************
* Miscellaneous
******************************************************************************/
@@ -201,7 +194,7 @@ static INLINE void
check_memory_allocator(struct mem_allocator* allocator)
{
if(MEM_ALLOCATED_SIZE(allocator)) {
- char dump[128];
+ char dump[1024];
MEM_DUMP(allocator, dump, sizeof(dump));
fprintf(stderr, "%s\n", dump);
FATAL("Memory leaks.\n");