commit a56c082439cb679a890af1f7e8179f346a22bbfc
parent 6eff3fc4983d92db883095405347910a3b1e366a
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Tue, 11 Sep 2018 18:47:44 +0200
Fix Front/Back convention
Additionally convention can now be chosen
Diffstat:
16 files changed, 312 insertions(+), 26 deletions(-)
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
@@ -126,6 +126,7 @@ if(NOT NO_TEST)
new_test(test_senc_descriptor)
new_test(test_senc_device)
new_test(test_senc_enclosure)
+ new_test(test_senc_inconsistant_cube)
new_test(test_senc_many_enclosures)
new_test(test_senc_many_triangles)
new_test(test_senc_sample_enclosure)
diff --git a/src/senc.h b/src/senc.h
@@ -73,6 +73,14 @@ struct senc_enclosure_header {
char is_infinite;
};
+/* Type used to define the convention for Front / Back sides.
+ * When looking at the Front side, vertices (in the order they are given in
+ * triangle definitions) can be seen either CW or CCW. */
+enum senc_side_convention {
+ SENC_CONVENTION_CW, /* Order is ClockWise */
+ SENC_CONVENTION_CCW /* Order is CounterClockWise */
+};
+
BEGIN_DECLS
/*******************************************************************************
@@ -104,6 +112,7 @@ senc_device_ref_put
SENC_API res_T
senc_scene_create
(struct senc_device* device,
+ const enum senc_side_convention front_side_convention,
struct senc_scene** scene);
/* Add a new set of vertices and triangles to the scene.
@@ -130,6 +139,11 @@ senc_scene_analyze
struct senc_descriptor** descriptor);
SENC_API res_T
+senc_scene_get_convention
+ (const struct senc_scene* scene,
+ enum senc_side_convention* front_side_convention);
+
+SENC_API res_T
senc_scene_get_triangles_count
(const struct senc_scene* scene,
unsigned* count);
diff --git a/src/senc_scene.c b/src/senc_scene.c
@@ -48,12 +48,14 @@ scene_release(ref_T * ref)
res_T
senc_scene_create
(struct senc_device* dev,
+ const enum senc_side_convention conv,
struct senc_scene** out_scn)
{
struct senc_scene* scn = NULL;
res_T res = RES_OK;
- if(!dev || !out_scn)
+ if(!dev || !out_scn
+ || (conv != SENC_CONVENTION_CW && conv != SENC_CONVENTION_CCW))
return RES_BAD_ARG;
scn = MEM_CALLOC(dev->allocator, 1, sizeof(struct senc_scene));
@@ -65,6 +67,7 @@ senc_scene_create
ref_init(&scn->ref);
SENC(device_ref_get(dev));
scn->dev = dev;
+ scn->convention = conv;
scn->ngeoms = 0;
scn->ntris = 0;
scn->nutris = 0;
@@ -281,6 +284,17 @@ error:
}
res_T
+senc_scene_get_convention
+ (const struct senc_scene* scn,
+ enum senc_side_convention* front_side_convention)
+{
+ if(!scn || !front_side_convention) return RES_BAD_ARG;
+ *front_side_convention = scn->convention;
+ return RES_OK;
+
+}
+
+res_T
senc_scene_get_triangles_count
(const struct senc_scene* scn,
unsigned* count)
diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c
@@ -388,7 +388,7 @@ extract_connex_components
/* To garanty that triangles with 2 sides in the component total to 0
* regardless of numeric accuracy, we need to prevent them to
- * contribute (remember than x + y - x - y can be non-zero). */
+ * contribute (remember than x + y - y == 0 can be false). */
ASSERT(trg_comp->component[SIDE_FRONT] == cc->cc_id
|| trg_comp->component[SIDE_BACK] == cc->cc_id);
if(trg_comp->component[SIDE_FRONT] == trg_comp->component[SIDE_BACK])
@@ -400,10 +400,11 @@ extract_connex_components
vertices[trg_in->vertice_id[0]].vec);
d3_cross(normal, edge0, edge1);
norm = d3_normalize(normal, normal);
- ASSERT(norm); (void) norm;
+ ASSERT(norm); (void)norm;
- /* Geometrical normal points toward the front side */
- if(TRGSIDE_IS_FRONT(side_id)) {
+ /* Geometrical normal points toward the front side
+ * if convention is CW, toward back side if CCW */
+ if(TRGSIDE_IS_FRONT(side_id) == (scn->convention == SENC_CONVENTION_CW)) {
max_z_nz += normal[2];
} else {
max_z_nz -= normal[2];
@@ -769,6 +770,8 @@ collect_and_link_neighbours
const unsigned char crt_edge = neighbour_info->common_edge_rank;
const struct triangle_in* trg_in = triangles_in + crt_id;
struct triangle_tmp* neighbour = triangles_tmp + crt_id;
+ union double3 n; /* Geometrical normal to neighbour triangle */
+ const int is_reversed = neighbour->reversed_edge[crt_edge];
v2 = trg_in->vertice_id[(crt_edge + 2) % 3];
max_z = MMAX(vertices[v2].pos.z, maxz_edge);
ASSERT(neighbour->max_z <= max_z);
@@ -778,9 +781,29 @@ collect_and_link_neighbours
d33_muld3(edge, basis, edge);
ASSERT(d3_len(edge) && (edge[0] || edge[1]));
neighbour_info->angle = atan2(edge[1], edge[0]);
+ if(is_reversed)
+ d3(n.vec, +edge[1], -edge[0], 0);
+ else
+ d3(n.vec, -edge[1], +edge[0], 0);
if(neighbour_info->angle < 0) neighbour_info->angle += 2 * PI;
- /* Due to catastrophic cancelation, -eps+2pi translates to 2pi */
- ASSERT(0 <= neighbour_info->angle && neighbour_info->angle <= 2 * PI);
+
+ /* Normal orientation calculation. */
+ if(neighbour_info->angle <= PI / 4) {
+ ASSERT(n.pos.y);
+ neighbour_info->normal_toward_next_neighbour = (n.pos.y > 0);
+ } else if (neighbour_info->angle <= 3 * PI / 4) {
+ ASSERT(n.pos.x);
+ neighbour_info->normal_toward_next_neighbour = (n.pos.x < 0);
+ } else if (neighbour_info->angle <= 5 * PI / 4) {
+ ASSERT(n.pos.y);
+ neighbour_info->normal_toward_next_neighbour = (n.pos.y < 0);
+ } else if (neighbour_info->angle <= 7 * PI / 4) {
+ ASSERT(n.pos.x);
+ neighbour_info->normal_toward_next_neighbour = (n.pos.x > 0);
+ } else {
+ ASSERT(n.pos.y);
+ neighbour_info->normal_toward_next_neighbour = (n.pos.y > 0);
+ }
}
/* Sort triangles by rotation angle */
qsort(darray_neighbour_data_get(neighbour_list), neighbour_count,
@@ -803,10 +826,12 @@ collect_and_link_neighbours
const trg_id_t crt_id = current->trg_id;
const trg_id_t ccw_id = ccw_neighbour->trg_id;
/* Facing sides of triangles */
+ const int cw = (scn->convention == SENC_CONVENTION_CW);
const enum side_id crt_side
- = triangles_tmp[crt_id].reversed_edge[crt_edge] ? SIDE_BACK : SIDE_FRONT;
+ = current->normal_toward_next_neighbour == cw ? SIDE_FRONT : SIDE_BACK;
const enum side_id ccw_side
- = triangles_tmp[ccw_id].reversed_edge[ccw_edge] ? SIDE_FRONT : SIDE_BACK;
+ = ccw_neighbour->normal_toward_next_neighbour == cw ?
+ SIDE_BACK : SIDE_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);
@@ -816,6 +841,7 @@ collect_and_link_neighbours
/* Link sides */
p_crt_side->facing_side_id[crt_edge] = ccw_side_idx;
p_ccw_side->facing_side_id[ccw_edge] = crt_side_idx;
+
/* Record media */
p_crt_side->medium = triangles_in[crt_id].medium[crt_side];
p_ccw_side->medium = triangles_in[ccw_id].medium[ccw_side];
diff --git a/src/senc_scene_analyze_c.h b/src/senc_scene_analyze_c.h
@@ -190,6 +190,9 @@ struct neighbour_info {
trg_id_t trg_id;
/* Rank of the edge in the triangle (in [0 2]) */
unsigned char common_edge_rank;
+ /* Does the geometrical normal point towards the next neighbour
+ * (if not, it points towards the previous one)? */
+ unsigned char normal_toward_next_neighbour;
};
#define DARRAY_NAME neighbour
#define DARRAY_DATA struct neighbour_info
diff --git a/src/senc_scene_c.h b/src/senc_scene_c.h
@@ -196,6 +196,9 @@ side_range_init(struct mem_allocator* alloc, struct side_range* data)
#include <rsys/dynamic_array.h>
struct senc_scene {
+ /* Front / Back sides convention */
+ enum senc_side_convention convention;
+
/* Triangle information as given by user; no duplicates here */
struct darray_triangle_in triangles_in;
diff --git a/src/test_senc_cube_behind_cube.c b/src/test_senc_cube_behind_cube.c
@@ -34,7 +34,7 @@ main(int argc, char** argv)
(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev) == RES_OK);
/* Create the scene */
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == RES_OK);
ctx.positions = box_vertices;
ctx.indices = box_indices;
diff --git a/src/test_senc_cube_in_cube.c b/src/test_senc_cube_in_cube.c
@@ -34,7 +34,7 @@ main(int argc, char** argv)
(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev) == RES_OK);
/* Create the scene */
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == RES_OK);
ctx.positions = box_vertices;
ctx.indices = box_indices;
diff --git a/src/test_senc_cube_on_cube.c b/src/test_senc_cube_on_cube.c
@@ -57,7 +57,7 @@ main(int argc, char** argv)
(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev) == RES_OK);
/* Create the scene */
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == RES_OK);
ctx.positions = cube_vertices; /* Need true cubes for cubes #1 and #2 */
ctx.indices = box_indices;
diff --git a/src/test_senc_descriptor.c b/src/test_senc_descriptor.c
@@ -39,7 +39,7 @@ main(int argc, char** argv)
CHK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)
== RES_OK);
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == RES_OK);
/* A 3D cube */
ctx.positions = box_vertices;
diff --git a/src/test_senc_enclosure.c b/src/test_senc_enclosure.c
@@ -47,7 +47,7 @@ main(int argc, char** argv)
CHK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)
== RES_OK);
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == RES_OK);
s3d_attribs.type = S3D_FLOAT3;
s3d_attribs.usage = S3D_POSITION;
@@ -187,7 +187,7 @@ main(int argc, char** argv)
/* Same 3D cube, but with a hole (incomplete).
* 1 single enclosure including both sides of triangles */
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CCW, &scn) == RES_OK);
ctx.positions = box_vertices;
ctx.indices = box_indices;
diff --git a/src/test_senc_inconsistant_cube.c b/src/test_senc_inconsistant_cube.c
@@ -0,0 +1,193 @@
+/* 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>
+
+/* The following array lists the indices toward the 3D vertices of each
+* triangle.
+* ,6---,7 ,6----7
+* ,' | ,'/| ,' | \ | Y Z
+* 2----3' / | 2', | \ | | ,'
+* |', | / ,5 | ',4---,5 0----X
+* | ',|/,' | ,' | ,'
+* 0----1' 0----1'
+* Front, right Back, left and
+* and Top faces bottom faces */
+/* Triangle #1 rotation order is not consistant with other triangles */
+static unsigned
+inconsistant_box_indices[12/*#triangles*/ * 3/*#indices per triangle*/] = {
+ 0, 1, 2, 1, 2, 3, /* Front face */
+ 0, 4, 2, 2, 4, 6, /* Left face*/
+ 4, 5, 6, 6, 5, 7, /* Back face */
+ 3, 7, 1, 1, 7, 5, /* Right face */
+ 2, 6, 3, 3, 6, 7, /* Top face */
+ 0, 1, 4, 4, 1, 5 /* Bottom face */
+};
+static const unsigned inconsistant_box_ntriangles
+= sizeof(inconsistant_box_indices) / (3 * sizeof(*inconsistant_box_indices));
+
+/* Media definitions reflect triangle #1 inconsistancy */
+static const unsigned
+inconsistant_medium_front[12] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+static const unsigned
+inconsistant_medium_back[12] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+
+void
+cmp_trg
+ (const unsigned itri,
+ const struct senc_enclosure* enclosure,
+ const unsigned trg2[3],
+ const double* vertices2,
+ int* trg_eq,
+ int* trg_reversed)
+{
+ unsigned trg1[3];
+ double t1[3][3];
+ double t2[3][3];
+ unsigned trg1_eq[3] = { 3, 3, 3 };
+ unsigned i, j, fst_vrtx = 3;
+
+ ASSERT(enclosure && trg2 && vertices2 && trg_eq && trg_reversed);
+ CHK(senc_enclosure_get_triangle(enclosure, itri, trg1) == RES_OK);
+ FOR_EACH(i, 0, 3) {
+ CHK(senc_enclosure_get_vertex(enclosure, trg1[i], t1[i]) == RES_OK);
+ d3_set(t2[i], vertices2 + (3 * trg2[i]));
+ }
+ FOR_EACH(i, 0, 3) {
+ FOR_EACH(j, 0, 3) {
+ if (d3_eq(t1[i], t2[j])) {
+ trg1_eq[i] = j;
+ if(i == 0) fst_vrtx = j;
+ break;
+ }
+ }
+ }
+ FOR_EACH(i, 0, 3) {
+ if(trg1_eq[i] == 3) {
+ *trg_eq = 0;
+ return;
+ }
+ if(trg1_eq[i] == trg1_eq[(i + 1) % 3]
+ || trg1_eq[i] == trg1_eq[(i + 2) % 3]) {
+ *trg_eq = 0;
+ return;
+ }
+ }
+ /* Same 3 vertices */
+ ASSERT(fst_vrtx != 3);
+ *trg_eq = 1;
+
+ *trg_reversed = (trg1_eq[1] != (fst_vrtx + 1) % 3);
+ ASSERT(*trg_reversed != (trg1_eq[1] != (fst_vrtx + 2) % 3));
+}
+
+void
+test(enum senc_side_convention 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;
+ enum senc_side_convention conv;
+ struct context ctx;
+ unsigned i, e, ecount;
+
+ CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK);
+ CHK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)
+ == RES_OK);
+
+ CHK(senc_scene_create(dev, convention, &scn) == RES_OK);
+
+ /* A 3D cube.
+ * 2 enclosures (inside, outside) sharing the same triangles,
+ * but opposite sides.
+ * What differs in this test is that triangle #0 vertices are given
+ * in the opposite rotation order. */
+ ctx.positions = box_vertices;
+ ctx.indices = inconsistant_box_indices;
+ ctx.scale = 1;
+ ctx.reverse_vrtx = 0;
+ ctx.reverse_med = 0;
+ d3(ctx.offset, 0, 0, 0);
+ ctx.front_media = inconsistant_medium_front;
+ 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);
+
+ CHK(senc_scene_analyze(scn, &desc) == RES_OK);
+
+ CHK(senc_descriptor_get_enclosure_count(desc, &ecount) == RES_OK);
+ CHK(ecount == 2);
+
+ CHK(senc_scene_get_convention(scn, &conv) == RES_OK);
+ CHK(conv == convention);
+
+ FOR_EACH(e, 0, ecount) {
+ unsigned medium, expected_external_medium;
+ char name[128];
+ int common;
+ 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);
+ CHK(senc_enclosure_get_medium(enclosure, 0, &medium) == RES_OK);
+ /* If CW the external enclosure's medium should be 0, 1 if CCW */
+ expected_external_medium = (conv == SENC_CONVENTION_CW) ? 0 : 1;
+ CHK(header.is_infinite == (medium == expected_external_medium));
+ /* Common media, for non reversed triangles */
+ common = (conv == SENC_CONVENTION_CW)
+ ? !header.is_infinite : header.is_infinite;
+
+ snprintf(name, sizeof(name), "test_inconsistant_cube_%s_%u.obj",
+ (conv == SENC_CONVENTION_CW) ? "cw" : "ccw", e);
+ dump_enclosure(desc, e, name);
+
+ FOR_EACH(i, 0, header.triangle_count) {
+ int same, reversed;
+ cmp_trg(i, enclosure,
+ inconsistant_box_indices + (3 * i), box_vertices,
+ &same, &reversed);
+ /* Should be made of the same triangles */
+ CHK(same);
+ /* Triangle #0 always differs because it was given in the opposite order
+ * Depending on the convention, it is the only one to be/not to be reversed */
+ CHK(reversed == (i == 0 ? !common : common));
+ }
+ 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_CW);
+ test(SENC_CONVENTION_CCW);
+ return 0;
+}
+\ No newline at end of file
diff --git a/src/test_senc_many_enclosures.c b/src/test_senc_many_enclosures.c
@@ -90,7 +90,7 @@ main(int argc, char** argv)
/* 64^3 = 262144 cylinders */
#define NB_CYL (NB_CYL_1 * NB_CYL_1 * NB_CYL_1)
/* Create the scene */
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == RES_OK);
ctx.ctx.positions = NULL;
ctx.ctx.indices = NULL;
diff --git a/src/test_senc_many_triangles.c b/src/test_senc_many_triangles.c
@@ -87,7 +87,7 @@ main(int argc, char** argv)
#define NB_CYL 4
/* Create the scene */
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == RES_OK);
ctx.ctx.positions = NULL;
ctx.ctx.indices = NULL;
diff --git a/src/test_senc_sample_enclosure.c b/src/test_senc_sample_enclosure.c
@@ -48,7 +48,7 @@ main(int argc, char** argv)
CHK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)
== RES_OK);
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == RES_OK);
vrtx_get.type = S3D_FLOAT3;
vrtx_get.usage = S3D_POSITION;
diff --git a/src/test_senc_scene.c b/src/test_senc_scene.c
@@ -26,18 +26,32 @@ main(int argc, char** argv)
struct senc_device* dev = NULL;
struct senc_scene* scn = NULL;
struct senc_descriptor* desc = NULL;
+ struct senc_enclosure* enc = NULL;
+ struct senc_enclosure_header header;
struct context ctx;
+ unsigned medcw[2], medccw[2];
unsigned count, i, maxm;
+ enum senc_side_convention convention;
(void)argc, (void)argv;
CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK);
CHK(senc_device_create(NULL, &allocator, SENC_NTHREADS_DEFAULT, 1, &dev)
== RES_OK);
- CHK(senc_scene_create(NULL, &scn) == RES_BAD_ARG);
- CHK(senc_scene_create(dev, NULL) == RES_BAD_ARG);
- CHK(senc_scene_create(NULL, NULL) == RES_BAD_ARG);
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(NULL, SENC_CONVENTION_CW, &scn) == RES_BAD_ARG);
+ CHK(senc_scene_create(dev, 5, &scn) == RES_BAD_ARG);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_create(NULL, 5, &scn) == RES_BAD_ARG);
+ CHK(senc_scene_create(NULL, SENC_CONVENTION_CW, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_create(dev, 5, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_create(NULL, 5, NULL) == RES_BAD_ARG);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == 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);
+ CHK(senc_scene_get_convention(scn, &convention) == RES_OK);
+ CHK(convention == SENC_CONVENTION_CW);
CHK(senc_scene_get_triangles_count(NULL, &count) == RES_BAD_ARG);
CHK(senc_scene_get_triangles_count(scn, NULL) == RES_BAD_ARG);
@@ -63,7 +77,9 @@ main(int argc, char** argv)
CHK(senc_scene_get_unique_vertices_count(scn, &count) == RES_OK);
CHK(count == 0);
- /* A 3D cube */
+ /* A 3D cube.
+ * With this geometry front is inside with CCW convention,
+ * outside with CW convention */
ctx.positions = box_vertices;
ctx.indices = box_indices;
ctx.scale = 1;
@@ -111,10 +127,17 @@ main(int argc, char** argv)
CHK(senc_scene_ref_put(scn) == RES_OK);
CHK(senc_descriptor_ref_put(desc) == RES_OK);
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CCW, &scn) == RES_OK);
+ CHK(senc_scene_get_convention(scn, &convention) == RES_OK);
+ CHK(convention == SENC_CONVENTION_CCW);
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
get_global_id, nvertices, get_position, &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);
+ CHK(senc_enclosure_get_header(enc, &header) == RES_OK);
+ CHK(!header.is_infinite);
+ CHK(senc_enclosure_ref_put(enc) == RES_OK);
FOR_EACH(i, 0, ntriangles) {
unsigned gid;
@@ -122,11 +145,12 @@ main(int argc, char** argv)
/* gid has been set to gid_face. */
CHK(gid == gid_face[i]);
}
+ CHK(senc_descriptor_get_global_triangle_media(desc, 0, medccw) == 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, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == RES_OK);
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media,
get_global_id, nvertices, get_position, &ctx) == RES_OK);
/* Medium mismatch between neighbour segments, but OK */
@@ -147,10 +171,15 @@ main(int argc, char** argv)
ctx.front_media = medium0;
CHK(senc_scene_ref_put(scn) == RES_OK);
CHK(senc_descriptor_ref_put(desc) == RES_OK);
- CHK(senc_scene_create(dev, &scn) == RES_OK);
+ CHK(senc_scene_create(dev, SENC_CONVENTION_CW, &scn) == RES_OK);
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,
nvertices, get_position, &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);
+ CHK(senc_enclosure_get_header(enc, &header) == RES_OK);
+ CHK(header.is_infinite);
+ CHK(senc_enclosure_ref_put(enc) == RES_OK);
FOR_EACH(i, 0, ntriangles) {
unsigned gid;
@@ -158,6 +187,8 @@ main(int argc, char** argv)
/* Default gid: triangle rank. */
CHK(gid == i);
}
+ CHK(senc_descriptor_get_global_triangle_media(desc, 0, medcw) == RES_OK);
+ FOR_EACH(i, 0, 2) CHK(medccw[i] == medcw[i]);
/* Invalid vertex ID */
CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL,