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 43cd6f1031dab4b70b806a42d1e0d3f2b163a7ef
parent fc91c9efee867a2b670ee4a2070bcfe87217e38c
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 11 Oct 2019 14:51:55 +0200

Allow to analyze scenes including sides with undefined medium

Diffstat:
Msrc/senc.h | 22+++++++++++++++-------
Msrc/senc_descriptor.c | 28+++++++++++++++++++---------
Msrc/senc_enclosure_data.h | 13+++++++------
Msrc/senc_scene.c | 27+++++++++++++++++++--------
Msrc/senc_scene_analyze.c | 67++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/senc_scene_c.h | 2+-
Msrc/test_senc_scene.c | 12++++++++++--
Msrc/test_senc_undefined_medium.c | 98++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/test_senc_utils.h | 2+-
9 files changed, 203 insertions(+), 68 deletions(-)

diff --git a/src/senc.h b/src/senc.h @@ -69,7 +69,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. */ @@ -165,7 +166,8 @@ senc_scene_reserve /* 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. + * 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 is kept (with its original @@ -176,15 +178,15 @@ senc_scene_add_geometry (struct senc_scene* scene, const unsigned triangles_count, 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), + void(*media) /* Can be NULL <=> SENC_UNDEFINED_MEDIUM medium used */ + (const unsigned itri, unsigned med[2], void* context), + void(*global_id) /* Can be NULL <=> use triangle rank */ + (const unsigned itri, unsigned* gid, void* context), const unsigned vertices_count, void(*position)(const unsigned ivert, double pos[3], void* context), void* context); -/* Returns a descriptor of the scene that holds the analysis' result. - * Its an error that some triangle side still has undefined medium. */ +/* Returns a descriptor of the scene that holds the analysis' result. */ SENC_API res_T senc_scene_analyze (struct senc_scene* scene, @@ -209,6 +211,12 @@ 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 triangles; the returned indices are * unique vertex indices. * Can be called anytime, before or after a call to analyze. */ 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); diff --git a/src/senc_enclosure_data.h b/src/senc_enclosure_data.h @@ -83,23 +83,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: diff --git a/src/senc_scene.c b/src/senc_scene.c @@ -83,7 +83,7 @@ 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; @@ -147,7 +147,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; @@ -193,7 +193,7 @@ 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, *range_adjust_ptr = NULL; @@ -229,12 +229,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] != SENC_UNDEFINED_MEDIUM && med[j] >= scn->nmeds) { + if(med[j] != SENC_UNDEFINED_MEDIUM && med[j] >= scn->next_medium_idx) { ASSERT(med[j] < MEDIUM_MAX__); - scn->nmeds = med[j] + 1; - darray_side_range_resize(&scn->media_use, scn->nmeds); + 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]; } @@ -307,7 +307,7 @@ senc_scene_add_geometry FOR_EACH(j, 0, 2) { struct side_range* media_use; if(tmp.medium[j] == SENC_UNDEFINED_MEDIUM) continue; - ASSERT(tmp.medium[j] < scn->nmeds); + 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((trg_id_t)u, j)); @@ -368,6 +368,17 @@ 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, diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c @@ -150,7 +150,7 @@ extract_connex_components * concurrently. */ 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__; @@ -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); @@ -318,6 +335,8 @@ 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))) { @@ -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(&current_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! */ @@ -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; @@ -912,8 +931,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 */ @@ -1032,9 +1053,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 +1063,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); @@ -1179,12 +1206,6 @@ senc_scene_analyze if(!scn || !out_desc) return RES_BAD_ARG; - if(scn->sides_with_defined_medium_count < 2 * scn->nutris) { - log_err(scn->dev, - "%s: not all triangles have defined media on both sides.\n", FUNC_NAME); - return RES_BAD_ARG; - } - desc = descriptor_create(scn); if(!desc) { res = RES_MEM_ERR; @@ -1240,7 +1261,7 @@ senc_scene_analyze 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)); diff --git a/src/senc_scene_c.h b/src/senc_scene_c.h @@ -217,7 +217,7 @@ 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; diff --git a/src/test_senc_scene.c b/src/test_senc_scene.c @@ -85,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 */ @@ -104,8 +114,6 @@ main(int argc, char** argv) nvertices, get_position, &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); CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, get_global_id, 0, get_position, &ctx) == RES_BAD_ARG); CHK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, diff --git a/src/test_senc_undefined_medium.c b/src/test_senc_undefined_medium.c @@ -30,13 +30,17 @@ test(enum senc_convention convention) struct senc_scene* scn = NULL; struct senc_enclosure* enclosure; struct senc_enclosure_header header; - unsigned medium; + unsigned medium, expected_external_medium, expected_internal_medium; unsigned gid; struct context ctx; - unsigned i, t, ecount, vcount, tcount; + unsigned i, t, ecount, vcount, tcount, scount; int is_front, is_in; unsigned media[12]; unsigned rev_box_indices[sizeof(box_indices) / sizeof(*box_indices)]; + int conv_front, conv_in; + + conv_front = (convention & SENC_CONVENTION_NORMAL_FRONT) != 0; + conv_in = (convention & SENC_CONVENTION_NORMAL_INSIDE) != 0; /* Create the box with reversed triangles */ FOR_EACH(i, 0, sizeof(rev_box_indices) / sizeof(*rev_box_indices)) { @@ -67,23 +71,77 @@ test(enum senc_convention convention) /* Can add the same triangles again defined/undefined media in any order */ - /* Add geometry with no media information */ + /* 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, + NULL, nvertices, get_position, &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, NULL, nvertices, get_position, &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); - /* Cannot run analyze with undefined media */ - BA(senc_scene_analyze(scn, &desc)); + 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)); + CHK(gid == t); + 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, NULL, nvertices, get_position, &ctx)); + OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount)); + CHK(scount == ntriangles / 2); - /* Cannot run analyze with undefined media */ - BA(senc_scene_analyze(scn, &desc)); + /* 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)); @@ -108,15 +166,20 @@ test(enum senc_convention convention) SWAP(const unsigned*, ctx.front_media, ctx.back_media); OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL, nvertices, get_position, &ctx)); + OK(senc_scene_get_unique_sides_without_medium_count(scn, &scount)); + CHK(scount == ntriangles / 2); - /* Cannot run analyze with undefined media */ - BA(senc_scene_analyze(scn, &desc)); + /* 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, NULL, nvertices, get_position, &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)); @@ -136,7 +199,7 @@ test(enum senc_convention convention) } } - /* Can run analyze */ + /* Analyze with all media defined */ OK(senc_scene_analyze(scn, &desc)); OK(senc_descriptor_ref_put(desc)); @@ -145,17 +208,20 @@ test(enum senc_convention convention) media[i] = 0; OK(senc_scene_add_geometry(scn, ntriangles, get_indices, get_media, NULL, nvertices, get_position, &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, NULL, nvertices, get_position, &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)); @@ -163,6 +229,9 @@ test(enum senc_convention convention) 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)); @@ -178,6 +247,13 @@ test(enum senc_convention convention) 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)); CHK(gid == t); diff --git a/src/test_senc_utils.h b/src/test_senc_utils.h @@ -204,7 +204,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");