star-enclosures-3d

Extract enclosures from 3D geometry
git clone git://git.meso-star.fr/star-enclosures-3d.git
Log | Files | Refs | README | LICENSE

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:
Mcmake/CMakeLists.txt | 1+
Msrc/senc.h | 14++++++++++++++
Msrc/senc_scene.c | 16+++++++++++++++-
Msrc/senc_scene_analyze.c | 42++++++++++++++++++++++++++++++++++--------
Msrc/senc_scene_analyze_c.h | 3+++
Msrc/senc_scene_c.h | 3+++
Msrc/test_senc_cube_behind_cube.c | 2+-
Msrc/test_senc_cube_in_cube.c | 2+-
Msrc/test_senc_cube_on_cube.c | 2+-
Msrc/test_senc_descriptor.c | 2+-
Msrc/test_senc_enclosure.c | 4++--
Asrc/test_senc_inconsistant_cube.c | 194+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_senc_many_enclosures.c | 2+-
Msrc/test_senc_many_triangles.c | 2+-
Msrc/test_senc_sample_enclosure.c | 2+-
Msrc/test_senc_scene.c | 47+++++++++++++++++++++++++++++++++++++++--------
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,