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 19274ee8374934b6b8b0feced157fdd0ba3082c4
parent f714362a43df38fc2418344e8153905dcbd9f44c
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 20 Dec 2019 17:27:43 +0100

Remove most of API.

Just keep enclosures extraction from a single deduplicated geometry.

Diffstat:
Mcmake/CMakeLists.txt | 4++--
Msrc/senc.h | 223++++++++++++++++---------------------------------------------------------------
Msrc/senc_descriptor.c | 265++++++++++++++-----------------------------------------------------------------
Msrc/senc_descriptor_c.h | 147-------------------------------------------------------------------------------
Msrc/senc_enclosure.c | 27+++++++++++++--------------
Msrc/senc_enclosure_c.h | 6+++---
Msrc/senc_enclosure_data.h | 54++++++++++++++++++++++++++++++++++++++++++------------
Msrc/senc_internal_types.h | 2++
Msrc/senc_s3d_wrapper.h | 16++++++++--------
Msrc/senc_scene.c | 325++++++++++++++++++++++++-------------------------------------------------------
Msrc/senc_scene_analyze.c | 204++++++++++++++++++++++++++++++++++---------------------------------------------
Msrc/senc_scene_analyze_c.h | 8++++++--
Msrc/senc_scene_c.h | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Asrc/senc_side_range.h | 44++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_senc_add_n_merge.c | 2+-
Msrc/test_senc_cube_behind_cube.c | 263+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/test_senc_cube_in_cube.c | 4++--
Msrc/test_senc_cube_on_cube.c | 8++++----
Msrc/test_senc_descriptor.c | 60++++++++++++++++++++++++++++++------------------------------
Msrc/test_senc_enclosure.c | 4++--
Msrc/test_senc_inconsistant_cube.c | 4++--
Msrc/test_senc_many_enclosures.c | 8++++----
Msrc/test_senc_many_triangles.c | 8++++----
Msrc/test_senc_sample_enclosure.c | 4++--
Msrc/test_senc_scene.c | 74+++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/test_senc_undefined_medium.c | 22+++++++++++-----------
Msrc/test_senc_undefined_medium_attr.c | 24++++++++++++------------
Msrc/test_senc_utils.h | 67+++++++++++++++++++++++--------------------------------------------
28 files changed, 861 insertions(+), 1182 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -63,13 +63,13 @@ set(SENC_FILES_INC_API senc_s3d_wrapper.h) set(SENC_FILES_INC - senc_descriptor_c.h senc_device_c.h senc_enclosure_c.h senc_enclosure_data.h senc_internal_types.h senc_scene_c.h - senc_scene_analyze_c.h) + senc_scene_analyze_c.h + senc_side_range.h) set(SENC_FILES_DOC COPYING README.md) diff --git a/src/senc.h b/src/senc.h @@ -56,7 +56,6 @@ struct mem_allocator; * a reference on the data, i.e. they increment or decrement the reference * counter, respectively. When this counter reaches 0, the object is silently * destroyed and cannot be used anymore. */ -struct senc_descriptor; struct senc_device; struct senc_scene; struct senc_enclosure; @@ -156,83 +155,28 @@ senc_device_ref_put * StarEnclosures scene. A scene is a collection of triangles. Each triangle is * defined with a medium on each side. ******************************************************************************/ -/* Creates an empty scene */ +/* Creates a scene from some vertices and triangles. + * Neither vertices nor triangles can include duplicates. + * Triangles cannot be degenerated. */ SENC_API res_T senc_scene_create (struct senc_device* device, 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, + /* Number of triangles */ 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 silently deduplicated on the fly. - * Triangles can be duplicates as long as media are compatible on both sides. - * Valid triangle duplicates are silently deduplicated, invalid duplicates - * trigger an error (add_geometry returns RES_BAD_ARG). - * 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. - * Media on duplicate triangles are consider compatible if: - * - the merge_triangle callback is provided and returns RES_OK, - * - or media are identical or SENC_UNDEFINED_MEDIUM. - * When deduplicating triangles, the first occurence remains (with its - * original index in user world, regardless of deduplication); the only - * situation where deduplication changes a previously recorded media is from - * SENC_UNDEFINED_MEDIUM to any defined medium. - * The add_triangle and merge_triangle callbacks can be used for attribute - * management (including triangle IDs) and to record media incompatibilities - * for a subsequent report; they allow the client app to store its own data. - * By returning an error, they can also 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), - /* User function that provides media ids for added triangles */ - void(*media) /* Can be NULL <=> SENC_UNDEFINED_MEDIUM medium used */ + /* User function that provides vertices ids for triangles */ + void(*get_indices)(const unsigned itri, unsigned ids[3], void* context), + /* User function that provides media ids for triangles */ + void(*get_media) /* Can be NULL <=> SENC_UNDEFINED_MEDIUM medium used */ (const unsigned itri, unsigned med[2], void* context), - /* Number of added vertices */ + /* Number of 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 immediately and returns - * whatever value add_triangle returned. */ - 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 or record a possible media conflict. - * The reversed_triangle arg indicates if the triangle vertices' order is - * the same it was when the triangle was first added. - * triangle_media and merge_media contain the involved media. - * If those media are incompatible and merge_triangle returns RES_OK the - * process will continue with the next triangle and possibly end in success. - * If return is not RES_OK, add_geometry stops immediately and returns - * whatever value merge_triangle returned. - * If merge_triangle is NULL, a strict media compatibility is required for - * add_geometry to success: add_geometry would stop and return RES_BAD_ARG - * on the first occurence of duplicate triangle with incompatible media. */ - res_T(*merge_triangle) /* Can be NULL */ - (const unsigned global_id, const unsigned itri, const int reversed_triangle, - const unsigned triangle_media[2], const unsigned merge_media[2], - void* context), - void* context); - -/* Returns a descriptor of the scene that holds the analysis' result. */ -SENC_API res_T -senc_scene_analyze - (struct senc_scene* scene, - struct senc_descriptor** descriptor); + /* User function that provides coordinates for vertices */ + void(*get_position)(const unsigned ivert, double pos[3], void* context), + /* Context provided to user callbacks; can be NULL */ + void* context, + /* The created scene */ + struct senc_scene** scene); /* Returns the convention flags in use with the scene. */ SENC_API res_T @@ -246,33 +190,16 @@ senc_scene_get_triangles_count (const struct senc_scene* scene, unsigned* count); -/* Returns the number of unique triangles in the scene (remaining - * triangles after deduplication). */ -SENC_API res_T -senc_scene_get_unique_triangles_count - (const struct senc_scene* scene, - unsigned* count); - -/* Returns the number of unique sides with SENC_UNDEFINED_MEDIUM medium. */ +/* Returns the itri_th triangle vertices' indices. */ 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 +senc_scene_get_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. */ +/* Returns the media for the itri_th triangle. */ SENC_API res_T -senc_scene_get_unique_triangle_media +senc_scene_get_triangle_media (const struct senc_scene* scene, const unsigned itri, unsigned media[2]); @@ -283,145 +210,81 @@ senc_scene_get_vertices_count (const struct senc_scene* scene, unsigned* count); -/* Returns the number of unique vertices in the scene (remaining - * vertices after deduplication). */ -SENC_API res_T -senc_scene_get_unique_vertices_count - (const struct senc_scene* scene, - unsigned* count); - -/* Returns the coordinates of the ivert_th unique vertex. - * Can be called anytime, before or after a call to analyze. */ +/* Returns the coordinates of the ivert_th vertex. */ SENC_API res_T -senc_scene_get_unique_vertex +senc_scene_get_vertex (const struct senc_scene* scene, const unsigned ivert, double coord[3]); -SENC_API res_T -senc_scene_ref_get - (struct senc_scene* scene); - -SENC_API res_T -senc_scene_ref_put - (struct senc_scene* scene); - -/******************************************************************************* - * StarEnclosures descriptor. It is an handle toward an analyze result. - ******************************************************************************/ /* Returns the greater medium id found in added geometry. In API calls using a * medium, any value in the [0 max_medium_id[ range is valid. However there can * be unused ids (no geometry refered to this medium id). */ SENC_API res_T -senc_descriptor_get_max_medium - (const struct senc_descriptor* descriptor, +senc_scene_get_max_medium + (const struct senc_scene* scene, unsigned* max_medium_id); /* Returns the number of enclosures. */ SENC_API res_T -senc_descriptor_get_enclosure_count - (const struct senc_descriptor* descriptor, +senc_scene_get_enclosure_count + (const struct senc_scene* scene, unsigned* count); /* Returns the number of enclosures that have some geometry refering to the * imed_th medium. */ SENC_API res_T -senc_descriptor_get_enclosure_count_by_medium - (const struct senc_descriptor* descriptor, +senc_scene_get_enclosure_count_by_medium + (const struct senc_scene* scene, const unsigned imed, unsigned* count); /* Returns the idx_th enclosure. */ SENC_API res_T -senc_descriptor_get_enclosure - (struct senc_descriptor* descriptor, +senc_scene_get_enclosure + (struct senc_scene* scene, const unsigned idx, struct senc_enclosure** enclosure); /* Returns the idx_th enclosure using the imed_th medium. */ SENC_API res_T -senc_descriptor_get_enclosure_by_medium - (struct senc_descriptor* descriptor, +senc_scene_get_enclosure_by_medium + (struct senc_scene* scene, const unsigned imed, const unsigned idx, struct senc_enclosure** enclosure); -/* Returns the number of unique triangles (no duplicates here) in the whole - * geometry. */ -SENC_API res_T -senc_descriptor_get_global_triangles_count - (const struct senc_descriptor* descriptor, - unsigned* count); - -/* Returns the number of unique vertices (no duplicates here) in the whole - * geometry. */ -SENC_API res_T -senc_descriptor_get_global_vertices_count - (const struct senc_descriptor* descriptor, - unsigned* count); /* Number of unique vertices. */ - -/* Returns the itri_th global unique triangles; the returned indices are global - * unique vertex indices. */ -SENC_API res_T -senc_descriptor_get_global_triangle - (const struct senc_descriptor* descriptor, - const unsigned itri, - unsigned indices[3]); - -/* Returns the coordinates of the ivert_th global unique vertex. */ -SENC_API res_T -senc_descriptor_get_global_vertex - (const struct senc_descriptor* descriptor, - const unsigned ivert, - double coord[3]); - -/* Returns the front and back media ids of the itri_th global unique - * triangles. */ -SENC_API res_T -senc_descriptor_get_global_triangle_media - (const struct senc_descriptor* descriptor, - const unsigned itri, - unsigned media[2]); - -/* Returns the enclosures the itri_th global unique triangles front and back - * sides are member of. */ +/* Returns the enclosures the itri_th triangle front and back sides are member + * of. */ SENC_API res_T -senc_descriptor_get_global_triangle_enclosures - (const struct senc_descriptor* descriptor, +senc_scene_get_triangle_enclosures + (const struct senc_scene* scene, const unsigned itri, unsigned enclosures[2]); -/* Returns the global id of the itri_th global unique triangle, that is the - * triangle index in user world regardless of deduplication. */ -SENC_API res_T -senc_descriptor_get_global_triangle_global_id - (const struct senc_descriptor* descriptor, - const unsigned itri, - unsigned* gid); - /* Returns the number of segments that are frontier segments: * - that have arity 1 (single triangle using the segment) * - that connect 2 different media */ SENC_API res_T -senc_descriptor_get_frontier_segments_count - (const struct senc_descriptor* descriptor, +senc_scene_get_frontier_segments_count + (const struct senc_scene* scene, unsigned* count); /* Returns the iseg_th frontier segment; the returned indices are global unique * vertex indices. */ SENC_API res_T -senc_descriptor_get_frontier_segment - (const struct senc_descriptor* descriptor, +senc_scene_get_frontier_segment + (const struct senc_scene* scene, const unsigned iseg, unsigned vrtx_id[2]); SENC_API res_T -senc_descriptor_ref_get - (struct senc_descriptor* descriptor); +senc_scene_ref_get + (struct senc_scene* scene); SENC_API res_T -senc_descriptor_ref_put - (struct senc_descriptor* descriptor); +senc_scene_ref_put + (struct senc_scene* scene); /******************************************************************************* * StarEnclosures enclosure. It is an handle toward an enclosure. diff --git a/src/senc_descriptor.c b/src/senc_descriptor.c @@ -13,8 +13,6 @@ * 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_descriptor_c.h" -#include "senc_device_c.h" #include "senc_enclosure_c.h" #include "senc_scene_c.h" #include "senc.h" @@ -23,108 +21,47 @@ #include <rsys/double3.h> #include <rsys/mem_allocator.h> - /******************************************************************************* - * Helper function - ******************************************************************************/ -static void -descriptor_release(ref_T * ref) -{ - struct senc_scene* scn = NULL; - struct senc_descriptor* desc = NULL; - ASSERT(ref); - desc = CONTAINER_OF(ref, struct senc_descriptor, ref); - scn = desc->scene; - darray_triangle_enc_release(&desc->triangles_enc); - darray_enclosure_release(&desc->enclosures); - darray_enc_ids_array_release(&desc->enc_ids_array_by_medium); - darray_frontier_edge_release(&desc->frontiers); - - MEM_RM(scn->dev->allocator, desc); - SENC(scene_ref_put(scn)); -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -struct senc_descriptor* -descriptor_create(struct senc_scene* scn) -{ - struct senc_descriptor* desc; - res_T res = RES_OK; - ASSERT(scn); - desc = MEM_CALLOC(scn->dev->allocator, 1, sizeof(struct senc_descriptor)); - if(desc) { - desc->scene = scn; - SENC(scene_ref_get(desc->scene)); - ref_init(&desc->ref); - darray_triangle_enc_init(scn->dev->allocator, &desc->triangles_enc); - 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, - 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)); - desc->enclosures_count = 1; - desc->triangle_count = scn->nutris; - desc->vertices_count = scn->nuverts; - } -end: - return desc; -error: - if(desc) SENC(descriptor_ref_put(desc)); - goto end; -} - -struct mem_allocator* - descriptor_get_allocator(struct senc_descriptor* desc) -{ - ASSERT(desc); - return desc->scene->dev->allocator; -} - /******************************************************************************* * Exported functions ******************************************************************************/ res_T -senc_descriptor_get_max_medium - (const struct senc_descriptor* desc, unsigned* max_medium_id) +senc_scene_get_max_medium + (const struct senc_scene* scn, unsigned* max_medium_id) { - if(!desc || !max_medium_id) return RES_BAD_ARG; - ASSERT(desc->scene->next_medium_idx < UINT_MAX); /* API type */ - *max_medium_id = (unsigned)desc->scene->next_medium_idx - 1; + if(!scn || !max_medium_id) return RES_BAD_ARG; + ASSERT(scn->next_medium_idx < UINT_MAX); /* API type */ + *max_medium_id = (unsigned)scn->next_medium_idx - 1; return RES_OK; } res_T -senc_descriptor_get_enclosure_count - (const struct senc_descriptor* desc, unsigned* count) +senc_scene_get_enclosure_count + (const struct senc_scene* scn, unsigned* count) { size_t tmp; - if(!desc || !count) return RES_BAD_ARG; - tmp = darray_enclosure_size_get(&desc->enclosures); + if(!scn || !count) return RES_BAD_ARG; + tmp = darray_enclosure_size_get(&scn->analyze.enclosures); ASSERT(tmp < UINT_MAX); /* API type */ - ASSERT(desc->enclosures_count == tmp); + ASSERT(scn->analyze.enclosures_count == tmp); *count = (unsigned)tmp; return RES_OK; } res_T -senc_descriptor_get_enclosure_count_by_medium - (const struct senc_descriptor* desc, +senc_scene_get_enclosure_count_by_medium + (const struct senc_scene* scn, const unsigned imed, unsigned* count) { size_t tmp, m_idx; const struct darray_enc_id* enc_ids; - if(!desc || !count - || (imed != SENC_UNDEFINED_MEDIUM && imed >= desc->scene->next_medium_idx)) + if(!scn || !count + || (imed != SENC_UNDEFINED_MEDIUM && imed >= scn->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) + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == 1 + scn->next_medium_idx); + m_idx = (imed == SENC_UNDEFINED_MEDIUM) ? scn->next_medium_idx : imed; + enc_ids = darray_enc_ids_array_cdata_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; tmp = darray_enc_id_size_get(enc_ids); ASSERT(tmp < UINT_MAX); /* API type */ @@ -133,23 +70,24 @@ senc_descriptor_get_enclosure_count_by_medium } FINLINE res_T -senc_descriptor_get_enclosure - (struct senc_descriptor* desc, +senc_scene_get_enclosure + (struct senc_scene* scn, const unsigned idx, struct senc_enclosure** out_enc) { struct senc_enclosure* enc; - if(!desc || idx >= darray_enclosure_size_get(&desc->enclosures) || !out_enc) + if(!scn || idx >= darray_enclosure_size_get(&scn->analyze.enclosures) + || !out_enc) return RES_BAD_ARG; - enc = enclosure_create(desc, idx); + enc = enclosure_create(scn, idx); if(!enc) return RES_MEM_ERR; *out_enc = enc; return RES_OK; } res_T -senc_descriptor_get_enclosure_by_medium - (struct senc_descriptor* desc, +senc_scene_get_enclosure_by_medium + (struct senc_scene* scn, const unsigned imed, const unsigned idx, struct senc_enclosure** out_enc) @@ -157,111 +95,31 @@ senc_descriptor_get_enclosure_by_medium size_t m_idx; const struct darray_enc_id* enc_ids; unsigned index; - if(!desc || !out_enc - || (imed != SENC_UNDEFINED_MEDIUM && imed >= desc->scene->next_medium_idx)) + if(!scn || !out_enc + || (imed != SENC_UNDEFINED_MEDIUM && imed >= scn->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; + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.enc_ids_array_by_medium) + == 1 + scn->next_medium_idx); + m_idx = (imed == SENC_UNDEFINED_MEDIUM) ? scn->next_medium_idx : imed; enc_ids = - darray_enc_ids_array_cdata_get(&desc->enc_ids_array_by_medium) + m_idx; + darray_enc_ids_array_cdata_get(&scn->analyze.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); -} - -res_T -senc_descriptor_get_global_triangles_count - (const struct senc_descriptor* desc, - unsigned* count) -{ - if(!desc || !count) return RES_BAD_ARG; - ASSERT(desc->triangle_count < UINT_MAX); - *count = (unsigned)desc->triangle_count; /* Back to API type */ - return RES_OK; + return senc_scene_get_enclosure(scn, index, out_enc); } res_T -senc_descriptor_get_global_vertices_count - (const struct senc_descriptor* desc, - unsigned* count) -{ - if(!desc || !count) return RES_BAD_ARG; - if(desc->vertices_count >= UINT_MAX) - return RES_BAD_ARG; - *count = (unsigned)desc->vertices_count; /* Back to API type */ - return RES_OK; -} - -res_T -senc_descriptor_get_global_triangle - (const struct senc_descriptor* desc, - const unsigned itri, - unsigned indices[3]) -{ - const struct triangle_in* trg; - int i; - if(!indices || ! 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; - - 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_descriptor_get_global_vertex - (const struct senc_descriptor* desc, - const unsigned ivert, - double vrtx[3]) -{ - const union double3* v; - if(!vrtx || !desc - || ivert >= darray_position_size_get(&desc->scene->vertices)) - return RES_BAD_ARG; - - v = darray_position_cdata_get(&desc->scene->vertices) + ivert; - d3_set(vrtx, v->vec); - return RES_OK; -} - -res_T -senc_descriptor_get_global_triangle_media - (const struct senc_descriptor* desc, - const unsigned itri, - unsigned media[2]) -{ - const struct triangle_in* trg; - int i; - if(!media || !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; - FOR_EACH(i, 0, 2) { -#if (UINT_MAX < MEDIUM_MAX__) - ASSERT(trg->medium[i] < UINT_MAX); -#endif - media[i] = (unsigned)trg->medium[i]; /* Back to API type */ - } - return RES_OK; -} - -res_T -senc_descriptor_get_global_triangle_enclosures - (const struct senc_descriptor* desc, +senc_scene_get_triangle_enclosures + (const struct senc_scene* scn, const unsigned itri, unsigned enclosures[2]) { const struct triangle_enc* trg; int i; - if(!enclosures || !desc - || itri >= darray_triangle_enc_size_get(&desc->triangles_enc)) + if(!enclosures || !scn + || itri >= darray_triangle_enc_size_get(&scn->analyze.triangles_enc)) return RES_BAD_ARG; - trg = darray_triangle_enc_cdata_get(&desc->triangles_enc) + itri; + trg = darray_triangle_enc_cdata_get(&scn->analyze.triangles_enc) + itri; FOR_EACH(i, 0, 2) { #if (UINT_MAX < ENCLOSURE_MAX__) ASSERT(trg->enclosure[i] < UINT_MAX); @@ -272,62 +130,31 @@ 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, +senc_scene_get_frontier_segments_count + (const struct senc_scene* scn, unsigned* count) { size_t tmp; - if(!desc || !count) + if(!scn || !count) return RES_BAD_ARG; - tmp = darray_frontier_edge_size_get(&desc->frontiers); + tmp = darray_frontier_edge_size_get(&scn->analyze.frontiers); ASSERT(tmp < UINT_MAX); *count = (unsigned)tmp; return RES_OK; } res_T -senc_descriptor_get_frontier_segment - (const struct senc_descriptor* desc, +senc_scene_get_frontier_segment + (const struct senc_scene* scn, const unsigned iseg, unsigned vrtx_id[2]) { const struct trg_edge* edge; - if(!vrtx_id || !desc - || iseg >= darray_frontier_edge_size_get(&desc->frontiers)) + if(!vrtx_id || !scn + || iseg >= darray_frontier_edge_size_get(&scn->analyze.frontiers)) return RES_BAD_ARG; - edge = darray_frontier_edge_cdata_get(&desc->frontiers) + iseg; + edge = darray_frontier_edge_cdata_get(&scn->analyze.frontiers) + iseg; vrtx_id[0] = (unsigned)edge->vrtx0; /* Back to API type */ vrtx_id[1] = (unsigned)edge->vrtx1; /* Back to API type */ return RES_OK; } - -res_T -senc_descriptor_ref_get(struct senc_descriptor* desc) -{ - if(!desc) return RES_BAD_ARG; - ref_get(&desc->ref); - return RES_OK; -} - -res_T -senc_descriptor_ref_put(struct senc_descriptor* desc) -{ - if(!desc) return RES_BAD_ARG; - ref_put(&desc->ref, descriptor_release); - return RES_OK; -} diff --git a/src/senc_descriptor_c.h b/src/senc_descriptor_c.h @@ -16,153 +16,6 @@ #ifndef SENC_DESCRIPTOR_C_H #define SENC_DESCRIPTOR_C_H -#include <rsys/ref_count.h> -#include <rsys/dynamic_array.h> -#include "senc.h" -#include "senc_enclosure_data.h" -#include "senc_internal_types.h" - -struct senc_scene; -struct mem_allocator; - -struct triangle_comp { - /* The connex component in which each side is. */ - component_id_t component[2]; -}; - -static void -triangle_comp_init(struct mem_allocator* alloc, struct triangle_comp* trg) { - int i; - (void)alloc; - ASSERT(trg); - FOR_EACH(i, 0, 2) trg->component[i] = COMPONENT_NULL__; -} - -#define DARRAY_NAME triangle_comp -#define DARRAY_DATA struct triangle_comp -#define DARRAY_FUNCTOR_INIT triangle_comp_init -#include <rsys/dynamic_array.h> - -struct triangle_enc { - /* The enclosure in which each side is. */ - enclosure_id_t enclosure[2]; -}; - -#ifndef NDEBUG -static void -triangle_enc_init(struct mem_allocator* alloc, struct triangle_enc* trg) { - int i; - (void)alloc; - ASSERT(trg); - FOR_EACH(i, 0, 2) trg->enclosure[i] = ENCLOSURE_NULL__; -} -#define DARRAY_FUNCTOR_INIT triangle_enc_init -#endif - -#define DARRAY_NAME triangle_enc -#define DARRAY_DATA struct triangle_enc -#include <rsys/dynamic_array.h> - -#define DARRAY_NAME enclosure -#define DARRAY_DATA struct enclosure_data -#define DARRAY_FUNCTOR_INIT enclosure_data_init -#define DARRAY_FUNCTOR_COPY enclosure_data_copy -#define DARRAY_FUNCTOR_RELEASE enclosure_data_release -#define DARRAY_FUNCTOR_COPY_AND_RELEASE enclosure_data_copy_and_release -#include <rsys/dynamic_array.h> - -#define DARRAY_NAME enc_id -#define DARRAY_DATA enclosure_id_t -#include <rsys/dynamic_array.h> - -#define DARRAY_NAME enc_ids_array -#define DARRAY_DATA struct darray_enc_id -#define DARRAY_FUNCTOR_INIT darray_enc_id_init -#define DARRAY_FUNCTOR_COPY darray_enc_id_copy -#define DARRAY_FUNCTOR_RELEASE darray_enc_id_release -#define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_enc_id_copy_and_release -#include <rsys/dynamic_array.h> - -/* Triangle edge struct and basic functions */ -struct trg_edge { - vrtx_id_t vrtx0, vrtx1; -}; - -static FINLINE int -edge_ok(const struct trg_edge* edge) { - return(edge - && edge->vrtx0 <= VRTX_MAX__ - && edge->vrtx1 <= VRTX_MAX__ - && edge->vrtx0 < edge->vrtx1); -} - -static FINLINE void -set_edge -(const vrtx_id_t vrtx0, - const vrtx_id_t vrtx1, - struct trg_edge* edge, - unsigned char* reversed) -{ - ASSERT(edge && reversed && vrtx0 != vrtx1); - ASSERT(*reversed == UCHAR_MAX); /* Should not be already set. */ - if(vrtx0 < vrtx1) { - edge->vrtx0 = vrtx0; - edge->vrtx1 = vrtx1; - *reversed = 0; /* Non reversed edge */ - } else { - edge->vrtx0 = vrtx1; - edge->vrtx1 = vrtx0; - *reversed = 1; /* Reversed edge */ - } - ASSERT(edge_ok(edge)); -} - -static FINLINE int -edge_eq(const struct trg_edge* e1, const struct trg_edge* e2) -{ - ASSERT(edge_ok(e1) && edge_ok(e2)); - return e1->vrtx0 == e2->vrtx0 && e1->vrtx1 == e2->vrtx1; -} - -/* Information kept during the building of side groups. */ -struct trgside { - /* Rank of the trgside facing this trgside through its edges */ - side_id_t facing_side_id[3]; - /* Id of this trgside's medium */ - medium_id_t medium; - - /* Implicit information that we don't need to store: - * - triangle_id - * - side - * This is due to the memory layout of the elt darray: - * front(trg_0), back(trg_0), front(trg_1), back(trg_1), ... */ -}; - -#define DARRAY_NAME frontier_edge -#define DARRAY_DATA struct trg_edge -#include <rsys/dynamic_array.h> - -struct senc_descriptor { - struct senc_scene* scene; - enclosure_id_t enclosures_count; - /* Store by-triangle enclosures */ - struct darray_triangle_enc triangles_enc; - /* Store enclosures */ - struct darray_enclosure enclosures; - struct darray_enc_ids_array enc_ids_array_by_medium; - trg_id_t triangle_count; - vrtx_id_t vertices_count; - /* Store frontiers */ - struct darray_frontier_edge frontiers; - - ref_T ref; -}; - -struct senc_descriptor* -descriptor_create(struct senc_scene* scn); - -struct mem_allocator* -descriptor_get_allocator(struct senc_descriptor* desc); #endif /* SENC_DESCRIPTOR_C_H */ diff --git a/src/senc_enclosure.c b/src/senc_enclosure.c @@ -14,8 +14,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "senc_enclosure_c.h" -#include "senc_descriptor_c.h" +#include "senc_enclosure_data.h" #include "senc_scene_c.h" +#include "senc_device_c.h" #include "senc.h" #include <rsys/rsys.h> @@ -30,13 +31,12 @@ static void enclosure_release(ref_T * ref) { struct senc_enclosure* enclosure = NULL; - struct senc_descriptor* desc = NULL; + struct senc_scene* scn = NULL; ASSERT(ref); enclosure = CONTAINER_OF(ref, struct senc_enclosure, ref); - desc = enclosure->desc; - - MEM_RM(descriptor_get_allocator(desc), enclosure); - SENC(descriptor_ref_put(desc)); + scn = enclosure->scene; + MEM_RM(scn->dev->allocator, enclosure); + SENC(scene_ref_put(scn)); } /******************************************************************************* @@ -44,20 +44,19 @@ enclosure_release(ref_T * ref) ******************************************************************************/ struct senc_enclosure* enclosure_create - (struct senc_descriptor* desc, + (struct senc_scene* scn, const unsigned idx) { struct senc_enclosure* enc; - ASSERT(desc && idx < darray_enclosure_size_get(&desc->enclosures)); - enc = MEM_CALLOC(descriptor_get_allocator(desc), - 1, sizeof(struct senc_enclosure)); + ASSERT(scn && idx < darray_enclosure_size_get(&scn->analyze.enclosures)); + enc = MEM_CALLOC(scn->dev->allocator, 1, sizeof(struct senc_enclosure)); if(enc) { const struct enclosure_data* data - = darray_enclosure_data_get(&desc->enclosures) + idx; - SENC(descriptor_ref_get(desc)); - enc->desc = desc; + = darray_enclosure_data_get(&scn->analyze.enclosures) + idx; + enc->scene = scn; enc->data = data; ref_init(&enc->ref); + SENC(scene_ref_get(scn)); } return enc; } @@ -109,7 +108,7 @@ senc_enclosure_get_vertex const vrtx_id_t idx = darray_vrtx_id_cdata_get(&enclosure->data->vertices)[ivert]; const union double3* positions - = darray_position_cdata_get(&enclosure->desc->scene->vertices); + = darray_position_cdata_get(&enclosure->scene->vertices); ASSERT(darray_vrtx_id_size_get(&enclosure->data->vertices) == enclosure->data->header.vertices_count); d3_set(coord, positions[idx].vec); diff --git a/src/senc_enclosure_c.h b/src/senc_enclosure_c.h @@ -21,17 +21,17 @@ #include "senc.h" struct enclosure_data; -struct senc_descriptor; +struct senc_scene; struct senc_enclosure { const struct enclosure_data* data; - struct senc_descriptor* desc; + struct senc_scene* scene; ref_T ref; }; struct senc_enclosure* enclosure_create - (struct senc_descriptor* desc, + (struct senc_scene* scene, const unsigned idx); #endif /* SENC_ENCLOSURE_C_H */ diff --git a/src/senc_enclosure_data.h b/src/senc_enclosure_data.h @@ -16,17 +16,27 @@ #ifndef SENC_ENCLOSURE_DATA_H #define SENC_ENCLOSURE_DATA_H +#include "senc.h" +#include "senc_internal_types.h" +#include "senc_side_range.h" + #include <rsys/rsys.h> #include <rsys/ref_count.h> #include <rsys/hash_table.h> #include <rsys/dynamic_array.h> - -#include "senc.h" -#include "senc_scene_c.h" -#include "senc_internal_types.h" +#include <rsys/hash_table.h> #include <limits.h> +#define DARRAY_NAME vrtx_id +#define DARRAY_DATA vrtx_id_t +#include <rsys/dynamic_array.h> + +#define HTABLE_NAME vrtx_id +#define HTABLE_KEY vrtx_id_t +#define HTABLE_DATA vrtx_id_t +#include <rsys/hash_table.h> + struct side_enc { vrtx_id_t vertice_id[3]; side_id_t side_id; @@ -93,23 +103,23 @@ static FINLINE res_T bool_array_of_media_to_darray_media (struct darray_media* dst, const struct darray_uchar* src, - const medium_id_t undef_idx) + const medium_id_t next_medium_idx) { res_T res = RES_OK; - medium_id_t i; + unsigned m_idx; const unsigned char* data; ASSERT(src && dst); data = darray_uchar_cdata_get(src); - ASSERT(undef_idx + 1 == darray_uchar_size_get(src)); - ASSERT(undef_idx < MEDIUM_MAX__); + ASSERT(next_medium_idx + 1 == darray_uchar_size_get(src)); + ASSERT(next_medium_idx < MEDIUM_MAX__); darray_media_clear(dst); if(res != RES_OK) goto error; - 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, &v); + FOR_EACH(m_idx, 0, next_medium_idx + 1) { + medium_id_t medium = m_idx ? (medium_id_t)(m_idx - 1) : SENC_UNDEFINED_MEDIUM; + if(!data[m_idx]) continue; + res = darray_media_push_back(dst, &medium); if(res != RES_OK) goto error; } end: @@ -202,4 +212,24 @@ error: return res; } +#define DARRAY_NAME enclosure +#define DARRAY_DATA struct enclosure_data +#define DARRAY_FUNCTOR_INIT enclosure_data_init +#define DARRAY_FUNCTOR_COPY enclosure_data_copy +#define DARRAY_FUNCTOR_RELEASE enclosure_data_release +#define DARRAY_FUNCTOR_COPY_AND_RELEASE enclosure_data_copy_and_release +#include <rsys/dynamic_array.h> + +#define DARRAY_NAME enc_id +#define DARRAY_DATA enclosure_id_t +#include <rsys/dynamic_array.h> + +#define DARRAY_NAME enc_ids_array +#define DARRAY_DATA struct darray_enc_id +#define DARRAY_FUNCTOR_INIT darray_enc_id_init +#define DARRAY_FUNCTOR_COPY darray_enc_id_copy +#define DARRAY_FUNCTOR_RELEASE darray_enc_id_release +#define DARRAY_FUNCTOR_COPY_AND_RELEASE darray_enc_id_copy_and_release +#include <rsys/dynamic_array.h> + #endif /* SENC_ENCLOSURE_DATA_H */ diff --git a/src/senc_internal_types.h b/src/senc_internal_types.h @@ -16,6 +16,8 @@ #ifndef SENC_INTERNAL_TYPES_H #define SENC_INTERNAL_TYPES_H +#include "senc.h" + #include <rsys/math.h> #include <stdint.h> diff --git a/src/senc_s3d_wrapper.h b/src/senc_s3d_wrapper.h @@ -22,29 +22,29 @@ #include <rsys/float3.h> static FINLINE void -senc_descriptor_get_global_indices__ +senc_scene_get_global_indices__ (const unsigned itri, unsigned indices[3], void* ctx) { - const struct senc_descriptor* descriptor = ctx; + const struct senc_scene* scene = ctx; res_T r; - ASSERT(indices && ctx); - r = senc_descriptor_get_global_triangle(descriptor, itri, indices); + ASSERT(indices && scene); + r = senc_scene_get_triangle(scene, itri, indices); ASSERT(r == RES_OK); (void)r; } static FINLINE void -senc_descriptor_get_global_vertices__ +senc_scene_get_global_vertices__ (const unsigned ivert, float coord[3], void* ctx) { - const struct senc_descriptor* descriptor = ctx; + const struct senc_scene* scene = ctx; double tmp[3]; res_T r; - ASSERT(coord && ctx); - r = senc_descriptor_get_global_vertex(descriptor, ivert, tmp); + ASSERT(coord && scene); + r = senc_scene_get_vertex(scene, ivert, tmp); ASSERT(r == RES_OK); (void)r; f3_set_d3(coord, tmp); } diff --git a/src/senc_scene.c b/src/senc_scene.c @@ -16,6 +16,7 @@ #include "senc.h" #include "senc_device_c.h" #include "senc_scene_c.h" +#include "senc_scene_analyze_c.h" #include <rsys/rsys.h> #include <rsys/double3.h> @@ -36,9 +37,13 @@ scene_release(ref_T * ref) dev = scn->dev; darray_triangle_in_release(&scn->triangles_in); darray_position_release(&scn->vertices); - htable_vrtx_release(&scn->unique_vertices); - htable_trg_release(&scn->unique_triangles); darray_side_range_release(&scn->media_use); + + darray_triangle_enc_release(&scn->analyze.triangles_enc); + darray_enclosure_release(&scn->analyze.enclosures); + darray_enc_ids_array_release(&scn->analyze.enc_ids_array_by_medium); + darray_frontier_edge_release(&scn->analyze.frontiers); + MEM_RM(dev->allocator, scn); SENC(device_ref_put(dev)); } @@ -59,12 +64,23 @@ res_T senc_scene_create (struct senc_device* dev, const int conv, + const unsigned ntris, + void(*indices)(const unsigned, unsigned*, void*), + void(*media)(const unsigned, unsigned*, void*), + const unsigned nverts, + void(*position)(const unsigned, double*, void* ctx), + void* ctx, struct senc_scene** out_scn) { struct senc_scene* scn = NULL; + /* Tables to detect duplicates */ + struct htable_vrtx unique_vertices; + struct htable_trg unique_triangles; + unsigned i; + const struct triangle_in* trg; res_T res = RES_OK; - if(!dev || !out_scn + if(!dev || !out_scn || !indices || !position /* Convention must be set both regarding FRONT/BACK and INSIDE/OUTSIDE */ || !(conv & (SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_BACK)) || !(conv & (SENC_CONVENTION_NORMAL_INSIDE | SENC_CONVENTION_NORMAL_OUTSIDE))) @@ -80,243 +96,132 @@ senc_scene_create SENC(device_ref_get(dev)); scn->dev = dev; scn->convention = conv; - scn->ntris = 0; - scn->nutris = 0; + scn->ntris = ntris; scn->next_medium_idx = 0; - scn->nverts = 0; - scn->nuverts = 0; - scn->sides_with_defined_medium_count = 0; + scn->nverts = nverts; darray_triangle_in_init(dev->allocator, &scn->triangles_in); darray_position_init(dev->allocator, &scn->vertices); - htable_vrtx_init(dev->allocator, &scn->unique_vertices); - htable_trg_init(dev->allocator, &scn->unique_triangles); + htable_vrtx_init(dev->allocator, &unique_vertices); + htable_trg_init(dev->allocator, &unique_triangles); darray_side_range_init(dev->allocator, &scn->media_use); -exit: - if(scn) *out_scn = scn; - return res; -error: - if(scn) { - SENC(scene_ref_put(scn)); - scn = NULL; - } - goto exit; -} + darray_triangle_enc_init(scn->dev->allocator, &scn->analyze.triangles_enc); + darray_enclosure_init(scn->dev->allocator, &scn->analyze.enclosures); + darray_enc_ids_array_init(scn->dev->allocator, + &scn->analyze.enc_ids_array_by_medium); + darray_frontier_edge_init(scn->dev->allocator, &scn->analyze.frontiers); + /* Enclosure 0 is always defined for infinite */ + OK(darray_enclosure_resize(&scn->analyze.enclosures, 1)); + scn->analyze.enclosures_count = 1; -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, unsigned*, void*), - void(*media)(const unsigned, unsigned*, void*), - const unsigned nverts, - 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, - const unsigned*, const unsigned*, void*), - void* ctx) -{ - struct darray_vrtx_id unique_vertice_ids; - unsigned i; - vrtx_id_t actual_nverts = 0; - vrtx_id_t actual_nuverts = 0; - trg_id_t actual_ntris = 0; - trg_id_t actual_nutris = 0; - const struct triangle_in* trg; - res_T res = RES_OK; - - if(!scn - || !indices || !position - || !nverts || ((size_t)scn->nverts + (size_t)nverts) > VRTX_MAX__ - || !ntris || ((size_t)scn->ntris + (size_t)ntris) > TRG_MAX__) + if(!scn || !indices || !position || !nverts || !ntris) return RES_BAD_ARG; - /* Make room for new geometry; suppose no more duplicates. */ - darray_vrtx_id_init(scn->dev->allocator, &unique_vertice_ids); - OK(darray_vrtx_id_reserve(&unique_vertice_ids, nverts)); - OK(darray_position_reserve(&scn->vertices, scn->nuverts + nverts)); - OK(darray_triangle_in_reserve(&scn->triangles_in, scn->nutris + ntris)); - OK(htable_vrtx_reserve(&scn->unique_vertices, scn->nuverts + nverts)); - OK(htable_trg_reserve(&scn->unique_triangles, scn->nutris + ntris)); + OK(darray_position_reserve(&scn->vertices, scn->nverts)); + OK(darray_triangle_in_reserve(&scn->triangles_in, scn->ntris)); + OK(htable_vrtx_reserve(&unique_vertices, scn->nverts)); + OK(htable_trg_reserve(&unique_triangles, scn->ntris)); trg = darray_triangle_in_cdata_get(&scn->triangles_in); - /* Get geometry */ + /* Get vertices */ FOR_EACH(i, 0, nverts) { vrtx_id_t* p_vrtx; union double3 tmp; - vrtx_id_t unique_v; /* API: position needs an unsigned */ position(i, tmp.vec, ctx); - p_vrtx = htable_vrtx_find(&scn->unique_vertices, &tmp); + p_vrtx = htable_vrtx_find(&unique_vertices, &tmp); if(p_vrtx) { /* Duplicate vertex */ - unique_v = *p_vrtx; - } else { - /* New vertex */ - unique_v = scn->nuverts + actual_nuverts; - 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; + log_err(scn->dev, "%s: vertex %u is a duplicate.\n", + FUNC_NAME, i); + res = RES_BAD_ARG; + goto error; } - /* The unique ID for vertex i is unique_v */ - ASSERT(i == darray_vrtx_id_size_get(&unique_vertice_ids)); - OK(darray_vrtx_id_push_back(&unique_vertice_ids, &unique_v)); - ++actual_nverts; + /* New vertex */ + ASSERT(i == htable_vrtx_size_get(&unique_vertices)); + OK(darray_position_push_back(&scn->vertices, &tmp)); + OK(htable_vrtx_set(&unique_vertices, &tmp, &i)); } - + /* Get triangles */ FOR_EACH(i, 0, ntris) { int j; 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; + struct triangle_in tmp; trg_id_t* p_trg; - char reversed; - /* Triangle index in user world regardless of deduplication. */ - tmp.global_id = (unsigned)(scn->ntris + i); indices(i, ind, ctx); /* API: indices need unsigneds */ FOR_EACH(j, 0, 3) { if(ind[j] >= nverts) { + log_err(scn->dev, "%s: triangle %u uses invalid vertex id %u.\n", + FUNC_NAME, i, ind[j]); res = RES_BAD_ARG; goto error; } - ASSERT(ind[j] < darray_vrtx_id_size_get(&unique_vertice_ids)); - /* Find the unique ID for this vertex */ - tmp.vertice_id[j] = darray_vrtx_id_cdata_get(&unique_vertice_ids)[ind[j]]; + ASSERT(ind[j] <= VRTX_MAX__); + tmp.vertice_id[j] = (vrtx_id_t)ind[j]; } if(tmp.vertice_id[0] == tmp.vertice_id[1] || tmp.vertice_id[0] == tmp.vertice_id[2] - || tmp.vertice_id[1] == tmp.vertice_id[2]) { - 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); - 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), - SPLIT3(positions[trg[i].vertice_id[2]].vec)); + || tmp.vertice_id[1] == tmp.vertice_id[2]) + { + log_err(scn->dev, "%s: triangle %u is degenerated.\n", + FUNC_NAME, i); res = RES_BAD_ARG; goto error; } /* Get media */ 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->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]; - } - /* Find duplicate triangles */ - reversed = trg_make_key(&trg_key, tmp.vertice_id); - p_trg = htable_trg_find(&scn->unique_triangles, &trg_key); + trg_make_key(&trg_key, tmp.vertice_id); + p_trg = htable_trg_find(&unique_triangles, &trg_key); if(p_trg) { - /* Duplicate triangle. Need to check duplicate validity */ - union vrtx_id3 utrg_key; - char ureversed = trg_make_key(&utrg_key, trg[*p_trg].vertice_id); - int same = (reversed == ureversed); - const medium_id_t* umed; - ASSERT(trg_key_eq(&trg_key, &utrg_key)); - if(!same) SWAP(unsigned, tmp.medium[0], tmp.medium[1]); - umed = trg[*p_trg].medium; - if(merge_triangle) { - /* Let the client app rule. */ - unsigned smed[2], mmed[2]; - FOR_EACH(j, 0, 2) { - smed[j] = (unsigned)umed[j]; - mmed[j] = (unsigned)tmp.medium[j]; - } - OK(merge_triangle(trg[*p_trg].global_id, i, same, smed, mmed, ctx)); - /* If merge_triangle returns OK its OK even if media are incompatible. */ - } else { - if(!compatible_medium(umed[0], tmp.medium[0]) - || !compatible_medium(umed[1], tmp.medium[1])) - { - res = RES_BAD_ARG; - goto error; - } - } - /* Legit duplicate (or accepted by merge_triangle): replace undef media. */ - 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++; - } - } - } else { - /* New triangle */ - trg_id_t u = scn->nutris + actual_nutris; - if (add_triangle) - OK(add_triangle(tmp.global_id, i, ctx)); - 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++; - } - ASSERT(u == htable_trg_size_get(&scn->unique_triangles)); - OK(htable_trg_set(&scn->unique_triangles, &trg_key, &u)); - ++actual_nutris; + /* Duplicate triangle */ + log_err(scn->dev, "%s: triangle %u is a duplicate.\n", + FUNC_NAME, i); + res = RES_BAD_ARG; + goto error; } - 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) { - 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((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((trg_id_t)u, j)); - ASSERT(media_use->last < 2 * (scn->nutris + actual_nutris + 1)); - ASSERT(media_use->first <= media_use->last); + /* New triangle */ + ASSERT(i == htable_trg_size_get(&unique_triangles)); + OK(htable_trg_set(&unique_triangles, &trg_key, &i)); + FOR_EACH(j, 0, 2) { + struct side_range* media_use; + unsigned m_idx = (med[j] == SENC_UNDEFINED_MEDIUM) ? 0 : med[j] + 1; + tmp.medium[j] = (medium_id_t)med[j]; + if(m_idx >= scn->next_medium_idx) { + scn->next_medium_idx = m_idx; + darray_side_range_resize(&scn->media_use, 1 + m_idx); } + /* media_use 0 is for SENC_UNDEFINED_MEDIUM */ + media_use = darray_side_range_data_get(&scn->media_use) + m_idx; + media_use->first = + MMIN(media_use->first, TRGIDxSIDE_2_TRGSIDE((trg_id_t)i, j)); + ASSERT(media_use->first < 2 * (scn->ntris + 1)); + media_use->last = + MMAX(media_use->last, TRGIDxSIDE_2_TRGSIDE((trg_id_t)i, j)); + ASSERT(media_use->last < 2 * (scn->ntris + 1)); + ASSERT(media_use->first <= media_use->last); } - ++actual_ntris; + OK(darray_triangle_in_push_back(&scn->triangles_in, &tmp)); } + OK(darray_enc_ids_array_resize(&scn->analyze.enc_ids_array_by_medium, + 1 + scn->next_medium_idx)); /* +1 is for undef */ + /* Proceed to the analyze */ + OK(scene_analyze(scn)); + exit: - darray_vrtx_id_release(&unique_vertice_ids); - /* Update sizes */ - scn->nuverts += actual_nuverts; - scn->nverts += actual_nverts; - scn->nutris += actual_nutris; - scn->ntris += actual_ntris; - ASSERT(scn->nuverts == htable_vrtx_size_get(&scn->unique_vertices)); - ASSERT(scn->nutris == htable_trg_size_get(&scn->unique_triangles)); + htable_vrtx_release(&unique_vertices); + htable_trg_release(&unique_triangles); + if(scn) *out_scn = scn; return res; + error: + if(scn) { + SENC(scene_ref_put(scn)); + scn = NULL; + } goto exit; } @@ -328,7 +233,6 @@ senc_scene_get_convention if(!scn || !convention) return RES_BAD_ARG; *convention = scn->convention; return RES_OK; - } res_T @@ -342,28 +246,7 @@ senc_scene_get_triangles_count } res_T -senc_scene_get_unique_triangles_count - (const struct senc_scene* scn, - unsigned* count) -{ - if(!scn || !count) return RES_BAD_ARG; - *count = scn->nutris; - return RES_OK; -} - -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 +senc_scene_get_triangle (const struct senc_scene* scn, const unsigned itri, unsigned indices[3]) @@ -383,7 +266,7 @@ senc_scene_get_unique_triangle } res_T -senc_scene_get_unique_triangle_media +senc_scene_get_triangle_media (const struct senc_scene* scn, const unsigned itri, unsigned media[2]) @@ -413,17 +296,7 @@ senc_scene_get_vertices_count } res_T -senc_scene_get_unique_vertices_count - (const struct senc_scene* scn, - unsigned* count) -{ - if(!scn || !count) return RES_BAD_ARG; - *count = scn->nuverts; - return RES_OK; -} - -res_T -senc_scene_get_unique_vertex +senc_scene_get_vertex (const struct senc_scene* scn, const unsigned ivert, double coord[3]) diff --git a/src/senc_scene_analyze.c b/src/senc_scene_analyze.c @@ -130,7 +130,7 @@ self_hit_filter static void extract_connex_components - (struct senc_descriptor* desc, + (struct senc_scene* scn, struct trgside* trgsides, struct darray_ptr_component_descriptor* connex_components, const struct darray_triangle_tmp* triangles_tmp_array, @@ -143,9 +143,8 @@ extract_connex_components { /* This function is called from an omp parallel block and executed * concurrently. */ - struct senc_scene* scn; struct mem_allocator* alloc; - int64_t mm, undefs; + int64_t m_idx; struct darray_side_id stack; struct darray_side_id ids_of_sides_around_max_z_vertex; const union double3* positions; @@ -159,51 +158,38 @@ extract_connex_components unsigned char* current_media = NULL; size_t sz, ii; - ASSERT(trgsides && desc && connex_components && triangles_tmp_array + ASSERT(scn && trgsides && connex_components && triangles_tmp_array && triangles_comp_array && s3d_view && component_count && p_res); - alloc = descriptor_get_allocator(desc); - scn = desc->scene; + alloc = scn->dev->allocator; positions = darray_position_cdata_get(&scn->vertices); triangles_tmp = darray_triangle_tmp_cdata_get(triangles_tmp_array); triangles_comp = darray_triangle_comp_data_get(triangles_comp_array); darray_side_id_init(alloc, &stack); darray_side_id_init(alloc, &ids_of_sides_around_max_z_vertex); darray_side_id_init(alloc, &current_component); - processed = MEM_CALLOC(alloc, scn->nutris, sizeof(unsigned char)); + processed = MEM_CALLOC(alloc, scn->ntris, sizeof(unsigned char)); if(!processed) { *p_res = RES_MEM_ERR; 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 { trg_id_t t_; + int s; ASSERT(darray_ptr_component_descriptor_size_get(connex_components) == 0); - FOR_EACH(t_, 0, scn->nutris) { + FOR_EACH(t_, 0, scn->ntris) { const struct triangle_in* trg_in = darray_triangle_in_cdata_get(&scn->triangles_in) + t_; const struct side_range* media_use = darray_side_range_cdata_get(&scn->media_use); - FOR_EACH(mm, 0, 2) { - const side_id_t side = TRGIDxSIDE_2_TRGSIDE(t_, 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); + FOR_EACH(s, 0, 2) { + const side_id_t side = TRGIDxSIDE_2_TRGSIDE(t_, s); + medium_id_t medium = trg_in->medium[s]; + m_idx = (medium == SENC_UNDEFINED_MEDIUM) ? 0 : medium + 1; + ASSERT(media_use[m_idx].first <= side && side + <= media_use[m_idx].last); } } } /* Implicit barrier here */ @@ -212,13 +198,12 @@ extract_connex_components /* We loop on sides to build connex components. */ #pragma omp for schedule(dynamic) nowait /* 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 */ + for(m_idx = 0; m_idx < 1 + (int64_t)scn->next_medium_idx; m_idx++) { + const medium_id_t medium = m_idx ? (medium_id_t)(m_idx - 1) : SENC_UNDEFINED_MEDIUM; + /* media_use 0 is for SENC_UNDEFINED_MEDIUM, n+1 is for n */ const struct side_range* media_use = darray_side_range_cdata_get(&scn->media_use) + m_idx; + /* Any not-already-used side is used as a starting point */ side_id_t first_side_not_in_component = media_use->first; double max_nz; side_id_t max_nz_side_id = SIDE_NULL__; @@ -230,19 +215,19 @@ extract_connex_components if(*p_res != RES_OK) continue; if(first_side_not_in_component == SIDE_NULL__) continue; /* Unused medium */ - ASSERT(first_side_not_in_component < 2 * scn->nutris); + ASSERT(first_side_not_in_component < 2 * scn->ntris); ASSERT(darray_side_id_size_get(&stack) == 0); ASSERT(darray_side_id_size_get(&current_component) == 0); for(;;) { /* Process all components for this medium */ const side_id_t start_side_id = get_side_not_in_connex_component - (last_side, trgsides, processed, &first_side_not_in_component, m); + (last_side, trgsides, processed, &first_side_not_in_component, medium); side_id_t crt_side_id = start_side_id; side_id_t last_side_id = start_side_id; vrtx_id_t max_z_vrtx_id = VRTX_NULL__; struct cc_descriptor *cc; double max_z = -DBL_MAX; component_canceled = 0; - ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->nutris); + ASSERT(start_side_id == SIDE_NULL__ || start_side_id < 2 * scn->ntris); darray_side_id_clear(&current_component); if(*p_res != RES_OK) break; @@ -254,16 +239,18 @@ extract_connex_components trg_id_t tid = TRGSIDE_2_TRG(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); + = darray_triangle_in_data_get(&scn->triangles_in)[tid].medium[s]; + ASSERT(side_med == medium); } #endif /* Reuse array if possible, or create a new one */ if(current_media) { - memset(current_media, 0, 1 + scn->next_medium_idx); /* +1 for possible undef */ + /* current_media 0 is for SENC_UNDEFINED_MEDIUM, n+1 is for n */ + memset(current_media, 0, 1 + scn->next_medium_idx); } else { - current_media = MEM_CALLOC(alloc, 1 + scn->next_medium_idx, sizeof(unsigned char)); + current_media = MEM_CALLOC(alloc, 1 + scn->next_medium_idx, + sizeof(*current_media)); if(!current_media) { *p_res = RES_MEM_ERR; continue; @@ -279,7 +266,7 @@ extract_connex_components darray_triangle_in_cdata_get(&scn->triangles_in) + crt_trg_id; unsigned char* trg_used = processed + crt_trg_id; const struct triangle_tmp* const trg_tmp = triangles_tmp + crt_trg_id; - ASSERT(crt_trg_id < scn->nutris); + ASSERT(crt_trg_id < scn->ntris); if(*p_res != RES_OK) break; @@ -331,8 +318,8 @@ extract_connex_components 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 + ? 0 : neighbour->medium + 1; + if(neighbour->medium < medium || (*nbour_used & SIDE_CANCELED_FLAG(nbour_side_id))) { /* 1) Not the same medium. @@ -384,7 +371,7 @@ extract_connex_components if(!cc) *p_res = RES_MEM_ERR; if(*p_res != RES_OK) break; - ASSERT(m == trgsides[start_side_id].medium); + ASSERT(medium == trgsides[start_side_id].medium); ASSERT(max_z_vrtx_id != VRTX_NULL__); cc_descriptor_init(alloc, cc); id = ATOMIC_INCR(component_count) - 1; @@ -411,7 +398,7 @@ extract_connex_components 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); + ASSERT(trgsides[s].medium >= medium); cmp[sid] = cc->cc_id; } @@ -507,16 +494,16 @@ extract_connex_components attribs.get = get_scn_position; /* Put geometry in a 3D view */ - OK(s3d_device_create(desc->scene->dev->logger, alloc, 0, &s3d)); + OK(s3d_device_create(scn->dev->logger, alloc, 0, &s3d)); OK(s3d_scene_create(s3d, &s3d_scn)); OK(s3d_shape_create_mesh(s3d, &s3d_shp)); /* Back to API type for ntris and nverts */ - ASSERT(desc->scene->nutris < UINT_MAX); - ASSERT(desc->scene->nuverts < UINT_MAX); + ASSERT(scn->ntris < UINT_MAX); + ASSERT(scn->nverts < UINT_MAX); OK(s3d_mesh_setup_indexed_vertices(s3d_shp, - (unsigned)desc->scene->nutris, get_scn_indices, - (unsigned)desc->scene->nuverts, &attribs, 1, scn)); + (unsigned)scn->ntris, get_scn_indices, + (unsigned)scn->nverts, &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)); @@ -538,7 +525,7 @@ extract_connex_components component_id_t c; ASSERT(ATOMIC_GET(component_count) == (int)darray_ptr_component_descriptor_size_get(connex_components)); - FOR_EACH(t_, 0, scn->nutris) { + FOR_EACH(t_, 0, scn->ntris) { struct triangle_comp* trg_comp = darray_triangle_comp_data_get(triangles_comp_array) + t_; ASSERT(trg_comp->component[SENC_FRONT] != COMPONENT_NULL__); @@ -549,14 +536,13 @@ extract_connex_components darray_ptr_component_descriptor_data_get(connex_components); ASSERT(components[c] != NULL && components[c]->cc_id == c); } - ASSERT(desc->triangle_count == scn->nutris); } /* Implicit barrier here */ #endif } static void group_connex_components - (struct senc_descriptor* desc, + (struct senc_scene* scn, struct trgside* trgsides, struct darray_triangle_comp* triangles_comp, struct darray_ptr_component_descriptor* connex_components, @@ -575,15 +561,15 @@ group_connex_components int64_t ccc; (void)trgsides; - ASSERT(desc && trgsides && triangles_comp && connex_components + ASSERT(scn && trgsides && triangles_comp && connex_components && s3d_view && next_enclosure_id && res); - ASSERT(desc->enclosures_count == 1); + ASSERT(scn->analyze.enclosures_count == 1); descriptors = darray_ptr_component_descriptor_data_get(connex_components); tmp = darray_ptr_component_descriptor_size_get(connex_components); ASSERT(tmp <= COMPONENT_MAX__); cc_count = (component_id_t)tmp; - positions = darray_position_cdata_get(&desc->scene->vertices); + positions = darray_position_cdata_get(&scn->vertices); /* Cast rays to find links between connex components */ #pragma omp for @@ -601,7 +587,7 @@ group_connex_components if(*res != RES_OK) continue; ASSERT(cc->cc_id == c); ASSERT(cc->cc_group_root == CC_GROUP_ID_NONE); - ASSERT(cc->max_z_vrtx_id < desc->scene->nverts); + ASSERT(cc->max_z_vrtx_id < scn->nverts); max_vrtx = positions[cc->max_z_vrtx_id].vec; if(cc->is_outer_border) { @@ -633,13 +619,13 @@ group_connex_components darray_triangle_comp_cdata_get(triangles_comp) + hit_trg_id; enum senc_side hit_side = ((hit.normal[2] < 0) /* Facing geometrical normal of hit */ - == ((desc->scene->convention & SENC_CONVENTION_NORMAL_FRONT) != 0)) + == ((scn->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 */ ? SENC_BACK : SENC_FRONT; ASSERT(hit.normal[2] != 0); - ASSERT(hit_trg_id < desc->scene->nutris); + ASSERT(hit_trg_id < scn->ntris); /* Not really the root until following links */ cc->cc_group_root = hit_trg_comp->component[hit_side]; @@ -654,13 +640,14 @@ group_connex_components #pragma omp single { res_T tmp_res = RES_OK; - desc->enclosures_count = (enclosure_id_t)ATOMIC_GET(next_enclosure_id); - tmp_res = darray_enclosure_resize(&desc->enclosures, desc->enclosures_count); + scn->analyze.enclosures_count = (enclosure_id_t)ATOMIC_GET(next_enclosure_id); + tmp_res = darray_enclosure_resize(&scn->analyze.enclosures, + scn->analyze.enclosures_count); if(tmp_res != RES_OK) { *res = tmp_res; } else { struct enclosure_data* enclosures - = darray_enclosure_data_get(&desc->enclosures); + = darray_enclosure_data_get(&scn->analyze.enclosures); FOR_EACH(ccc, 0, cc_count) { component_id_t c = (component_id_t)ccc; struct cc_descriptor* const cc = descriptors[c]; @@ -688,7 +675,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->next_medium_idx + 1); + scn->next_medium_idx + 1); if(tmp_res != RES_OK) { *res = tmp_res; break; @@ -731,7 +718,7 @@ collect_and_link_neighbours res_T tmp_res; ASSERT(scn && trgsides && triangles_tmp_array && frontiers && res); - ASSERT((size_t)scn->nuverts + (size_t)scn->nutris + 2 <= EDGE_MAX__); + ASSERT((size_t)scn->nverts + (size_t)scn->ntris + 2 <= EDGE_MAX__); htable_edge_id_init(scn->dev->allocator, &edge_ids); darray_neighbourhood_init(scn->dev->allocator, &neighbourhood_by_edge); @@ -740,18 +727,18 @@ collect_and_link_neighbours triangles_tmp = darray_triangle_tmp_data_get(triangles_tmp_array); vertices = darray_position_cdata_get(&scn->vertices); - ASSERT(scn->nutris == darray_triangle_tmp_size_get(triangles_tmp_array)); + ASSERT(scn->ntris == darray_triangle_tmp_size_get(triangles_tmp_array)); /* Make some room for edges. */ nbedges_guess = 4 + (thread_count == 1 - ? (edge_id_t)(scn->nuverts + scn->nutris) - : (edge_id_t)((scn->nuverts + scn->nutris) / (0.75 * thread_count))); + ? (edge_id_t)(scn->nverts + scn->ntris) + : (edge_id_t)((scn->nverts + scn->ntris) / (0.75 * thread_count))); OK2(darray_neighbourhood_reserve(&neighbourhood_by_edge, nbedges_guess)); OK2(htable_edge_id_reserve(&edge_ids, nbedges_guess)); /* Loop on triangles to register edges. * All threads considering all the edges and processing some */ - FOR_EACH(t, 0, scn->nutris) { + FOR_EACH(t, 0, scn->ntris) { struct trg_edge edge; unsigned char ee; FOR_EACH(ee, 0, 3) { @@ -912,9 +899,8 @@ collect_and_link_neighbours previous = darray_neighbour_cdata_get(neighbour_list) + i - 1; prev_id = previous->trg_id; log_err(scn->dev, - "%s: found 2 overlying triangles (%lu & %lu).\n", FUNC_NAME, - (unsigned long)triangles_in[crt_id].global_id, - (unsigned long)triangles_in[prev_id].global_id); + "%s: found 2 overlying triangles (%u & %u).\n", FUNC_NAME, + (unsigned)crt_id, (unsigned)prev_id); tmp_res = RES_BAD_OP; goto tmp_error; } @@ -945,7 +931,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)crt_id); disc.vrtx0 = v0; disc.vrtx1 = v1; darray_frontier_edge_push_back(frontiers, &disc); @@ -961,7 +947,7 @@ tmp_error: static void build_result - (struct senc_descriptor* desc, + (struct senc_scene* scn, const struct darray_ptr_component_descriptor* connex_components, const struct darray_triangle_comp* triangles_comp_array, struct darray_frontier_edge* frontiers, @@ -978,15 +964,13 @@ build_result struct triangle_enc* triangles_enc; const struct triangle_comp* triangles_comp; struct htable_vrtx_id vtable; - struct senc_scene* scn; int output_normal_in, normals_front, normals_back; int64_t tt; int64_t ee; - ASSERT(desc && connex_components && triangles_comp_array && frontiers && res); + ASSERT(scn && connex_components && triangles_comp_array && frontiers && res); - alloc = descriptor_get_allocator(desc); - scn = desc->scene; + alloc = scn->dev->allocator; output_normal_in = (scn->convention & SENC_CONVENTION_NORMAL_INSIDE) != 0; normals_front = (scn->convention & SENC_CONVENTION_NORMAL_FRONT) != 0; normals_back = (scn->convention & SENC_CONVENTION_NORMAL_BACK) != 0; @@ -996,22 +980,22 @@ build_result ASSERT(darray_ptr_component_descriptor_size_get(connex_components) <= COMPONENT_MAX__); cc_descriptors = darray_ptr_component_descriptor_cdata_get(connex_components); - enclosures = darray_enclosure_data_get(&desc->enclosures); + enclosures = darray_enclosure_data_get(&scn->analyze.enclosures); triangles_in = darray_triangle_in_cdata_get(&scn->triangles_in); triangles_comp = darray_triangle_comp_cdata_get(triangles_comp_array); #pragma omp single { res_T tmp_res = - darray_triangle_enc_resize(&desc->triangles_enc, scn->nutris); + darray_triangle_enc_resize(&scn->analyze.triangles_enc, scn->ntris); if(tmp_res != RES_OK) *res = tmp_res; }/* Implicit barrier here. */ if(*res != RES_OK) return; - triangles_enc = darray_triangle_enc_data_get(&desc->triangles_enc); + triangles_enc = darray_triangle_enc_data_get(&scn->analyze.triangles_enc); /* Build global enclosure information */ #pragma omp for - for(tt = 0; tt < (int64_t)scn->nutris; tt++) { + for(tt = 0; tt < (int64_t)scn->ntris; tt++) { trg_id_t t = (trg_id_t)tt; const component_id_t cf_id = triangles_comp[t].component[SENC_FRONT]; const component_id_t cb_id = triangles_comp[t].component[SENC_BACK]; @@ -1030,9 +1014,9 @@ build_result * openmp block as a given enclosure is processed by a single thread */ htable_vrtx_id_init(alloc, &vtable); - ASSERT(desc->enclosures_count <= ENCLOSURE_MAX__); + ASSERT(scn->analyze.enclosures_count <= ENCLOSURE_MAX__); #pragma omp for schedule(dynamic) nowait - for(ee = 0; ee < (int64_t)desc->enclosures_count; ee++) { + for(ee = 0; ee < (int64_t)scn->analyze.enclosures_count; ee++) { const enclosure_id_t e = (enclosure_id_t)ee; struct enclosure_data* enc = enclosures + e; trg_id_t fst_idx = 0; @@ -1062,18 +1046,17 @@ 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]; - size_t m_idx = (medium == SENC_UNDEFINED_MEDIUM) - ? scn->next_medium_idx : medium; - struct darray_enc_id* enc_ids_by_medium; + medium_id_t medium = darray_media_cdata_get(&enc->enclosed_media)[m]; + unsigned m_idx = (medium == SENC_UNDEFINED_MEDIUM) ? 0 : medium + 1; + struct darray_enc_id* enc_ids_array_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) + ASSERT(darray_enc_ids_array_size_get(&scn->analyze.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; + enc_ids_array_by_medium = + darray_enc_ids_array_data_get(&scn->analyze.enc_ids_array_by_medium) + m_idx; #pragma omp critical { - tmp_res = darray_enc_id_push_back(enc_ids_by_medium, &e); + tmp_res = darray_enc_id_push_back(enc_ids_array_by_medium, &e); } if(tmp_res != RES_OK) { *res = tmp_res; @@ -1089,7 +1072,7 @@ build_result (size_t)(enc->side_count * 0.6))); /* New vertex numbering scheme local to the enclosure */ htable_vrtx_id_clear(&vtable); - ASSERT(scn->nutris == darray_triangle_in_size_get(&scn->triangles_in)); + ASSERT(scn->ntris == darray_triangle_in_size_get(&scn->triangles_in)); /* Put at the end the back-faces of triangles that also have their * front-face in the list. */ for(t = TRGSIDE_2_TRG(enc->side_range.first); @@ -1133,7 +1116,7 @@ build_result int ii = revert_triangle ? 2 - i : i; side_enc->vertice_id[i] = vertice_id[ii]; } - side_enc->side_id = TRGIDxSIDE_2_TRGSIDE(trg_in->global_id, SENC_FRONT); + side_enc->side_id = TRGIDxSIDE_2_TRGSIDE(t, SENC_FRONT); } if(triangles_enc[t].enclosure[SENC_BACK] == e) { /* Back side of the original triangle is member of the enclosure */ @@ -1147,7 +1130,7 @@ build_result int ii = revert_triangle ? 2 - i : i; side_enc->vertice_id[i] = vertice_id[ii]; } - side_enc->side_id = TRGIDxSIDE_2_TRGSIDE(trg_in->global_id, SENC_BACK); + side_enc->side_id = TRGIDxSIDE_2_TRGSIDE(t, SENC_BACK); } if(fst_idx == sgd_idx) break; } @@ -1159,7 +1142,7 @@ build_result htable_vrtx_id_release(&vtable); /* The first thread here copies frontiers into descriptor */ #pragma omp single nowait - darray_frontier_edge_copy_and_clear(&desc->frontiers, frontiers); + darray_frontier_edge_copy_and_clear(&scn->analyze.frontiers, frontiers); /* No barrier here */ } @@ -1167,11 +1150,9 @@ build_result * Exported functions ******************************************************************************/ res_T -senc_scene_analyze - (struct senc_scene* scn, - struct senc_descriptor** out_desc) +scene_analyze + (struct senc_scene* scn) { - struct senc_descriptor* desc = NULL; /* By triangle tmp data */ struct darray_triangle_tmp triangles_tmp; char triangles_tmp_initialized = 0; @@ -1194,24 +1175,18 @@ senc_scene_analyze res_T res = RES_OK; res_T res2 = RES_OK; - if(!scn || !out_desc) return RES_BAD_ARG; - - desc = descriptor_create(scn); - if(!desc) { - res = RES_MEM_ERR; - goto error; - } + if(!scn) return RES_BAD_ARG; - if(!scn->nutris) goto exit; + if(!scn->ntris) goto exit; darray_triangle_tmp_init(scn->dev->allocator, &triangles_tmp); triangles_tmp_initialized = 1; darray_frontier_edge_init(scn->dev->allocator, &frontiers); frontiers_initialized = 1; - OK(darray_triangle_tmp_resize(&triangles_tmp, scn->nutris)); + OK(darray_triangle_tmp_resize(&triangles_tmp, scn->ntris)); trgsides - = MEM_CALLOC(scn->dev->allocator, 2 * scn->nutris, sizeof(struct trgside)); + = MEM_CALLOC(scn->dev->allocator, 2 * scn->ntris, sizeof(struct trgside)); if(!trgsides) { res = RES_MEM_ERR; goto error; @@ -1220,7 +1195,7 @@ senc_scene_analyze else { /* Initialise trgsides to allow assert code */ size_t i; - FOR_EACH(i, 0, 2 * scn->nutris) + FOR_EACH(i, 0, 2 * scn->ntris) init_trgside(scn->dev->allocator, trgsides + i); } #endif @@ -1249,7 +1224,7 @@ senc_scene_analyze 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)); + OK2(darray_triangle_comp_resize(&triangles_comp, scn->ntris)); tmp_error: if(tmp_res != RES_OK) res2 = tmp_res; } @@ -1269,7 +1244,7 @@ senc_scene_analyze } /* Step 2: extract triangle connex components */ - extract_connex_components(desc, trgsides, &connex_components, + extract_connex_components(scn, trgsides, &connex_components, &triangles_tmp, &triangles_comp, &s3d_view, &component_count, &res); /* No barrier at the end of step 2: data used in step 2 cannot be * released / data produced by step 2 cannot be used @@ -1296,7 +1271,7 @@ senc_scene_analyze } /* No barrier here */ /* Step 3: group components */ - group_connex_components(desc, trgsides, &triangles_comp, + group_connex_components(scn, trgsides, &triangles_comp, &connex_components, s3d_view, &next_enclosure_id, &res); /* Barrier at the end of step 3: data used in step 3 can be released / * data produced by step 3 can be used */ @@ -1319,7 +1294,7 @@ senc_scene_analyze } /* No barrier here */ /* Step 4: Build result */ - build_result(desc, &connex_components, &triangles_comp, &frontiers, &res); + build_result(scn, &connex_components, &triangles_comp, &frontiers, &res); /* No barrier at the end of step 4: data used in step 4 cannot be * released / data produced by step 4 cannot be used * until next sync point */ @@ -1364,11 +1339,8 @@ exit: if(frontiers_initialized) darray_frontier_edge_release(&frontiers); if(trgsides) MEM_RM(scn->dev->allocator, trgsides); - if(desc) *out_desc = desc; return res; error: - if(desc) SENC(descriptor_ref_put(desc)); - desc = NULL; goto exit; } diff --git a/src/senc_scene_analyze_c.h b/src/senc_scene_analyze_c.h @@ -16,14 +16,15 @@ #ifndef SENC_SCNENE_ANALYZE_C_H #define SENC_SCNENE_ANALYZE_C_H -#include "senc_scene_c.h" #include "senc_internal_types.h" -#include "senc_descriptor_c.h" +#include "senc.h" #include <rsys/mem_allocator.h> #include <rsys/hash_table.h> #include <rsys/double3.h> +struct senc_scene; + static FINLINE void init_trgside(struct mem_allocator* alloc, struct trgside* data) { @@ -194,4 +195,7 @@ neighbourhood_copy_and_release #define DARRAY_FUNCTOR_COPY_AND_RELEASE neighbourhood_copy_and_release #include <rsys/dynamic_array.h> +extern LOCAL_SYM res_T +scene_analyze(struct senc_scene* scene); + #endif /* SENC_SCNENE_ANALYZE_C_H */ diff --git a/src/senc_scene_c.h b/src/senc_scene_c.h @@ -13,21 +13,118 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef SENC_SCNENE_C_H -#define SENC_SCNENE_C_H +#ifndef SENC_SCENE_C_H +#define SENC_SCENE_C_H #include "senc_internal_types.h" +#include "senc_enclosure_data.h" +#include "senc_side_range.h" +#include "senc.h" #include <rsys/ref_count.h> #include <rsys/dynamic_array.h> #include <rsys/hash_table.h> struct mem_allocator; +struct senc_scene; -#define HTABLE_NAME vrtx_id -#define HTABLE_KEY vrtx_id_t -#define HTABLE_DATA vrtx_id_t -#include <rsys/hash_table.h> +struct triangle_comp { + /* The connex component in which each side is. */ + component_id_t component[2]; +}; + +static void +triangle_comp_init(struct mem_allocator* alloc, struct triangle_comp* trg) { + int i; + (void)alloc; + ASSERT(trg); + FOR_EACH(i, 0, 2) trg->component[i] = COMPONENT_NULL__; +} + +#define DARRAY_NAME triangle_comp +#define DARRAY_DATA struct triangle_comp +#define DARRAY_FUNCTOR_INIT triangle_comp_init +#include <rsys/dynamic_array.h> + +struct triangle_enc { + /* The enclosure in which each side is. */ + enclosure_id_t enclosure[2]; +}; + +#ifndef NDEBUG +static void +triangle_enc_init(struct mem_allocator* alloc, struct triangle_enc* trg) { + int i; + (void)alloc; + ASSERT(trg); + FOR_EACH(i, 0, 2) trg->enclosure[i] = ENCLOSURE_NULL__; +} +#define DARRAY_FUNCTOR_INIT triangle_enc_init +#endif + +#define DARRAY_NAME triangle_enc +#define DARRAY_DATA struct triangle_enc +#include <rsys/dynamic_array.h> + +/* Triangle edge struct and basic functions */ +struct trg_edge { + vrtx_id_t vrtx0, vrtx1; +}; + +static FINLINE int +edge_ok(const struct trg_edge* edge) { + return(edge + && edge->vrtx0 <= VRTX_MAX__ + && edge->vrtx1 <= VRTX_MAX__ + && edge->vrtx0 < edge->vrtx1); +} + +static FINLINE void +set_edge + (const vrtx_id_t vrtx0, + const vrtx_id_t vrtx1, + struct trg_edge* edge, + unsigned char* reversed) +{ + ASSERT(edge && reversed && vrtx0 != vrtx1); + ASSERT(*reversed == UCHAR_MAX); /* Should not be already set. */ + if (vrtx0 < vrtx1) { + edge->vrtx0 = vrtx0; + edge->vrtx1 = vrtx1; + *reversed = 0; /* Non reversed edge */ + } + else { + edge->vrtx0 = vrtx1; + edge->vrtx1 = vrtx0; + *reversed = 1; /* Reversed edge */ + } + ASSERT(edge_ok(edge)); +} + +static FINLINE int +edge_eq(const struct trg_edge* e1, const struct trg_edge* e2) +{ + ASSERT(edge_ok(e1) && edge_ok(e2)); + return e1->vrtx0 == e2->vrtx0 && e1->vrtx1 == e2->vrtx1; +} + +/* Information kept during the building of side groups. */ +struct trgside { + /* Rank of the trgside facing this trgside through its edges */ + side_id_t facing_side_id[3]; + /* Id of this trgside's medium */ + medium_id_t medium; + + /* Implicit information that we don't need to store: + * - triangle_id + * - side + * This is due to the memory layout of the elt darray: + * front(trg_0), back(trg_0), front(trg_1), back(trg_1), ... */ +}; + +#define DARRAY_NAME frontier_edge +#define DARRAY_DATA struct trg_edge +#include <rsys/dynamic_array.h> union double3 { struct { @@ -48,8 +145,6 @@ 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 regardless of deduplication. */ - unsigned global_id; }; static FINLINE void @@ -59,7 +154,6 @@ triangle_in_init(struct mem_allocator* alloc, struct triangle_in* trg) { ASSERT(trg); FOR_EACH(i, 0, 3) trg->vertice_id[i] = VRTX_NULL__; FOR_EACH(i, 0, 2) trg->medium[i] = SENC_UNDEFINED_MEDIUM; - trg->global_id = 0; } #define DARRAY_NAME triangle_in @@ -95,10 +189,6 @@ vrtx_eq(const union double3* v1, const union double3* v2) #define HTABLE_KEY_FUNCTOR_EQ vrtx_eq #include <rsys/hash_table.h> -#define DARRAY_NAME vrtx_id -#define DARRAY_DATA vrtx_id_t -#include <rsys/dynamic_array.h> - union vrtx_id3 { struct { vrtx_id_t v0, v1, v2; @@ -177,51 +267,37 @@ trg_key_eq(const union vrtx_id3* k1, const union vrtx_id3* k2) #define HTABLE_KEY_FUNCTOR_EQ trg_key_eq #include <rsys/hash_table.h> -struct side_range { - side_id_t first, last; +struct descriptor { + enclosure_id_t enclosures_count; + /* Store by-triangle enclosures */ + struct darray_triangle_enc triangles_enc; + /* Store enclosures */ + struct darray_enclosure enclosures; + struct darray_enc_ids_array enc_ids_array_by_medium; + /* Store frontiers */ + struct darray_frontier_edge frontiers; }; -static FINLINE void -side_range_init(struct mem_allocator* alloc, struct side_range* data) -{ - ASSERT(data); - (void)alloc; - data->first = SIDE_NULL__; - data->last = 0; -} -#define DARRAY_NAME side_range -#define DARRAY_DATA struct side_range -#define DARRAY_FUNCTOR_INIT side_range_init -#include <rsys/dynamic_array.h> struct senc_scene { /* Front / Back sides convention */ int convention; - - /* Triangle information as given by user; no duplicates here */ + /* Triangle information as given by user */ struct darray_triangle_in triangles_in; - - /* Vertex information as given by user; no duplicates here */ + /* Vertex information as given by user */ struct darray_position vertices; - - /* Htables used to detect duplicate vertices. - * As we rely on edges (i.e. vertice IDs) to build - * neighbourhoods, we need vertice unicity. */ - /* Keep each unique vertex; no duplicates here. */ - struct htable_vrtx unique_vertices; - - /* Htables used to detect duplicate triangles. */ - /* Keep each unique triangle; no duplicates here. */ - struct htable_trg unique_triangles; /* Keep sizes */ - trg_id_t ntris, nutris; /* Trg count, unique trg count */ - vrtx_id_t nverts, nuverts; /* Vrtx count, unique vrtx count */ + trg_id_t ntris; /* Trg count */ + vrtx_id_t nverts; /* Vrtx count */ medium_id_t next_medium_idx; + /* media_use 0 is for SENC_UNDEFINED_MEDIUM, n+1 is for n */ struct darray_side_range media_use; - side_id_t sides_with_defined_medium_count; + + /* The descriptor of the analyze */ + struct descriptor analyze; ref_T ref; struct senc_device* dev; }; -#endif /* SENC_SCNENE_C_H */ +#endif /* SENC_SCENE_C_H */ diff --git a/src/senc_side_range.h b/src/senc_side_range.h @@ -0,0 +1,44 @@ +/* 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/>. */ + +#ifndef SENC_SIDE_RANGE_H +#define SENC_SIDE_RANGE_H + +#include "senc_internal_types.h" + +#include <rsys/dynamic_array.h> + +struct mem_allocator; + +struct side_range { + side_id_t first, last; +}; + +static FINLINE void +side_range_init(struct mem_allocator* alloc, struct side_range* data) +{ + ASSERT(data); + (void)alloc; + data->first = SIDE_NULL__; + data->last = 0; +} + +#define DARRAY_NAME side_range +#define DARRAY_DATA struct side_range +#define DARRAY_FUNCTOR_INIT side_range_init +#include <rsys/dynamic_array.h> + + +#endif /* SENC_SCENE_C_H */ diff --git a/src/test_senc_add_n_merge.c b/src/test_senc_add_n_merge.c @@ -60,7 +60,7 @@ main(int argc, char** argv) struct mem_allocator allocator; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned i; struct add_geom_ctx add_geom_ctx; unsigned media[12]; diff --git a/src/test_senc_cube_behind_cube.c b/src/test_senc_cube_behind_cube.c @@ -18,99 +18,256 @@ #include <rsys/double3.h> + /* Dump of star-geometry 'cube_behind_cube_2'. */ +static const double cube_behind_cube_2_vertices[48] = +{ + 0.100000, 0.000000, 0.000000, + 1.000000, 0.000000, 0.000000, + 0.000000, 1.000000, 0.000000, + 1.000000, 1.000000, 0.000000, + 0.000000, 0.000000, 1.100000, + 1.000000, 0.000000, 1.000000, + 0.000000, 1.000000, 1.000000, + 1.000000, 1.100000, 1.000000, + -1.500000, -2.000000, 20.000000, + 3.000000, -2.000000, 20.000000, + -2.000000, 3.000000, 20.000000, + 3.000000, 3.000000, 20.000000, + -2.000000, -2.000000, 25.500000, + 3.000000, -2.000000, 25.000000, + -2.000000, 3.000000, 25.000000, + 3.000000, 3.500000, 25.000000 +}; +static const unsigned cube_behind_cube_2_vertices_count = 16; +static const unsigned cube_behind_cube_2_triangles[72] = +{ + 0, 2, 1, + 1, 2, 3, + 0, 4, 2, + 2, 4, 6, + 4, 5, 6, + 6, 5, 7, + 3, 7, 1, + 1, 7, 5, + 2, 6, 3, + 3, 6, 7, + 0, 1, 4, + 4, 1, 5, + 8, 10, 9, + 9, 10, 11, + 8, 12, 10, + 10, 12, 14, + 12, 13, 14, + 14, 13, 15, + 11, 15, 9, + 9, 15, 13, + 10, 14, 11, + 11, 14, 15, + 8, 9, 12, + 12, 9, 13 +}; +static const unsigned cube_behind_cube_2_triangles_count = 24; +static const unsigned cube_behind_cube_2_properties[72] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0 +}; +/* Dump of star-geometry 'cube_behind_cube_3'. */ +static const double cube_behind_cube_3_vertices[72] = +{ + 0.100000, 0.000000, 0.000000, + 1.000000, 0.000000, 0.000000, + 0.000000, 1.000000, 0.000000, + 1.000000, 1.000000, 0.000000, + 0.000000, 0.000000, 1.100000, + 1.000000, 0.000000, 1.000000, + 0.000000, 1.000000, 1.000000, + 1.000000, 1.100000, 1.000000, + -1.500000, -2.000000, 20.000000, + 3.000000, -2.000000, 20.000000, + -2.000000, 3.000000, 20.000000, + 3.000000, 3.000000, 20.000000, + -2.000000, -2.000000, 25.500000, + 3.000000, -2.000000, 25.000000, + -2.000000, 3.000000, 25.000000, + 3.000000, 3.500000, 25.000000, + -2.300000, -3.000000, 30.000000, + 4.000000, -3.000000, 30.000000, + -3.000000, 4.000000, 30.000000, + 4.000000, 4.000000, 30.000000, + -3.000000, -3.000000, 37.700000, + 4.000000, -3.000000, 37.000000, + -3.000000, 4.000000, 37.000000, + 4.000000, 4.700000, 37.000000 +}; +static const unsigned cube_behind_cube_3_vertices_count = 24; +static const unsigned cube_behind_cube_3_triangles[108] = +{ + 0, 2, 1, + 1, 2, 3, + 0, 4, 2, + 2, 4, 6, + 4, 5, 6, + 6, 5, 7, + 3, 7, 1, + 1, 7, 5, + 2, 6, 3, + 3, 6, 7, + 0, 1, 4, + 4, 1, 5, + 8, 10, 9, + 9, 10, 11, + 8, 12, 10, + 10, 12, 14, + 12, 13, 14, + 14, 13, 15, + 11, 15, 9, + 9, 15, 13, + 10, 14, 11, + 11, 14, 15, + 8, 9, 12, + 12, 9, 13, + 16, 18, 17, + 17, 18, 19, + 16, 20, 18, + 18, 20, 22, + 20, 21, 22, + 22, 21, 23, + 19, 23, 17, + 17, 23, 21, + 18, 22, 19, + 19, 22, 23, + 16, 17, 20, + 20, 17, 21 +}; +static const unsigned cube_behind_cube_3_triangles_count = 36; +static const unsigned cube_behind_cube_3_properties[108] = +{ + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0 +}; + int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc_descriptor* desc = NULL; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned i, ecount, maxm; (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); + (NULL, &allocator, 1, 1, &dev) == RES_OK); - /* Create the scene */ + /* Create a scene with the first and second cubes */ + ctx.positions = cube_behind_cube_2_vertices; + ctx.indices = cube_behind_cube_2_triangles; + ctx.properties = cube_behind_cube_2_properties; CHK(senc_scene_create(dev, - SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, &scn) == RES_OK); - - 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 = medium0; - ctx.back_media = medium1; - - /* First cube */ - 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 */ - d3(ctx.offset, -2, -2, 20); - ctx.scale = 5; - - /* Second cube */ - 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); - - CHK(senc_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); + SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, + cube_behind_cube_2_triangles_count, get_indices, get_media_from_properties, + cube_behind_cube_2_vertices_count, get_position, &ctx, &scn) == RES_OK); + + CHK(senc_scene_get_enclosure_count(scn, &ecount) == RES_OK); CHK(ecount == 3); FOR_EACH(i, 0, ecount) { struct senc_enclosure* enclosure; struct senc_enclosure_header header; - CHK(senc_descriptor_get_enclosure(desc, i, &enclosure) == RES_OK); + CHK(senc_scene_get_enclosure(scn, i, &enclosure) == RES_OK); CHK(senc_enclosure_get_header(enclosure, &header) == RES_OK); ASSERT(header.enclosed_media_count == 1); CHK(senc_enclosure_ref_put(enclosure) == RES_OK); } - CHK(senc_descriptor_get_max_medium(desc, &maxm) == RES_OK); + CHK(senc_scene_get_max_medium(scn, &maxm) == RES_OK); CHK(maxm == 1); - check_desc(desc); - - /* Even further in +Z, even bigger */ - d3(ctx.offset, -3, -3, 30); - ctx.scale = 7; - /* Front/back media have been exchanged: external enclosure shows 2 media */ - ctx.front_media = medium1; - ctx.back_media = medium0; - - /* Third cube */ - 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); - if(desc) CHK(senc_descriptor_ref_put(desc) == RES_OK); - desc = NULL; - CHK(senc_scene_analyze(scn, &desc) == RES_OK); + /* Create a scene with the 3 cubes */ + ctx.positions = cube_behind_cube_3_vertices; + ctx.indices = cube_behind_cube_3_triangles; + ctx.properties = cube_behind_cube_3_properties; + CHK(senc_scene_create(dev, + SENC_CONVENTION_NORMAL_FRONT | SENC_CONVENTION_NORMAL_INSIDE, + cube_behind_cube_3_triangles_count, get_indices, get_media_from_properties, + cube_behind_cube_3_vertices_count, get_position, &ctx, &scn) == RES_OK); - CHK(senc_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); + CHK(senc_scene_get_enclosure_count(scn, &ecount) == RES_OK); CHK(ecount == 4); FOR_EACH(i, 0, ecount) { struct senc_enclosure* enclosure; struct senc_enclosure_header header; - CHK(senc_descriptor_get_enclosure(desc, i, &enclosure) == RES_OK); + CHK(senc_scene_get_enclosure(scn, i, &enclosure) == RES_OK); CHK(senc_enclosure_get_header(enclosure, &header) == RES_OK); ASSERT(header.enclosed_media_count == (header.is_infinite ? 2u : 1u)); CHK(senc_enclosure_ref_put(enclosure) == RES_OK); } - CHK(senc_descriptor_get_max_medium(desc, &maxm) == RES_OK); + CHK(senc_scene_get_max_medium(scn, &maxm) == RES_OK); CHK(maxm == 1); - check_desc(desc); CHK(senc_scene_ref_put(scn) == RES_OK); CHK(senc_device_ref_put(dev) == RES_OK); - if(desc) CHK(senc_descriptor_ref_put(desc) == RES_OK); check_memory_allocator(&allocator); mem_shutdown_proxy_allocator(&allocator); diff --git a/src/test_senc_cube_in_cube.c b/src/test_senc_cube_in_cube.c @@ -22,10 +22,10 @@ int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned i, ecount, maxm; (void)argc, (void)argv; diff --git a/src/test_senc_cube_on_cube.c b/src/test_senc_cube_on_cube.c @@ -45,10 +45,10 @@ int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned count, i; (void)argc, (void)argv; @@ -107,10 +107,10 @@ main(int argc, char** argv) CHK(senc_descriptor_get_enclosure_count(desc, &count) == RES_OK); CHK(count == 4); - CHK(senc_descriptor_get_global_vertices_count(desc, &count) == RES_OK); + CHK(senc_descriptor_get_vertices_count(desc, &count) == RES_OK); CHK(count == 20); - CHK(senc_descriptor_get_global_triangles_count(desc, &count) == RES_OK); + CHK(senc_descriptor_get_triangles_count(desc, &count) == RES_OK); CHK(count == 34); CHK(senc_descriptor_get_enclosure_count(desc, &count) == RES_OK); diff --git a/src/test_senc_descriptor.c b/src/test_senc_descriptor.c @@ -25,9 +25,9 @@ main(int argc, char** argv) struct mem_allocator allocator; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_enclosure* enc = NULL; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned count, maxm; unsigned indices[3]; double coord[3]; @@ -115,61 +115,61 @@ main(int argc, char** argv) CHK(senc_descriptor_get_enclosure_by_medium(NULL, 9, 9, NULL) == RES_BAD_ARG); CHK(senc_descriptor_get_enclosure_by_medium(desc, 0, 0, &enc) == RES_OK); - CHK(senc_descriptor_get_global_vertices_count(NULL, &count) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_vertices_count(desc, NULL) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_vertices_count(desc, &count) == RES_OK); + CHK(senc_descriptor_get_vertices_count(NULL, &count) == RES_BAD_ARG); + CHK(senc_descriptor_get_vertices_count(desc, NULL) == RES_BAD_ARG); + CHK(senc_descriptor_get_vertices_count(desc, &count) == RES_OK); CHK(count == nvertices); - CHK(senc_descriptor_get_global_triangles_count(NULL, &count) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangles_count(desc, NULL) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangles_count(desc, &count) == RES_OK); + CHK(senc_descriptor_get_triangles_count(NULL, &count) == RES_BAD_ARG); + CHK(senc_descriptor_get_triangles_count(desc, NULL) == RES_BAD_ARG); + CHK(senc_descriptor_get_triangles_count(desc, &count) == RES_OK); CHK(count == ntriangles); - CHK(senc_descriptor_get_global_triangle(NULL, 0, indices) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle(NULL, ntriangles, indices) + CHK(senc_descriptor_get_triangle(NULL, 0, indices) == RES_BAD_ARG); + CHK(senc_descriptor_get_triangle(NULL, ntriangles, indices) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle(desc, 0, NULL) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle(desc, 0, indices) == RES_OK); + CHK(senc_descriptor_get_triangle(desc, 0, NULL) == RES_BAD_ARG); + CHK(senc_descriptor_get_triangle(desc, 0, indices) == RES_OK); CHK(indices[0] == box_indices[0] && indices[1] == box_indices[1] && indices[2] == box_indices[2]); - CHK(senc_descriptor_get_global_vertex(NULL, 0, coord) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_vertex(NULL, nvertices, coord) + CHK(senc_descriptor_get_vertex(NULL, 0, coord) == RES_BAD_ARG); + CHK(senc_descriptor_get_vertex(NULL, nvertices, coord) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_vertex(desc, 0, NULL) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_vertex(desc, 0, coord) == RES_OK); + CHK(senc_descriptor_get_vertex(desc, 0, NULL) == RES_BAD_ARG); + CHK(senc_descriptor_get_vertex(desc, 0, coord) == RES_OK); CHK(coord[0] == box_vertices[0] && coord[1] == box_vertices[1] && coord[2] == box_vertices[2]); - CHK(senc_descriptor_get_global_triangle_media(NULL, 0, media) + CHK(senc_descriptor_get_triangle_media(NULL, 0, media) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle_media(NULL, nvertices, media) + CHK(senc_descriptor_get_triangle_media(NULL, nvertices, media) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle_media(desc, 0, NULL) + CHK(senc_descriptor_get_triangle_media(desc, 0, NULL) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle_media(desc, 0, media) == RES_OK); + CHK(senc_descriptor_get_triangle_media(desc, 0, media) == RES_OK); CHK(media[0] == ctx.front_media[0] && media[1] == ctx.back_media[1]); - CHK(senc_descriptor_get_global_triangle_enclosures( + CHK(senc_descriptor_get_triangle_enclosures( NULL, 0, enclosures) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle_enclosures( + CHK(senc_descriptor_get_triangle_enclosures( NULL, nvertices, enclosures) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle_enclosures(desc, 0, NULL) + CHK(senc_descriptor_get_triangle_enclosures(desc, 0, NULL) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle_enclosures(desc, 0, enclosures) + CHK(senc_descriptor_get_triangle_enclosures(desc, 0, enclosures) == RES_OK); CHK(enclosures[0] == 0 && enclosures[1] == 1); - CHK(senc_descriptor_get_global_triangle_global_id(NULL, 0, indices) + CHK(senc_descriptor_get_triangle_global_id(NULL, 0, indices) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle_global_id(NULL, nvertices, indices) + CHK(senc_descriptor_get_triangle_global_id(NULL, nvertices, indices) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle_global_id(desc, 0, NULL) + CHK(senc_descriptor_get_triangle_global_id(desc, 0, NULL) == RES_BAD_ARG); - CHK(senc_descriptor_get_global_triangle_global_id(desc, 0, indices) + CHK(senc_descriptor_get_triangle_global_id(desc, 0, indices) == RES_OK); /* No duplicates: user id is unique vertex id */ CHK(indices[0] == 0); @@ -181,11 +181,11 @@ main(int argc, char** argv) 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); + CHK(senc_descriptor_get_vertices_count(desc, &count) == RES_OK); /* Duplicate vertices have been replaced */ CHK(count == nvertices); - CHK(senc_descriptor_get_global_triangles_count(desc, &count) == RES_OK); + CHK(senc_descriptor_get_triangles_count(desc, &count) == RES_OK); /* Duplicate triangles have been replaced */ CHK(count == ntriangles); diff --git a/src/test_senc_enclosure.c b/src/test_senc_enclosure.c @@ -25,7 +25,7 @@ static void test(const int convention) { struct mem_allocator allocator; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; struct senc_enclosure* enclosures[2] = { NULL, NULL }; @@ -40,7 +40,7 @@ test(const int convention) unsigned gid; enum senc_side side; double vrtx[3]; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned i, n, t, ecount; int conv; const int conv_front = (convention & SENC_CONVENTION_NORMAL_FRONT) != 0; diff --git a/src/test_senc_inconsistant_cube.c b/src/test_senc_inconsistant_cube.c @@ -52,14 +52,14 @@ static void test(const int convention) { struct mem_allocator allocator; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; struct senc_enclosure* enclosure; struct senc_enclosure_header header; int conv; int conv_front, conv_in; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned i, e, ecount; CHK(mem_init_proxy_allocator(&allocator, &mem_default_allocator) == RES_OK); diff --git a/src/test_senc_many_enclosures.c b/src/test_senc_many_enclosures.c @@ -24,7 +24,7 @@ struct s3dut_context { struct s3dut_mesh_data data; - struct context ctx; + struct context ctx = CONTEXT_NULL__; }; static void @@ -69,7 +69,7 @@ int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; struct s3dut_mesh* cyl = NULL; @@ -138,9 +138,9 @@ main(int argc, char** argv) /* dump_global(desc, "test_many_enclosures.obj"); */ - CHK(senc_descriptor_get_global_vertices_count(desc, &count) == RES_OK); + CHK(senc_descriptor_get_vertices_count(desc, &count) == RES_OK); CHK(count == NB_CYL * cyl_vrtx_count); - CHK(senc_descriptor_get_global_triangles_count(desc, &count) == RES_OK); + CHK(senc_descriptor_get_triangles_count(desc, &count) == RES_OK); CHK(count == NB_CYL * cyl_trg_count); CHK(senc_descriptor_get_enclosure_count(desc, &count) == RES_OK); diff --git a/src/test_senc_many_triangles.c b/src/test_senc_many_triangles.c @@ -24,7 +24,7 @@ struct s3dut_context { struct s3dut_mesh_data data; - struct context ctx; + struct context ctx = CONTEXT_NULL__; }; static void @@ -69,7 +69,7 @@ int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; struct s3dut_mesh* cyl = NULL; @@ -123,9 +123,9 @@ main(int argc, char** argv) /* dump_global(desc, "test_many_triangles.obj"); */ - CHK(senc_descriptor_get_global_vertices_count(desc, &count) == RES_OK); + CHK(senc_descriptor_get_vertices_count(desc, &count) == RES_OK); CHK(count == NB_CYL * cyl_vrtx_count); - CHK(senc_descriptor_get_global_triangles_count(desc, &count) == RES_OK); + CHK(senc_descriptor_get_triangles_count(desc, &count) == RES_OK); CHK(count == NB_CYL * cyl_trg_count); CHK(senc_descriptor_get_enclosure_count(desc, &count) == RES_OK); diff --git a/src/test_senc_sample_enclosure.c b/src/test_senc_sample_enclosure.c @@ -27,7 +27,7 @@ int main(int argc, char** argv) { struct mem_allocator allocator; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; struct senc_enclosure* enclosure = NULL; @@ -39,7 +39,7 @@ main(int argc, char** argv) struct s3d_primitive prim; struct s3d_vertex_data vrtx_get; struct ssp_rng* rng; - struct context ctx; + struct context ctx = CONTEXT_NULL__; int i; float st[2]; (void)argc, (void)argv; diff --git a/src/test_senc_scene.c b/src/test_senc_scene.c @@ -25,10 +25,10 @@ main(int argc, char** argv) struct mem_allocator allocator; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_enclosure* enc = NULL; struct senc_enclosure_header header; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned medfront[2], medback[2], ind[3]; double vrtx[3]; unsigned count, i, maxm; @@ -67,10 +67,10 @@ main(int argc, char** argv) CHK(senc_scene_get_triangles_count(scn, &count) == RES_OK); CHK(count == 0); - CHK(senc_scene_get_unique_triangles_count(NULL, &count) == RES_BAD_ARG); - CHK(senc_scene_get_unique_triangles_count(scn, NULL) == RES_BAD_ARG); - CHK(senc_scene_get_unique_triangles_count(NULL, NULL) == RES_BAD_ARG); - CHK(senc_scene_get_unique_triangles_count(scn, &count) == RES_OK); + CHK(senc_scene_get_triangles_count(NULL, &count) == RES_BAD_ARG); + CHK(senc_scene_get_triangles_count(scn, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_triangles_count(NULL, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_triangles_count(scn, &count) == RES_OK); CHK(count == 0); CHK(senc_scene_get_vertices_count(NULL, &count) == RES_BAD_ARG); @@ -122,39 +122,39 @@ main(int argc, char** argv) CHK(senc_scene_get_triangles_count(scn, &count) == RES_OK); CHK(count == ntriangles); - CHK(senc_scene_get_unique_triangles_count(scn, &count) == RES_OK); + CHK(senc_scene_get_triangles_count(scn, &count) == RES_OK); CHK(count == ntriangles); CHK(senc_scene_get_vertices_count(scn, &count) == RES_OK); CHK(count == nvertices); 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_get_triangle(NULL, 0, ind) == RES_BAD_ARG); + CHK(senc_scene_get_triangle(scn, UINT_MAX, ind) == RES_BAD_ARG); + CHK(senc_scene_get_triangle(scn, 0, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_triangle(NULL, UINT_MAX, ind) == RES_BAD_ARG); + CHK(senc_scene_get_triangle(NULL, 0, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_triangle(scn, UINT_MAX, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_triangle(NULL, UINT_MAX, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_triangle(scn, 0, ind) == RES_OK); + + CHK(senc_scene_get_triangle_media(NULL, 0, ind) == RES_BAD_ARG); + CHK(senc_scene_get_triangle_media(scn, UINT_MAX, ind) == RES_BAD_ARG); + CHK(senc_scene_get_triangle_media(scn, 0, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_triangle_media(NULL, UINT_MAX, ind) == RES_BAD_ARG); + CHK(senc_scene_get_triangle_media(NULL, 0, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_triangle_media(scn, UINT_MAX, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_triangle_media(NULL, UINT_MAX, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_triangle_media(scn, 0, ind) == RES_OK); + + CHK(senc_scene_get_vertex(NULL, 0, vrtx) == RES_BAD_ARG); + CHK(senc_scene_get_vertex(scn, UINT_MAX, vrtx) == RES_BAD_ARG); + CHK(senc_scene_get_vertex(scn, 0, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_vertex(NULL, UINT_MAX, vrtx) == RES_BAD_ARG); + CHK(senc_scene_get_vertex(NULL, 0, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_vertex(scn, UINT_MAX, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_vertex(NULL, UINT_MAX, NULL) == RES_BAD_ARG); + CHK(senc_scene_get_vertex(scn, 0, vrtx) == RES_OK); CHK(senc_scene_analyze(NULL, NULL) == RES_BAD_ARG); CHK(senc_scene_analyze(scn, NULL) == RES_BAD_ARG); @@ -187,12 +187,12 @@ main(int argc, char** argv) FOR_EACH(i, 0, ntriangles) { unsigned gid; - CHK(senc_descriptor_get_global_triangle_global_id(desc, i, &gid) == RES_OK); + CHK(senc_descriptor_get_triangle_global_id(desc, i, &gid) == RES_OK); /* Check numbering shift */ CHK(gid == (i ? i + 1 : 0)); } - CHK(senc_descriptor_get_global_triangle_media(desc, 0, medback) == RES_OK); + CHK(senc_descriptor_get_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); @@ -234,12 +234,12 @@ main(int argc, char** argv) FOR_EACH(i, 0, ntriangles) { unsigned gid; - CHK(senc_descriptor_get_global_triangle_global_id(desc, i, &gid) == RES_OK); + CHK(senc_descriptor_get_triangle_global_id(desc, i, &gid) == RES_OK); /* Check numbering shift */ CHK(gid == (i ? i + 1 : 0)); } - CHK(senc_descriptor_get_global_triangle_media(desc, 0, medfront) == RES_OK); + CHK(senc_descriptor_get_triangle_media(desc, 0, medfront) == RES_OK); FOR_EACH(i, 0, 2) CHK(medback[i] == medfront[i]); /* Invalid vertex ID */ diff --git a/src/test_senc_undefined_medium.c b/src/test_senc_undefined_medium.c @@ -23,7 +23,7 @@ static void test(const int convention) { struct mem_allocator allocator; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; struct senc_enclosure* enclosure; @@ -31,7 +31,7 @@ test(const int convention) unsigned medium, expected_external_medium, expected_internal_medium; unsigned gid; enum senc_side side; - struct context ctx; + struct context ctx = CONTEXT_NULL__; unsigned i, t, ecount, vcount, tcount, scount; unsigned media[12]; unsigned rev_box_indices[sizeof(box_indices) / sizeof(*box_indices)]; @@ -140,18 +140,18 @@ test(const int convention) /* 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)); + OK(senc_scene_get_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)); + OK(senc_scene_get_triangle(scn, i, ids)); + OK(senc_scene_get_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)); + OK(senc_scene_get_vertex(scn, ids[j], pos)); } } @@ -178,18 +178,18 @@ test(const int convention) /* 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)); + OK(senc_scene_get_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)); + OK(senc_scene_get_triangle(scn, i, ids)); + OK(senc_scene_get_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)); + OK(senc_scene_get_vertex(scn, ids[j], pos)); } } @@ -216,7 +216,7 @@ test(const int convention) /* Scene is still OK and can be analyzed */ OK(senc_scene_analyze(scn, &desc)); - OK(senc_descriptor_get_global_triangles_count(desc, &tcount)); + OK(senc_descriptor_get_triangles_count(desc, &tcount)); CHK(tcount == sizeof(media) / sizeof(*media)); OK(senc_descriptor_get_enclosure_count(desc, &ecount)); diff --git a/src/test_senc_undefined_medium_attr.c b/src/test_senc_undefined_medium_attr.c @@ -85,7 +85,7 @@ merge_trg compat &= (triangle_media[i] == SENC_UNDEFINED_MEDIUM || merge_media[i] == SENC_UNDEFINED_MEDIUM || triangle_media[i] == merge_media[i]); - if (!compat) return RES_BAD_ARG; + if(!compat) return RES_BAD_ARG; merge_ctx = ctx->custom; res = darray_intface_id_resize(&merge_ctx->global_interf_data, global_id + 1); if(res != RES_OK) return res; @@ -110,7 +110,7 @@ static void test(const int convention) { struct mem_allocator allocator; - struct senc_descriptor* desc = NULL; + struct descriptor* desc = NULL; struct senc_device* dev = NULL; struct senc_scene* scn = NULL; struct senc_enclosure* enclosure; @@ -118,7 +118,7 @@ test(const int convention) unsigned medium, expected_external_medium, expected_internal_medium; unsigned gid; enum senc_side side; - struct context ctx; + struct context ctx = CONTEXT_NULL__; 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)]; @@ -238,18 +238,18 @@ test(const int convention) /* 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)); + OK(senc_scene_get_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)); + OK(senc_scene_get_triangle(scn, i, ids)); + OK(senc_scene_get_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)); + OK(senc_scene_get_vertex(scn, ids[j], pos)); } } @@ -276,18 +276,18 @@ test(const int convention) /* 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)); + OK(senc_scene_get_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)); + OK(senc_scene_get_triangle(scn, i, ids)); + OK(senc_scene_get_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)); + OK(senc_scene_get_vertex(scn, ids[j], pos)); } } @@ -314,7 +314,7 @@ test(const int convention) /* Scene is still OK and can be analyzed */ OK(senc_scene_analyze(scn, &desc)); - OK(senc_descriptor_get_global_triangles_count(desc, &tcount)); + OK(senc_descriptor_get_triangles_count(desc, &tcount)); CHK(tcount == sizeof(media) / sizeof(*media)); OK(senc_descriptor_get_enclosure_count(desc, &ecount)); diff --git a/src/test_senc_utils.h b/src/test_senc_utils.h @@ -81,11 +81,15 @@ struct context { const unsigned* indices; const unsigned* front_media; const unsigned* back_media; + const unsigned* properties; void* custom; double offset[3]; double scale; char reverse_vrtx, reverse_med; }; +#define CONTEXT_NULL__ {\ + NULL, NULL, NULL, NULL, NULL, NULL, {0,0,0}, 1, 0, 0\ +} static const unsigned medium0[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned medium1[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; @@ -123,32 +127,41 @@ get_media(const unsigned itri, unsigned medium[2], void* context) medium[ctx->reverse_med ? 0 : 1] = ctx->back_media[itri]; } +static INLINE void +get_media_from_properties(const unsigned itri, unsigned medium[2], void* context) +{ + const struct context* ctx = context; + ASSERT(medium && ctx); + medium[ctx->reverse_med ? 1 : 0] = ctx->properties[3 * itri + 0]; + medium[ctx->reverse_med ? 0 : 1] = ctx->properties[3 * itri + 1]; +} + /******************************************************************************* * Miscellaneous ******************************************************************************/ static INLINE void dump_global - (struct senc_descriptor* desc, + (struct senc_scene* scn, const char* name) { FILE* stream; unsigned triangles_count, vertices_count, i; - ASSERT(desc && name); + ASSERT(scn && name); - CHK(senc_descriptor_get_global_vertices_count(desc, &vertices_count) == RES_OK); - CHK(senc_descriptor_get_global_triangles_count(desc, &triangles_count) == RES_OK); + CHK(senc_scene_get_vertices_count(scn, &vertices_count) == RES_OK); + CHK(senc_scene_get_triangles_count(scn, &triangles_count) == RES_OK); stream = fopen(name, "w"); CHK(stream); FOR_EACH(i, 0, vertices_count) { double tmp[3]; - CHK(senc_descriptor_get_global_vertex(desc, i, tmp) == RES_OK); + CHK(senc_scene_get_vertex(scn, i, tmp) == RES_OK); fprintf(stream, "v %g %g %g\n", SPLIT3(tmp)); } FOR_EACH(i, 0, triangles_count) { unsigned indices[3]; - CHK(senc_descriptor_get_global_triangle(desc, i, indices) == RES_OK); + CHK(senc_scene_get_triangle(scn, i, indices) == RES_OK); fprintf(stream, "f %lu %lu %lu\n", (unsigned long)(1 + indices[0]), (unsigned long)(1 + indices[1]), (unsigned long)(1 + indices[2])); } @@ -157,7 +170,7 @@ dump_global static INLINE void dump_enclosure - (struct senc_descriptor* desc, + (struct senc_scene* scn, const unsigned enc, const char* name) { @@ -166,11 +179,11 @@ dump_enclosure FILE* stream; unsigned count, i; - ASSERT(desc && name); + ASSERT(scn && name); - SENC(descriptor_get_enclosure_count(desc, &count)); + SENC(scene_get_enclosure_count(scn, &count)); ASSERT(enc < count); - CHK(senc_descriptor_get_enclosure(desc, enc, &enclosure) == RES_OK); + CHK(senc_scene_get_enclosure(scn, enc, &enclosure) == RES_OK); CHK(senc_enclosure_get_header(enclosure, &header) == RES_OK); stream = fopen(name, "w"); @@ -204,40 +217,6 @@ check_memory_allocator(struct mem_allocator* allocator) /******************************************************************************* * Check functions ******************************************************************************/ -static INLINE void check_desc(struct senc_descriptor* desc) -{ - unsigned maxm, ecount, i; - size_t e_cpt = 0; - CHK(senc_descriptor_get_max_medium(desc, &maxm) == RES_OK); - CHK(senc_descriptor_get_enclosure_count(desc, &ecount) == RES_OK); - for(i = 0; i <= maxm; i++) { - unsigned j, ecount_bym; - unsigned found = 0; - CHK(senc_descriptor_get_enclosure_count_by_medium(desc, i, &ecount_bym) == RES_OK); - /* Can be 0 if media numbering is not compact */ - FOR_EACH(j, 0, ecount_bym) { - struct senc_enclosure* enc; - struct senc_enclosure_header h; - unsigned k; - int f = 0; - CHK(senc_descriptor_get_enclosure_by_medium(desc, i, j, &enc) == RES_OK); - CHK(senc_enclosure_get_header(enc, &h) == RES_OK); - ASSERT(h.enclosed_media_count); - FOR_EACH(k, 0, h.enclosed_media_count) { - unsigned m; - CHK(senc_enclosure_get_medium(enc, k, &m) == RES_OK); - found += (m == i); - f += (m == i); - } - ASSERT(f == 1); /* Single reference expected */ - CHK(senc_enclosure_ref_put(enc) == RES_OK); - } - ASSERT(found == ecount_bym); /* All the enclosures enclose medim i */ - e_cpt += ecount_bym; - } - ASSERT(e_cpt >= ecount); /* Every enc has been visited at least once */ -} - /* Compare the itri-th triangle of enclosure with a triangle described by trg2 & vertices2 */ static INLINE void cmp_trg