star-geometry-3d

Clean and decorate 3D geometries
git clone git://git.meso-star.fr/star-geometry-3d.git
Log | Files | Refs | README | LICENSE

commit b905addcb8c666b5384ae7a24182affbdacc557c
parent 0966c671e2044a5b6aa3857300ab3bb912a11606
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 12 Dec 2019 16:12:28 +0100

Merge sg3_report in sg3_geometry

Diffstat:
Mcmake/CMakeLists.txt | 12++++--------
Msrc/sg3_geometry.c | 611+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Asrc/sg3_geometry.h | 291++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/sg3_geometry_c.h | 138-------------------------------------------------------------------------------
Dsrc/sg3_report.c | 544-------------------------------------------------------------------------------
Dsrc/sg3_report.h | 266-------------------------------------------------------------------------------
Msrc/star-geometry.h | 210+++++++++++++++++++++++++++++++++++--------------------------------------------
Msrc/test_sg3_geometry.c | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
Asrc/test_sg3_geometry_2.c | 399+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_sg3_report.c | 79++++++-------------------------------------------------------------------------
Dsrc/test_sg3_report_2.c | 412-------------------------------------------------------------------------------
11 files changed, 1406 insertions(+), 1712 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -37,11 +37,10 @@ include(rcmake_runtime) include_directories( ${RSys_INCLUDE_DIR} - ${StarEnc_INCLUDE_DIR} - ${StarSTL_INCLUDE_DIR}) + ${StarEnc_INCLUDE_DIR}) rcmake_append_runtime_dirs(_runtime_dirs - RSys StarEnc StarSTL) + RSys StarEnc) ################################################################################ # Configure and define targets @@ -54,7 +53,6 @@ set(VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) set(SG3_FILES_SRC sg3_device.c sg3_geometry.c - sg3_report.c ) set(SG3_FILES_INC_API @@ -62,9 +60,8 @@ set(SG3_FILES_INC_API set(SG3_FILES_INC sg3_device.h - sg3_geometry_c.h + sg3_geometry.h sg3_misc.h - sg3_report.h ) set(SG3_FILES_DOC COPYING README.md) @@ -121,8 +118,7 @@ if(NOT NO_TEST) new_test(test_sg3_device) new_test(test_sg3_geometry) - new_test(test_sg3_report) - new_test(test_sg3_report_2) + new_test(test_sg3_geometry_2) endif() ################################################################################ diff --git a/src/sg3_geometry.c b/src/sg3_geometry.c @@ -14,9 +14,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "star-geometry.h" -#include "sg3_geometry_c.h" +#include "sg3_geometry.h" #include "sg3_device.h" -#include "sg3_report.h" #include <limits.h> @@ -26,30 +25,17 @@ static void geometry_release(ref_T* ref) { - struct sg3_geometry* geometry; + struct sg3_geometry* geom; ASSERT(ref); - geometry = CONTAINER_OF(ref, struct sg3_geometry, ref); - - v_n_t_ref_put(geometry->v_n_t); - htable_trg_release(&geometry->unique_triangles_ids); - htable_vrtx_release(&geometry->unique_vertices_ids); - if(geometry->report) { - sg3_report_ref_put(geometry->report); - /* Don't reset geometry->report->associated!!! */ - } - MEM_RM(geometry->dev->allocator, geometry); -} + geom = CONTAINER_OF(ref, struct sg3_geometry, ref); -static void -v_n_t_release(ref_T* ref) -{ - struct v_n_t* v_n_t; - ASSERT(ref); - v_n_t = CONTAINER_OF(ref, struct v_n_t, ref); + darray_triangle_release(&geom->unique_triangles); + darray_vertex_release(&geom->unique_vertices); + htable_trg_release(&geom->unique_triangles_ids); + htable_vrtx_release(&geom->unique_vertices_ids); + darray_trg_descriptions_release(&geom->trg_descriptions); - darray_triangle_release(&v_n_t->unique_triangles); - darray_vertex_release(&v_n_t->unique_vertices); - MEM_RM(v_n_t->dev->allocator, v_n_t); + MEM_RM(geom->dev->allocator, geom); } static FINLINE int /* Return 1 if reversed */ @@ -108,57 +94,182 @@ trg_make_key(struct unsigned3* k, const unsigned t[3]) } /******************************************************************************* + * Local functions + ******************************************************************************/ +res_T +geometry_register_triangle + (struct sg3_geometry* geom, + const struct triangle* triangle, + const unsigned triangle_unique_id, + const unsigned set_id, + /* The conflict code as returned by user callback; if no callback provided + * set_id is 0 or 1 according to media equality / SG3_UNDEFINED_PROPERTY */ + const int merge_conflict) +{ + res_T res = RES_OK; + struct trg_descriptions* trg_d; + int i; + char keep_prop_def[SG3_PROP_TYPES_COUNT__]; + + ASSERT(geom && triangle); + + ERR(geometry_enlarge_trg_descriptions(geom, triangle_unique_id + 1)); + trg_d = (darray_trg_descriptions_data_get(&geom->trg_descriptions) + + triangle_unique_id); + /* Record information */ + FOR_EACH(i, 0, SG3_PROP_TYPES_COUNT__) { + struct darray_definition* definitions; + struct definition* defs; + int done = 0; + size_t j; + keep_prop_def[i] = trg_d->property_defined[i]; + if(triangle->properties[i] == SG3_UNDEFINED_PROPERTY) + trg_d->defs_include_undefined = 1; + else trg_d->property_defined[i] = 1; + definitions = trg_d->defs + i; + defs = darray_definition_data_get(definitions); + FOR_EACH(j, 0, darray_definition_size_get(definitions)) { + if(defs[j].property_value == triangle->properties[i]) { + /* This property_value is already registered: no conflict */ + const unsigned* ids = darray_uint_cdata_get(&defs[j].set_ids); + size_t k; + /* Search if property_value already includes set_id */ + FOR_EACH(k, 0, darray_uint_size_get(&defs[j].set_ids)) { + if(ids[k] == set_id) { + /* Same value+set_id was there already */ + done = 1; + break; + } + } + if(!done) { + /* Need to add the set_id for this property_value */ + ERR(darray_uint_push_back(&defs[j].set_ids, &set_id)); + done = 1; + } + break; + } + } + if(!done) { + /* This property_value was not recorded already */ + size_t defs_sz = darray_definition_size_get(definitions); + struct definition* new_def; + ERR(darray_definition_resize(definitions, 1 + defs_sz)); + new_def = darray_definition_data_get(definitions) + defs_sz; + ERR(darray_uint_push_back(&new_def->set_ids, &set_id)); + new_def->property_value = triangle->properties[i]; + if(!trg_d->merge_conflict && merge_conflict) { + /* If more than 1 merge_conflict occur, the first one remains */ + trg_d->merge_conflict = merge_conflict; + geom->merge_conflict_count++; + } + } + } + + if((!keep_prop_def[SG3_FRONT] || !keep_prop_def[SG3_BACK]) + && trg_d->property_defined[SG3_FRONT] && trg_d->property_defined[SG3_BACK]) + { + /* Both sides are now defined */ + ASSERT(geom->trg_with_undef_sides_count > 0); + geom->trg_with_undef_sides_count--; + } + + if(!keep_prop_def[SG3_INTFACE] && trg_d->property_defined[SG3_INTFACE]) { + /* Interface is now defined */ + ASSERT(geom->trg_with_undef_intface_count > 0); + geom->trg_with_undef_intface_count--; + } + +exit: + return res; +error: + goto exit; +} + +static void +dump_partition + (const struct sg3_geometry* geom, + FILE* stream, + const char* group_name, + enum sg3_dump_content partition) +{ + const struct trg_descriptions* trg_descriptions; + const struct triangle* triangles; + size_t sz, i; + ASSERT(geom && stream && group_name); + ASSERT(partition == SG3_MERGE_CONFLICTS + || partition == SG3_PROPERTY_CONFLICTS + || partition == SG3_VALID_TRIANGLE); + trg_descriptions + = darray_trg_descriptions_cdata_get(&geom->trg_descriptions); + sz = darray_trg_descriptions_size_get(&geom->trg_descriptions); + triangles = darray_triangle_cdata_get(&geom->unique_triangles); + fprintf(stream, "g %s\n", group_name); + FOR_EACH(i, 0, sz) { + int dump; + if(partition == SG3_VALID_TRIANGLE) + dump = !(trg_descriptions[i].merge_conflict + || trg_descriptions[i].properties_conflict); + else if(partition == SG3_MERGE_CONFLICTS) + dump = trg_descriptions[i].merge_conflict; + else { + ASSERT(partition == SG3_PROPERTY_CONFLICTS); + dump = trg_descriptions[i].properties_conflict; + } + if(!dump) continue; + fprintf(stream, "f %u %u %u\n", + /* OBJ indexing starts at 1 */ + 1 + triangles[i].vertex_ids[0], + 1 + triangles[i].vertex_ids[1], + 1 + triangles[i].vertex_ids[2]); + } +} +/******************************************************************************* * Exported functions ******************************************************************************/ res_T sg3_geometry_create (struct sg3_device* dev, - struct sg3_report* report, /* Can be NULL */ struct sg3_geometry** out_geometry) { - struct sg3_geometry* geometry = NULL; + struct sg3_geometry* geom = NULL; res_T res = RES_OK; - if(!dev || !out_geometry || (report && report->associated)) { + if(!dev || !out_geometry) { res = RES_BAD_ARG; goto error; } - geometry = MEM_CALLOC(dev->allocator, 1, sizeof(struct sg3_geometry)); - if(!geometry) { + geom = MEM_CALLOC(dev->allocator, 1, sizeof(struct sg3_geometry)); + if(!geom) { log_err(dev, "%s: could not allocate the sg3_geometry.\n", FUNC_NAME); res = RES_MEM_ERR; goto error; } - geometry->dev = dev; - - ERR(v_n_t_create(dev, &geometry->v_n_t)); - htable_trg_init(dev->allocator, &geometry->unique_triangles_ids); - htable_vrtx_init(dev->allocator, &geometry->unique_vertices_ids); - geometry->triangle_count_including_duplicates = 0; - geometry->sides_with_defined_medium_count = 0; - geometry->set_id = 0; - geometry->report = report; - - ref_init(&geometry->ref); - - if(report) { - report->associated = 1; - report->v_n_t = geometry->v_n_t; - sg3_report_ref_get(report); - /* The report has a reference on v_n_t */ - v_n_t_ref_get(geometry->v_n_t); - } + + darray_triangle_init(dev->allocator, &geom->unique_triangles); + darray_vertex_init(dev->allocator, &geom->unique_vertices); + htable_trg_init(dev->allocator, &geom->unique_triangles_ids); + htable_vrtx_init(dev->allocator, &geom->unique_vertices_ids); + darray_trg_descriptions_init(dev->allocator, &geom->trg_descriptions); + geom->triangle_count_including_duplicates = 0; + geom->sides_with_defined_medium_count = 0; + geom->set_id = 0; + geom->trg_with_undef_sides_count = 0; + geom->trg_with_undef_intface_count = 0; + geom->merge_conflict_count = 0; + geom->properties_conflict_count = 0; + geom->dev = dev; + + ref_init(&geom->ref); exit: - if(out_geometry) *out_geometry = geometry; + if(out_geometry) *out_geometry = geom; return res; error: - if(geometry) { - if(geometry->v_n_t) v_n_t_ref_put(geometry->v_n_t); - SG3(geometry_ref_put(geometry)); - geometry = NULL; + if(geom) { + SG3(geometry_ref_put(geom)); + geom = NULL; } goto exit; } @@ -185,7 +296,6 @@ sg3_geometry_add unsigned actual_nutris = 0; unsigned i; struct triangle* trg; - int found_inconsistency = 0; /* Tmp table of IDs to record unique IDs of the currently added vertices */ struct darray_uint unique_vertice_ids; @@ -195,22 +305,18 @@ sg3_geometry_add } alloc = geom->dev->allocator; - nuverts = darray_vertex_size_get(&geom->v_n_t->unique_vertices); - nutris = darray_triangle_size_get(&geom->v_n_t->unique_triangles); + nuverts = darray_vertex_size_get(&geom->unique_vertices); + nutris = darray_triangle_size_get(&geom->unique_triangles); /* Make room for new geometry; suppose no more duplicates */ darray_uint_init(alloc, &unique_vertice_ids); ERR(darray_uint_reserve(&unique_vertice_ids, nverts)); - ERR(darray_vertex_reserve(&geom->v_n_t->unique_vertices, nuverts + nverts)); - ERR(darray_triangle_reserve(&geom->v_n_t->unique_triangles, nutris + ntris)); + ERR(darray_vertex_reserve(&geom->unique_vertices, nuverts + nverts)); + ERR(darray_triangle_reserve(&geom->unique_triangles, nutris + ntris)); ERR(htable_vrtx_reserve(&geom->unique_vertices_ids, nuverts + nverts)); ERR(htable_trg_reserve(&geom->unique_triangles_ids, nutris + ntris)); - if(geom->report) { - ASSERT(nutris - == darray_trg_descriptions_size_get(&geom->report->trg_descriptions)); - ERR(darray_trg_descriptions_reserve(&geom->report->trg_descriptions, - nutris + ntris)); - } + ASSERT(nutris == darray_trg_descriptions_size_get(&geom->trg_descriptions)); + ERR(darray_trg_descriptions_reserve(&geom->trg_descriptions, nutris + ntris)); /* Get vertices and deduplicate */ FOR_EACH(i, 0, nverts) { unsigned* p_vrtx; @@ -226,7 +332,7 @@ sg3_geometry_add ASSERT(nuverts + actual_nuverts < UINT_MAX); unique_v = (unsigned)(nuverts + actual_nuverts); ASSERT(unique_v == htable_vrtx_size_get(&geom->unique_vertices_ids)); - ERR(darray_vertex_push_back(&geom->v_n_t->unique_vertices, &tmp)); + ERR(darray_vertex_push_back(&geom->unique_vertices, &tmp)); ERR(htable_vrtx_set(&geom->unique_vertices_ids, &tmp, &unique_v)); ++actual_nuverts; } @@ -235,15 +341,14 @@ sg3_geometry_add } /* Get triangles and deduplicate */ - trg = darray_triangle_data_get(&geom->v_n_t->unique_triangles); + trg = darray_triangle_data_get(&geom->unique_triangles); FOR_EACH(i, 0, ntris) { int j, reversed; struct unsigned3 trg_key; struct triangle tmp = TRG_UNDEF__; unsigned* p_trg; + struct trg_descriptions* trg_descriptions = NULL; unsigned unique_id; - struct trg_descriptions trgd; - struct trg_descriptions* p_trgd; /* Triangle index in user world regardless of deduplication. */ tmp.global_id = (geom->triangle_count_including_duplicates + i); @@ -279,36 +384,28 @@ sg3_geometry_add int already_conflict; ASSERT(trg_key_eq(&trg_key, &utrg_key)); unique_id = *p_trg; - /* Use report or tmp storage for merge_conflict status */ - if(geom->report) { - struct trg_descriptions* trg_descriptions; - ERR(report_enlarge_trg_descriptions(geom->report, 1 + unique_id)); - trg_descriptions - = darray_trg_descriptions_data_get(&geom->report->trg_descriptions); - p_trgd = trg_descriptions + i; - } - else p_trgd = &trgd; + ERR(geometry_enlarge_trg_descriptions(geom, 1 + unique_id)); + trg_descriptions + = darray_trg_descriptions_data_get(&geom->trg_descriptions); if(!same) SWAP(unsigned, tmp.properties[SG3_FRONT], tmp.properties[SG3_BACK]); - already_conflict = p_trgd->merge_conflict; + already_conflict = trg_descriptions[i].merge_conflict; if(merge_trg) { /* Let the client app rule. */ ERR(merge_trg(trg[*p_trg].global_id, i, same, trg[*p_trg].properties, - tmp.properties, ctx, &p_trgd->merge_conflict)); + tmp.properties, ctx, &trg_descriptions[i].merge_conflict)); } else { FOR_EACH(j, 0, SG3_PROP_TYPES_COUNT__) { if(!sg3_compatible_property(trg[*p_trg].properties[j], tmp.properties[j])) { - p_trgd->merge_conflict = 1; + trg_descriptions[i].merge_conflict = 1; break; } } } - if(p_trgd->merge_conflict && !already_conflict) { - if(geom->report) geom->report->merge_conflict_count++; - found_inconsistency = 1; - } + if(trg_descriptions[i].merge_conflict && !already_conflict) + geom->merge_conflict_count++; /* Replace SG3_UNDEFINED_PROPERTY properties */ FOR_EACH(j, 0, SG3_PROP_TYPES_COUNT__) { if(trg[*p_trg].properties[j] == SG3_UNDEFINED_PROPERTY @@ -324,15 +421,10 @@ sg3_geometry_add unique_id = (unsigned)(nutris + actual_nutris); if(add_trg) ERR(add_trg(tmp.global_id, i, ctx)); - /* Use report or tmp storage for merge_conflict status */ - if(geom->report) { - struct trg_descriptions* trg_descriptions; - ERR(report_enlarge_trg_descriptions(geom->report, 1 + unique_id)); - trg_descriptions - = darray_trg_descriptions_data_get(&geom->report->trg_descriptions); - p_trgd = trg_descriptions + i; - } else p_trgd = &trgd; - ERR(darray_triangle_push_back(&geom->v_n_t->unique_triangles, &tmp)); + ERR(geometry_enlarge_trg_descriptions(geom, 1 + unique_id)); + trg_descriptions + = darray_trg_descriptions_data_get(&geom->trg_descriptions); + ERR(darray_triangle_push_back(&geom->unique_triangles, &tmp)); FOR_EACH(j, 0, SG3_PROP_TYPES_COUNT__) { if((j == SG3_FRONT || j == SG3_BACK) && tmp.properties[j] != SG3_UNDEFINED_PROPERTY) @@ -343,14 +435,10 @@ sg3_geometry_add ++actual_nutris; } ++actual_ntris; - /* Register triangle in report */ - if(geom->report) { - ERR(report_record_triangle(geom->report, &tmp, unique_id, geom->set_id, - p_trgd->properties_conflict)); - if(p_trgd->properties_conflict) { - geom->report->merge_conflict_count++; - } - } + ERR(geometry_register_triangle(geom, &tmp, unique_id, geom->set_id, + trg_descriptions[i].properties_conflict)); + if(trg_descriptions[i].properties_conflict) + geom->merge_conflict_count++; } ASSERT(nuverts + actual_nuverts @@ -362,76 +450,320 @@ exit: darray_uint_release(&unique_vertice_ids); /* Update sizes */ geom->triangle_count_including_duplicates += actual_ntris; - return found_inconsistency ? RES_BAD_ARG : res; + return res; error: goto exit; } res_T -sg3_geometry_ref_get(struct sg3_geometry* geometry) +sg3_geometry_validate_properties + (struct sg3_geometry* geom, + res_T(*validate)(const unsigned, const unsigned*, void*, int*), + void* ctx) { - if(!geometry) return RES_BAD_ARG; - ref_get(&geometry->ref); - return RES_OK; + size_t sz__; + unsigned i, sz; + struct trg_descriptions* trg_descriptions; + res_T res = RES_OK; + + if(!geom || !validate) { + res = RES_BAD_ARG; + goto error; + } + + sz__ = darray_trg_descriptions_size_get(&geom->trg_descriptions); + ASSERT(sz__ <= UINT_MAX); + sz = (unsigned)sz__; + trg_descriptions + = darray_trg_descriptions_data_get(&geom->trg_descriptions); + geom->properties_conflict_count = 0; /* Reset count */ + FOR_EACH(i, 0, sz) { + unsigned props[3] = { + SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY }; + struct trg_descriptions* trgd = trg_descriptions + i; + /* Validate only triangle not flagged with merge_conflict */ + if(trgd->merge_conflict) { + trgd->properties_conflict = 0; + continue; + } + /* Get non-conflicting properties */ + /* Call vaildation */ + ERR(validate(i, props, ctx, &trgd->properties_conflict)); + if(trgd->properties_conflict) + geom->properties_conflict_count++; + } + +exit: + return res; +error: + goto exit; } res_T -sg3_geometry_ref_put(struct sg3_geometry* geometry) +sg3_geometry_get_unique_vertices_count + (const struct sg3_geometry* geom, + unsigned* count) { - if(!geometry) return RES_BAD_ARG; - ref_put(&geometry->ref, geometry_release); - return RES_OK; + res_T res = RES_OK; + size_t sz; + if(!geom || !count) { + res = RES_BAD_ARG; + goto error; + } + sz = darray_vertex_size_get(&geom->unique_vertices); + ASSERT(sz <= UINT_MAX); + *count = (unsigned)sz; +exit: + return res; +error: + goto exit; } -/******************************************************************************* - * Local functions - ******************************************************************************/ res_T -v_n_t_create - (struct sg3_device* dev, - struct v_n_t** out_v_n_t) +sg3_geometry_get_unique_triangles_count + (const struct sg3_geometry* geom, + unsigned* count) +{ + res_T res = RES_OK; + size_t sz; + if(!geom || !count) { + res = RES_BAD_ARG; + goto error; + } + sz = darray_triangle_size_get(&geom->unique_triangles); + ASSERT(sz <= UINT_MAX); + *count = (unsigned)sz; +exit: + return res; +error: + goto exit; +} + +res_T +sg3_geometry_get_triangle_with_undefined_side_count + (const struct sg3_geometry* geom, + unsigned* count) +{ + res_T res = RES_OK; + if(!geom || !count) { + res = RES_BAD_ARG; + goto error; + } + *count = geom->trg_with_undef_sides_count; +exit: + return res; +error: + goto exit; +} + +res_T +sg3_geometry_get_triangle_with_undefined_interface_count + (const struct sg3_geometry* geom, + unsigned* count) { - struct v_n_t* v_n_t = NULL; res_T res = RES_OK; + if(!geom || !count) { + res = RES_BAD_ARG; + goto error; + } + *count = geom->trg_with_undef_intface_count; +exit: + return res; +error: + goto exit; +} - if(!dev || !out_v_n_t) { +res_T +sg3_geometry_get_merge_conflict_count + (const struct sg3_geometry* geom, + unsigned* count) +{ + res_T res = RES_OK; + if(!geom || !count) { res = RES_BAD_ARG; goto error; } + *count = geom->merge_conflict_count; +exit: + return res; +error: + goto exit; +} - v_n_t = MEM_CALLOC(dev->allocator, 1, sizeof(struct v_n_t)); - if(!v_n_t) { - log_err(dev, - "%s: could not allocate the star-geometry v_n_t.\n", FUNC_NAME); - res = RES_MEM_ERR; +res_T +sg3_geometry_get_properties_conflict_count + (const struct sg3_geometry* geom, + unsigned* count) +{ + res_T res = RES_OK; + if(!geom || !count) { + res = RES_BAD_ARG; + goto error; + } + *count = geom->properties_conflict_count; +exit: + return res; +error: + goto exit; +} + +res_T +sg3_geometry_dump_as_obj + (const struct sg3_geometry* geom, + FILE* stream, + int flags) +{ + res_T res = RES_OK; + const struct vertex* vertices; + size_t vsz, tsz, i; + if(!geom || !stream || !flags + || !geom->triangle_count_including_duplicates) + { + if(geom && !geom->triangle_count_including_duplicates) + log_err(geom->dev, + "%s: cannot dump empty geometries as OBJ\n", + FUNC_NAME); + res = RES_BAD_ARG; goto error; } - v_n_t->dev = dev; - darray_triangle_init(dev->allocator, &v_n_t->unique_triangles); - darray_vertex_init(dev->allocator, &v_n_t->unique_vertices); - ref_init(&v_n_t->ref); + /* Headers */ + fprintf(stream, "# Dump of star-geometry\n"); + fprintf(stream, "# Geometry counts:\n"); + vsz = darray_vertex_size_get(&geom->unique_vertices); + ASSERT(vsz <= UINT_MAX); + fprintf(stream, "# . %u vertices\n", (unsigned)vsz); + tsz = darray_triangle_size_get(&geom->unique_triangles); + ASSERT(tsz <= UINT_MAX); + fprintf(stream, "# . %u triangles\n", (unsigned)tsz); + fprintf(stream, + "# . %u triangles flagged with a merge conflict\n", + geom->merge_conflict_count); + fprintf(stream, + "# . %u triangles flagged with a property conflict\n", + geom->merge_conflict_count); + + /* Dump vertices */ + vertices = darray_vertex_cdata_get(&geom->unique_vertices); + FOR_EACH(i, 0, vsz) + fprintf(stream, "v %f %f %f\n", SPLIT3(vertices[i].coord)); + + /* Dump triangles by groups */ + dump_partition(geom, stream, "Valid triangles", SG3_VALID_TRIANGLE); + dump_partition(geom, stream, "Merge conflicts", SG3_MERGE_CONFLICTS); + dump_partition(geom, stream, "Property conflicts", SG3_PROPERTY_CONFLICTS); exit: - if(out_v_n_t) *out_v_n_t = v_n_t; return res; error: - if(v_n_t) { - v_n_t_ref_put(v_n_t); - v_n_t = NULL; + goto exit; +} + +res_T +sg3_geometry_dump_as_C_code + (const struct sg3_geometry* geom, + FILE* stream, + const char* name_prefix) +{ + res_T res = RES_OK; + const struct vertex* vertices; + const struct triangle* triangles; + size_t vsz, tsz, i; + if(!geom || !stream || !name_prefix + || geom->merge_conflict_count + || geom->properties_conflict_count + || !geom->triangle_count_including_duplicates) + { + if(geom + && (geom->merge_conflict_count + || geom->properties_conflict_count)) + log_err(geom->dev, + "%s: cannot dump geometries with conflict as C code\n", + FUNC_NAME); + if(geom && !geom->triangle_count_including_duplicates) + log_err(geom->dev, + "%s: cannot dump empty geometries as C code\n", + FUNC_NAME); + res = RES_BAD_ARG; + goto error; + } + /* Headers */ + fprintf(stream, "/* Dump of star-geometry. */\n"); + vsz = darray_vertex_size_get(&geom->unique_vertices); + ASSERT(vsz <= UINT_MAX); + tsz = darray_triangle_size_get(&geom->unique_triangles); + ASSERT(tsz <= UINT_MAX); + + if(vsz == 0 || tsz == 0) { + log_err(geom->dev, + "%s: no geometry to dump\n", + FUNC_NAME); + res = RES_BAD_ARG; + goto error; } + + /* Dump vertices */ + vertices = darray_vertex_cdata_get(&geom->unique_vertices); + fprintf(stream, + "const double %s_vertices[%u][3] =\n" + " {\n", + name_prefix, (unsigned)vsz); + FOR_EACH(i, 0, vsz - 1) + fprintf(stream, + " { %f, %f, %f },\n", SPLIT3(vertices[i].coord)); + fprintf(stream, + " { %f, %f, %f }\n", SPLIT3(vertices[vsz - 1].coord)); + fprintf(stream, + " }" + "}\n"); + + /* Dump triangles */ + triangles = darray_triangle_cdata_get(&geom->unique_triangles); + fprintf(stream, + "const unsigned %s_triangles[%u][3] =\n" + " {\n", + name_prefix, (unsigned)tsz); + FOR_EACH(i, 0, tsz - 1) + fprintf(stream, + " { %u, %u, %u },\n", SPLIT3(triangles[i].vertex_ids)); + fprintf(stream, + " { %u, %u, %u }\n", SPLIT3(triangles[tsz - 1].vertex_ids)); + fprintf(stream, + " }" + "}\n"); + + /* Dump properties */ + triangles = darray_triangle_cdata_get(&geom->unique_triangles); + fprintf(stream, + "const unsigned %s_properties[%u][3] =\n" + " {\n", + name_prefix, (unsigned)tsz); + FOR_EACH(i, 0, tsz - 1) + fprintf(stream, + " { %u, %u, %u },\n", SPLIT3(triangles[i].properties)); + fprintf(stream, + " { %u, %u, %u }\n", SPLIT3(triangles[tsz - 1].properties)); + fprintf(stream, + " }" + "}\n"); + +exit: + return res; +error: goto exit; } -void -v_n_t_ref_get(struct v_n_t* dev) +res_T +sg3_geometry_ref_get(struct sg3_geometry* geom) { - ASSERT(dev); - ref_get(&dev->ref); + if(!geom) return RES_BAD_ARG; + ref_get(&geom->ref); + return RES_OK; } -void -v_n_t_ref_put(struct v_n_t* dev) +res_T +sg3_geometry_ref_put(struct sg3_geometry* geom) { - ASSERT(dev); - ref_put(&dev->ref, v_n_t_release); -} -\ No newline at end of file + if(!geom) return RES_BAD_ARG; + ref_put(&geom->ref, geometry_release); + return RES_OK; +} diff --git a/src/sg3_geometry.h b/src/sg3_geometry.h @@ -0,0 +1,291 @@ +/* Copyright (C) 2016-2019 |Meso|Star> (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 SG3_GEOMETRY_H__ +#define SG3_GEOMETRY_H__ + +#include "star-geometry.h" +#include "sg3_misc.h" + +#include <rsys/ref_count.h> +#include <rsys/dynamic_array.h> +#include <rsys/hash_table.h> + +/* Forward declaration of external opaque data types */ + +/******************************************************************************* + * A type to store triangles + ******************************************************************************/ +struct triangle { + unsigned vertex_ids[3]; + /* FRONT/BACK/INTERFACE property */ + unsigned properties[SG3_PROP_TYPES_COUNT__]; + /* ID of the triangle in user world, i.e. without deduplication */ + unsigned global_id; +}; +#define TRG_UNDEF__ {\ + { SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY },\ + { SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY },\ + SG3_UNDEFINED_PROPERTY\ +} +#define DARRAY_NAME triangle +#define DARRAY_DATA struct triangle +#include <rsys/dynamic_array.h> + +/******************************************************************************* + * A type to store vertices + ******************************************************************************/ +struct vertex { + double coord[3]; +}; +#define DARRAY_NAME vertex +#define DARRAY_DATA struct vertex +#include <rsys/dynamic_array.h> + +/******************************************************************************* + * A type to map triangle vertices to IDs in unique_triangles + ******************************************************************************/ +struct unsigned3 { unsigned x[3]; }; + +static FINLINE int +trg_key_eq(const struct unsigned3* k1, const struct unsigned3* k2) +{ + ASSERT(k1 && k2); + ASSERT(k1->x[0] < k1->x[1] && k1->x[1] < k1->x[2]); + ASSERT(k2->x[0] < k2->x[1] && k2->x[1] < k2->x[2]); + return (k1->x[0] == k2->x[0]) + && (k1->x[1] == k2->x[1]) + && (k1->x[2] == k2->x[2]); +} + +#define HTABLE_NAME trg +#define HTABLE_KEY struct unsigned3 +#define HTABLE_DATA unsigned +#define HTABLE_KEY_FUNCTOR_EQ trg_key_eq +#include <rsys/hash_table.h> + + /******************************************************************************* + * A type to map vertex coordinates to IDs in unique_vertices + ******************************************************************************/ +static FINLINE int +vrtx_eq(const struct vertex* v1, const struct vertex* v2) +{ + int i; + ASSERT(v1 && v2); + FOR_EACH(i, 0, 3) if(v1->coord[i] != v2->coord[i]) return 0; + return 1; +} + +#define HTABLE_NAME vrtx +#define HTABLE_KEY struct vertex +#define HTABLE_DATA unsigned +#define HTABLE_KEY_FUNCTOR_EQ vrtx_eq +#include <rsys/hash_table.h> + +/******************************************************************************* + * Types to record sources and values of triangle descriptions. + ******************************************************************************/ + + /* A type to store a value and the files defining this value + * (usualy a single file) */ +struct definition { + /* The value */ + unsigned property_value; + /* The IDs of the geometry sets that defined the value */ + struct darray_uint set_ids; +}; + +static FINLINE void +init_definition +(struct mem_allocator* alloc, + struct definition* data) +{ + ASSERT(alloc && data); + data->property_value = SG3_UNDEFINED_PROPERTY; + darray_uint_init(alloc, &data->set_ids); +} + +static INLINE res_T +copy_definition +(struct definition* dst, + const struct definition* src) +{ + res_T res = RES_OK; + ASSERT(dst && src); + dst->property_value = src->property_value; + ERR(darray_uint_copy(&dst->set_ids, &src->set_ids)); +exit: + return res; +error: + goto exit; +} + +static FINLINE void +release_definition +(struct definition* data) +{ + ASSERT(data); + darray_uint_release(&data->set_ids); +} + +#define DARRAY_NAME definition +#define DARRAY_DATA struct definition +#define DARRAY_FUNCTOR_INIT init_definition +#define DARRAY_FUNCTOR_COPY copy_definition +#define DARRAY_FUNCTOR_RELEASE release_definition +#include <rsys/dynamic_array.h> + +/* A type to accumulate information for a triangle. + * If there is more than 1 definition / field, it is a conflict */ +struct trg_descriptions { + struct darray_definition defs[SG3_PROP_TYPES_COUNT__]; + int merge_conflict; + int properties_conflict; + char defs_include_undefined; + char property_defined[SG3_PROP_TYPES_COUNT__]; +}; + +static FINLINE void +init_trg_descriptions +(struct mem_allocator* alloc, + struct trg_descriptions* data) +{ + int i; + ASSERT(alloc && data); + FOR_EACH(i, 0, 3) darray_definition_init(alloc, data->defs + i); + data->merge_conflict = 0; + data->properties_conflict = 0; + data->defs_include_undefined = 0; + FOR_EACH(i, 0, 3) data->property_defined[i] = 0; +} + +static INLINE res_T +copy_trg_descriptions +(struct trg_descriptions* dst, + const struct trg_descriptions* src) +{ + res_T res = RES_OK; + int i; + ASSERT(dst && src); + FOR_EACH(i, 0, SG3_PROP_TYPES_COUNT__) + ERR(darray_definition_copy(&dst->defs[i], &src->defs[i])); + dst->merge_conflict = src->merge_conflict; + dst->properties_conflict = src->properties_conflict; + dst->defs_include_undefined = src->defs_include_undefined; + FOR_EACH(i, 0, 3) dst->property_defined[i] = src->property_defined[i]; +exit: + return res; +error: + goto exit; +} + +static FINLINE void +release_trg_descriptions +(struct trg_descriptions* data) +{ + int i; + ASSERT(data); + FOR_EACH(i, 0, SG3_PROP_TYPES_COUNT__) + darray_definition_release(data->defs + i); +} + +#define DARRAY_NAME trg_descriptions +#define DARRAY_DATA struct trg_descriptions +#define DARRAY_FUNCTOR_INIT init_trg_descriptions +#define DARRAY_FUNCTOR_COPY copy_trg_descriptions +#define DARRAY_FUNCTOR_RELEASE release_trg_descriptions +#include <rsys/dynamic_array.h> + +/******************************************************************************* + * A type to store interface IDs, as star-enclosures doesn't manage them. + ******************************************************************************/ +static FINLINE void +init_trg_intfaceid +(struct mem_allocator* alloc, + unsigned* data) +{ + ASSERT(data); (void)alloc; + *data = SG3_UNDEFINED_PROPERTY; +} + +#define DARRAY_NAME intface_id +#define DARRAY_DATA unsigned +#define DARRAY_FUNCTOR_INIT init_trg_intfaceid +#include <rsys/dynamic_array.h> + +/******************************************************************************* + * Types to store geometry amid sg3_geometry_add calls. + ******************************************************************************/ +struct sg3_geometry { + /* Record unique (i.e. deduplicated) triangles */ + struct darray_triangle unique_triangles; + /* Record coordinates for unique (i.e. deduplicated) vertices */ + struct darray_vertex unique_vertices; + + /* A table to map triangle vertices to IDs in unique_triangles */ + struct htable_trg unique_triangles_ids; + /* A table to map vertex coordinates to IDs in unique_vertices */ + struct htable_vrtx unique_vertices_ids; + + /* Record which set defined what */ + struct darray_trg_descriptions trg_descriptions; + + /* Counts */ + unsigned set_id; + unsigned triangle_count_including_duplicates; + unsigned sides_with_defined_medium_count; + unsigned trg_with_undef_sides_count; + unsigned trg_with_undef_intface_count; + unsigned merge_conflict_count; + unsigned properties_conflict_count; + + struct sg3_device* dev; + ref_T ref; +}; + +/******************************************************************************* + * Local functions + ******************************************************************************/ + +extern res_T +geometry_register_triangle + (struct sg3_geometry* geometry, + const struct triangle* triangle, + const unsigned triangle_unique_id, + const unsigned set_id, + const int merge_conflict); + +/* Add new undefined triangle descriptions to a geometry */ +static res_T +geometry_enlarge_trg_descriptions + (struct sg3_geometry* geom, + const size_t sz) +{ + res_T res = RES_OK; + size_t old_sz = + darray_trg_descriptions_size_get(&geom->trg_descriptions); + if(sz <= old_sz) return RES_OK; + ASSERT(sz - old_sz < UINT_MAX); + ERR(darray_trg_descriptions_resize(&geom->trg_descriptions, sz)); + geom->trg_with_undef_sides_count += (unsigned)(sz - old_sz); + geom->trg_with_undef_intface_count += (unsigned)(sz - old_sz); + +exit: + return res; +error: + goto exit; +} + +#endif /* SG3_GEOMETRY_H__ */ diff --git a/src/sg3_geometry_c.h b/src/sg3_geometry_c.h @@ -1,138 +0,0 @@ -/* Copyright (C) 2016-2019 |Meso|Star> (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 SG3_GEOMETRY_C_H__ -#define SG3_GEOMETRY_C_H__ - -#include "star-geometry.h" -#include "sg3_misc.h" - -#include <rsys/ref_count.h> -#include <rsys/dynamic_array.h> -#include <rsys/hash_table.h> - -/* Forward declaration of external opaque data types */ - -/******************************************************************************* - * A type to store triangles - ******************************************************************************/ -struct triangle { - unsigned vertex_ids[3]; - /* FRONT/BACK/INTERFACE property */ - unsigned properties[SG3_PROP_TYPES_COUNT__]; - /* ID of the triangle in user world, i.e. without deduplication */ - unsigned global_id; -}; -#define TRG_UNDEF__ {\ - { SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY },\ - { SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY },\ - SG3_UNDEFINED_PROPERTY\ -} -#define DARRAY_NAME triangle -#define DARRAY_DATA struct triangle -#include <rsys/dynamic_array.h> - -/******************************************************************************* - * A type to store vertices - ******************************************************************************/ -struct vertex { - double coord[3]; -}; -#define DARRAY_NAME vertex -#define DARRAY_DATA struct vertex -#include <rsys/dynamic_array.h> - -/******************************************************************************* - * A type to share vertices and triangles with reports - ******************************************************************************/ -struct v_n_t { - /* Record unique (i.e. deduplicated) triangles */ - struct darray_triangle unique_triangles; - /* Record coordinates for unique (i.e. deduplicated) vertices */ - struct darray_vertex unique_vertices; - - struct sg3_device* dev; - ref_T ref; -}; - -extern res_T -v_n_t_create(struct sg3_device* dev, struct v_n_t** v_n_t); - -extern void -v_n_t_ref_get(struct v_n_t* dev); - -extern void -v_n_t_ref_put(struct v_n_t* dev); - -/******************************************************************************* - * A type to map triangle vertices to IDs in unique_triangles - ******************************************************************************/ -struct unsigned3 { unsigned x[3]; }; - -static FINLINE int -trg_key_eq(const struct unsigned3* k1, const struct unsigned3* k2) -{ - ASSERT(k1 && k2); - ASSERT(k1->x[0] < k1->x[1] && k1->x[1] < k1->x[2]); - ASSERT(k2->x[0] < k2->x[1] && k2->x[1] < k2->x[2]); - return (k1->x[0] == k2->x[0]) - && (k1->x[1] == k2->x[1]) - && (k1->x[2] == k2->x[2]); -} - -#define HTABLE_NAME trg -#define HTABLE_KEY struct unsigned3 -#define HTABLE_DATA unsigned -#define HTABLE_KEY_FUNCTOR_EQ trg_key_eq -#include <rsys/hash_table.h> - - /******************************************************************************* - * A type to map vertex coordinates to IDs in unique_vertices - ******************************************************************************/ -static FINLINE int -vrtx_eq(const struct vertex* v1, const struct vertex* v2) -{ - int i; - ASSERT(v1 && v2); - FOR_EACH(i, 0, 3) if(v1->coord[i] != v2->coord[i]) return 0; - return 1; -} - -#define HTABLE_NAME vrtx -#define HTABLE_KEY struct vertex -#define HTABLE_DATA unsigned -#define HTABLE_KEY_FUNCTOR_EQ vrtx_eq -#include <rsys/hash_table.h> - -struct sg3_geometry { - /* Record unique (i.e. deduplicated) vertices and triangles */ - struct v_n_t* v_n_t; - - /* A table to map triangle vertices to IDs in unique_triangles */ - struct htable_trg unique_triangles_ids; - /* A table to map vertex coordinates to IDs in unique_vertices */ - struct htable_vrtx unique_vertices_ids; - - /* Counts */ - unsigned set_id; - unsigned triangle_count_including_duplicates; - unsigned sides_with_defined_medium_count; - - struct sg3_report* report; - struct sg3_device* dev; - ref_T ref; -}; - -#endif /* SG3_GEOMETRY_C_H__ */ diff --git a/src/sg3_report.c b/src/sg3_report.c @@ -1,544 +0,0 @@ -/* Copyright (C) 2016-2019 |Meso|Star> (contact@meso-star.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#include "star-geometry.h" -#include "sg3_geometry_c.h" -#include "sg3_report.h" -#include "sg3_device.h" - -#include <limits.h> - - /******************************************************************************* - * Helper functions - ******************************************************************************/ -static void -report_release(ref_T* ref) -{ - struct sg3_report* report; - ASSERT(ref); - report = CONTAINER_OF(ref, struct sg3_report, ref); - v_n_t_ref_put(report->v_n_t); - darray_trg_descriptions_release(&report->trg_descriptions); - MEM_RM(report->dev->allocator, report); -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -res_T -report_record_triangle - (struct sg3_report* report, - const struct triangle* triangle, - const unsigned triangle_unique_id, - const unsigned set_id, - /* The conflict code as returned by user callback; if no callback provided - * set_id is 0 or 1 according to media equality / SG3_UNDEFINED_PROPERTY */ - const int merge_conflict) -{ - res_T res = RES_OK; - struct trg_descriptions* trg_d; - int i; - char keep_prop_def[SG3_PROP_TYPES_COUNT__]; - - ASSERT(report && triangle); - - ERR(report_enlarge_trg_descriptions(report, triangle_unique_id + 1)); - trg_d = (darray_trg_descriptions_data_get(&report->trg_descriptions) - + triangle_unique_id); - /* Record information */ - FOR_EACH(i, 0, SG3_PROP_TYPES_COUNT__) { - struct darray_definition* definitions; - struct definition* defs; - int done = 0; - size_t j; - keep_prop_def[i] = trg_d->property_defined[i]; - if(triangle->properties[i] == SG3_UNDEFINED_PROPERTY) - trg_d->defs_include_undefined = 1; - else trg_d->property_defined[i] = 1; - definitions = trg_d->defs + i; - defs = darray_definition_data_get(definitions); - FOR_EACH(j, 0, darray_definition_size_get(definitions)) { - if(defs[j].property_value == triangle->properties[i]) { - /* This property_value is already registered: no conflict */ - const unsigned* ids = darray_uint_cdata_get(&defs[j].set_ids); - size_t k; - /* Search if property_value already includes set_id */ - FOR_EACH(k, 0, darray_uint_size_get(&defs[j].set_ids)) { - if(ids[k] == set_id) { - /* Same value+set_id was there already */ - done = 1; - break; - } - } - if(!done) { - /* Need to add the set_id for this property_value */ - ERR(darray_uint_push_back(&defs[j].set_ids, &set_id)); - done = 1; - } - break; - } - } - if(!done) { - /* This property_value was not recorded already */ - size_t defs_sz = darray_definition_size_get(definitions); - struct definition* new_def; - ERR(darray_definition_resize(definitions, 1 + defs_sz)); - new_def = darray_definition_data_get(definitions) + defs_sz; - ERR(darray_uint_push_back(&new_def->set_ids, &set_id)); - new_def->property_value = triangle->properties[i]; - if(!trg_d->merge_conflict && merge_conflict) { - /* If more than 1 merge_conflict occur, the first one remains */ - trg_d->merge_conflict = merge_conflict; - report->merge_conflict_count++; - } - } - } - - if((!keep_prop_def[SG3_FRONT] || !keep_prop_def[SG3_BACK]) - && trg_d->property_defined[SG3_FRONT] && trg_d->property_defined[SG3_BACK]) - { - /* Both sides are now defined */ - ASSERT(report->trg_with_undef_sides_count > 0); - report->trg_with_undef_sides_count--; - } - - if(!keep_prop_def[SG3_INTFACE] && trg_d->property_defined[SG3_INTFACE]) { - /* Interface is now defined */ - ASSERT(report->trg_with_undef_intface_count > 0); - report->trg_with_undef_intface_count--; - } - -exit: - return res; -error: - goto exit; -} - -static void -dump_partition - (const struct sg3_report* report, - FILE* stream, - const char* group_name, - enum sg3_report_dump_content partition) -{ - const struct trg_descriptions* trg_descriptions; - const struct triangle* triangles; - size_t sz, i; - ASSERT(report && stream && group_name); - ASSERT(partition == SG3_MERGE_CONFLICTS - || partition == SG3_PROPERTY_CONFLICTS - || partition == SG3_VALID_TRIANGLE); - trg_descriptions - = darray_trg_descriptions_cdata_get(&report->trg_descriptions); - sz = darray_trg_descriptions_size_get(&report->trg_descriptions); - triangles = darray_triangle_cdata_get(&report->v_n_t->unique_triangles); - fprintf(stream, "g %s\n", group_name); - FOR_EACH(i, 0, sz) { - int dump; - if(partition == SG3_VALID_TRIANGLE) - dump = !(trg_descriptions[i].merge_conflict - || trg_descriptions[i].properties_conflict); - else if(partition == SG3_MERGE_CONFLICTS) - dump = trg_descriptions[i].merge_conflict; - else { - ASSERT(partition == SG3_PROPERTY_CONFLICTS); - dump = trg_descriptions[i].properties_conflict; - } - if(!dump) continue; - fprintf(stream, "f %u %u %u\n", - /* OBJ indexing starts at 1 */ - 1 + triangles[i].vertex_ids[0], - 1 + triangles[i].vertex_ids[1], - 1 + triangles[i].vertex_ids[2]); - } -} - -/******************************************************************************* - * Exported functions - ******************************************************************************/ -res_T -sg3_report_create - (struct sg3_device* dev, - struct sg3_report** out_report) -{ - struct sg3_report* report = NULL; - res_T res = RES_OK; - - if(!dev || !out_report) { - res = RES_BAD_ARG; - goto error; - } - - report = MEM_CALLOC(dev->allocator, 1, sizeof(struct sg3_report)); - if(!report) { - log_err(dev, - "%s: could not allocate the star-geometry device.\n", FUNC_NAME); - res = RES_MEM_ERR; - goto error; - } - report->dev = dev; - report->trg_with_undef_sides_count = 0; - report->trg_with_undef_intface_count = 0; - report->merge_conflict_count = 0; - report->properties_conflict_count = 0; - report->associated = 0; - darray_trg_descriptions_init(dev->allocator, &report->trg_descriptions); - ref_init(&report->ref); - -exit: - if(out_report) *out_report = report; - return res; -error: - if(report) { - SG3(report_ref_put(report)); - report = NULL; - } - goto exit; -} - -res_T -sg3_report_validate_properties - (struct sg3_report* report, - res_T(*validate)(const unsigned, const unsigned*, void*, int*), - void* ctx) -{ - size_t sz__; - unsigned i, sz; - struct trg_descriptions* trg_descriptions; - res_T res = RES_OK; - - if(!report || !validate || !report->associated) { - if(report && !report->associated) - log_err(report->dev, - "%s: report is not associated to a geometry\n", - FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - - sz__ = darray_trg_descriptions_size_get(&report->trg_descriptions); - ASSERT(sz__ <= UINT_MAX); - sz = (unsigned)sz__; - trg_descriptions - = darray_trg_descriptions_data_get(&report->trg_descriptions); - report->properties_conflict_count = 0; /* Reset count */ - FOR_EACH(i, 0, sz) { - unsigned props[3] = { - SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY, SG3_UNDEFINED_PROPERTY }; - struct trg_descriptions* trgd = trg_descriptions + i; - /* Validate only triangle not flagged with merge_conflict */ - if(trgd->merge_conflict) { - trgd->properties_conflict = 0; - continue; - } - /* Get non-conflicting properties */ - /* Call vaildation */ - ERR(validate(i, props, ctx, &trgd->properties_conflict)); - if(trgd->properties_conflict) - report->properties_conflict_count++; - } - -exit: - return res; -error: - goto exit; -} - -res_T -sg3_report_get_unique_vertices_count - (const struct sg3_report* report, - unsigned* count) -{ - res_T res = RES_OK; - size_t sz; - if(!report || !count || !report->associated) { - if(report && !report->associated) - log_err(report->dev, - "%s: report is not associated to a geometry\n", - FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - sz = darray_vertex_size_get(&report->v_n_t->unique_vertices); - ASSERT(sz <= UINT_MAX); - *count = (unsigned)sz; -exit: - return res; -error: - goto exit; -} - -res_T -sg3_report_get_unique_triangles_count - (const struct sg3_report* report, - unsigned* count) -{ - res_T res = RES_OK; - size_t sz; - if(!report || !count || !report->associated) { - if(report && !report->associated) - log_err(report->dev, - "%s: report is not associated to a geometry\n", - FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - sz = darray_triangle_size_get(&report->v_n_t->unique_triangles); - ASSERT(sz <= UINT_MAX); - *count = (unsigned)sz; -exit: - return res; -error: - goto exit; -} - -res_T -sg3_report_get_triangle_with_undefined_side_count - (const struct sg3_report* report, - unsigned* count) -{ - res_T res = RES_OK; - if(!report || !count || !report->associated) { - if(report && !report->associated) - log_err(report->dev, - "%s: report is not associated to a geometry\n", - FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - *count = report->trg_with_undef_sides_count; -exit: - return res; -error: - goto exit; -} - -res_T -sg3_report_get_triangle_with_undefined_interface_count - (const struct sg3_report* report, - unsigned* count) -{ - res_T res = RES_OK; - if(!report || !count || !report->associated) { - if(report && !report->associated) - log_err(report->dev, - "%s: report is not associated to a geometry\n", - FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - *count = report->trg_with_undef_intface_count; -exit: - return res; -error: - goto exit; -} - -res_T -sg3_report_get_merge_conflict_count - (const struct sg3_report* report, - unsigned* count) -{ - res_T res = RES_OK; - if(!report || !count || !report->associated) { - if(report && !report->associated) - log_err(report->dev, - "%s: report is not associated to a geometry\n", - FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - *count = report->merge_conflict_count; -exit: - return res; -error: - goto exit; -} - -res_T -sg3_report_get_properties_conflict_count - (const struct sg3_report* report, - unsigned* count) -{ - res_T res = RES_OK; - if(!report || !count || !report->associated) { - if(report && !report->associated) - log_err(report->dev, - "%s: report is not associated to a geometry\n", - FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - *count = report->properties_conflict_count; -exit: - return res; -error: - goto exit; -} - -res_T -sg3_report_dump_as_obj - (const struct sg3_report* report, - FILE* stream, - int flags) -{ - res_T res = RES_OK; - const struct vertex* vertices; - size_t vsz, tsz, i; - if(!report || !stream || !flags || !report->associated) { - if(report && !report->associated) - log_err(report->dev, - "%s: report is not associated to a geometry\n", - FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - /* Headers */ - fprintf(stream, "# Dump of star-geometry report\n"); - fprintf(stream, "# Geometry counts:\n"); - vsz = darray_vertex_size_get(&report->v_n_t->unique_vertices); - ASSERT(vsz <= UINT_MAX); - fprintf(stream, "# . %u vertices\n", (unsigned)vsz); - tsz = darray_triangle_size_get(&report->v_n_t->unique_triangles); - ASSERT(tsz <= UINT_MAX); - fprintf(stream, "# . %u triangles\n", (unsigned)tsz); - fprintf(stream, - "# . %u triangles flagged with a merge conflict\n", - report->merge_conflict_count); - fprintf(stream, - "# . %u triangles flagged with a property conflict\n", - report->merge_conflict_count); - - /* Dump vertices */ - vertices = darray_vertex_cdata_get(&report->v_n_t->unique_vertices); - FOR_EACH(i, 0, vsz) - fprintf(stream, "v %f %f %f\n", SPLIT3(vertices[i].coord)); - - /* Dump triangles by groups */ - dump_partition(report, stream, "Merge conflicts", SG3_MERGE_CONFLICTS); - dump_partition(report, stream, "Property conflicts", SG3_PROPERTY_CONFLICTS); - dump_partition(report, stream, "Valid triangles", SG3_VALID_TRIANGLE); - -exit: - return res; -error: - goto exit; -} - -res_T -sg3_report_dump_as_C_code - (const struct sg3_report* report, - FILE* stream, - const char* name_prefix) -{ - res_T res = RES_OK; - const struct vertex* vertices; - const struct triangle* triangles; - size_t vsz, tsz, i; - if(!report || !stream || !name_prefix || !report->associated - || report->merge_conflict_count > 0 || report->properties_conflict_count) - { - if(report && !report->associated) - log_err(report->dev, - "%s: report is not associated to a geometry\n", - FUNC_NAME); - if(report->merge_conflict_count > 0 || report->properties_conflict_count) - log_err(report->dev, - "%s: cannot dump geometries with conflict as C code\n", - FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - /* Headers */ - fprintf(stream, "/* Dump of star-geometry report. */\n"); - vsz = darray_vertex_size_get(&report->v_n_t->unique_vertices); - ASSERT(vsz <= UINT_MAX); - tsz = darray_triangle_size_get(&report->v_n_t->unique_triangles); - ASSERT(tsz <= UINT_MAX); - - if(vsz == 0 || tsz == 0) { - log_err(report->dev, - "%s: no geometry to dump\n", - FUNC_NAME); - res = RES_BAD_ARG; - goto error; - } - - /* Dump vertices */ - vertices = darray_vertex_cdata_get(&report->v_n_t->unique_vertices); - fprintf(stream, - "const double %s_vertices[%u][3] =\n" - " {\n", - name_prefix, (unsigned)vsz); - FOR_EACH(i, 0, vsz-1) - fprintf(stream, - " { %f, %f, %f },\n", SPLIT3(vertices[i].coord)); - fprintf(stream, - " { %f, %f, %f }\n", SPLIT3(vertices[vsz - 1].coord)); - fprintf(stream, - " }" - "}\n"); - - /* Dump triangles */ - triangles = darray_triangle_cdata_get(&report->v_n_t->unique_triangles); - fprintf(stream, - "const unsigned %s_triangles[%u][3] =\n" - " {\n", - name_prefix, (unsigned)tsz); - FOR_EACH(i, 0, tsz-1) - fprintf(stream, - " { %u, %u, %u },\n", SPLIT3(triangles[i].vertex_ids)); - fprintf(stream, - " { %u, %u, %u }\n", SPLIT3(triangles[tsz - 1].vertex_ids)); - fprintf(stream, - " }" - "}\n"); - - /* Dump properties */ - triangles = darray_triangle_cdata_get(&report->v_n_t->unique_triangles); - fprintf(stream, - "const unsigned %s_properties[%u][3] =\n" - " {\n", - name_prefix, (unsigned)tsz); - FOR_EACH(i, 0, tsz - 1) - fprintf(stream, - " { %u, %u, %u },\n", SPLIT3(triangles[i].properties)); - fprintf(stream, - " { %u, %u, %u }\n", SPLIT3(triangles[tsz - 1].properties)); - fprintf(stream, - " }" - "}\n"); - -exit: - return res; -error: - goto exit; -} - -res_T -sg3_report_ref_get(struct sg3_report* report) -{ - if(!report) return RES_BAD_ARG; - ref_get(&report->ref); - return RES_OK; -} - -res_T -sg3_report_ref_put(struct sg3_report* report) -{ - if(!report) return RES_BAD_ARG; - ref_put(&report->ref, report_release); - return RES_OK; -} diff --git a/src/sg3_report.h b/src/sg3_report.h @@ -1,266 +0,0 @@ -/* Copyright (C) 2016-2019 |Meso|Star> (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 SG3_REPORT_H__ -#define SG3_REPORT_H__ - -#include "star-geometry.h" -#include "sg3_misc.h" - -#include <rsys/rsys.h> -#include <rsys/ref_count.h> -#include <rsys/str.h> -#include <rsys/dynamic_array_uint.h> -#include <rsys/dynamic_array.h> - - /* Forward declarations */ -struct mem_allocator; -struct sg3_device; -struct sg3_report; -struct darray_description; -struct triangle; -struct sg3_geometry; -struct v_n_t; - -/******************************************************************************* - * Types to record sources and values of triangle descriptions. - ******************************************************************************/ - -/* A type to store a value and the files defining this value - * (usualy a single file) */ -struct definition { - /* The value */ - unsigned property_value; - /* The IDs of the geometry sets that defined the value */ - struct darray_uint set_ids; -}; - -static FINLINE void -init_definition - (struct mem_allocator* alloc, - struct definition* data) -{ - ASSERT(alloc && data); - data->property_value = SG3_UNDEFINED_PROPERTY; - darray_uint_init(alloc, &data->set_ids); -} - -static INLINE res_T -copy_definition - (struct definition* dst, - const struct definition* src) -{ - res_T res = RES_OK; - ASSERT(dst && src); - dst->property_value = src->property_value; - ERR(darray_uint_copy(&dst->set_ids, &src->set_ids)); -exit: - return res; -error: - goto exit; -} - -static FINLINE void -release_definition - (struct definition* data) -{ - ASSERT(data); - darray_uint_release(&data->set_ids); -} - -#define DARRAY_NAME definition -#define DARRAY_DATA struct definition -#define DARRAY_FUNCTOR_INIT init_definition -#define DARRAY_FUNCTOR_COPY copy_definition -#define DARRAY_FUNCTOR_RELEASE release_definition -#include <rsys/dynamic_array.h> - -/* A type to accumulate information for a triangle. - * If there is more than 1 definition / field, it is a conflict */ -struct trg_descriptions { - struct darray_definition defs[SG3_PROP_TYPES_COUNT__]; - int merge_conflict; - int properties_conflict; - char defs_include_undefined; - char property_defined[SG3_PROP_TYPES_COUNT__]; -}; - -static FINLINE void -init_trg_descriptions - (struct mem_allocator* alloc, - struct trg_descriptions* data) -{ - int i; - ASSERT(alloc && data); - FOR_EACH(i, 0, 3) darray_definition_init(alloc, data->defs + i); - data->merge_conflict = 0; - data->properties_conflict = 0; - data->defs_include_undefined = 0; - FOR_EACH(i, 0, 3) data->property_defined[i] = 0; -} - -static INLINE res_T -copy_trg_descriptions - (struct trg_descriptions* dst, - const struct trg_descriptions* src) -{ - res_T res = RES_OK; - int i; - ASSERT(dst && src); - FOR_EACH(i, 0, SG3_PROP_TYPES_COUNT__) - ERR(darray_definition_copy(&dst->defs[i], &src->defs[i])); - dst->merge_conflict = src->merge_conflict; - dst->properties_conflict = src->properties_conflict; - dst->defs_include_undefined = src->defs_include_undefined; - FOR_EACH(i, 0, 3) dst->property_defined[i] = src->property_defined[i]; -exit: - return res; -error: - goto exit; -} - -static FINLINE void -release_trg_descriptions - (struct trg_descriptions* data) -{ - int i; - ASSERT(data); - FOR_EACH(i, 0, SG3_PROP_TYPES_COUNT__) - darray_definition_release(data->defs + i); -} - -#define DARRAY_NAME trg_descriptions -#define DARRAY_DATA struct trg_descriptions -#define DARRAY_FUNCTOR_INIT init_trg_descriptions -#define DARRAY_FUNCTOR_COPY copy_trg_descriptions -#define DARRAY_FUNCTOR_RELEASE release_trg_descriptions -#include <rsys/dynamic_array.h> - -/******************************************************************************* - * A type to store interface IDs, as star-enclosures doesn't manage them. - ******************************************************************************/ -static FINLINE void -init_trg_intfaceid - (struct mem_allocator* alloc, - unsigned* data) -{ - ASSERT(data); (void)alloc; - *data = SG3_UNDEFINED_PROPERTY; -} - -#define DARRAY_NAME intface_id -#define DARRAY_DATA unsigned -#define DARRAY_FUNCTOR_INIT init_trg_intfaceid -#include <rsys/dynamic_array.h> - -/******************************************************************************* - * A type to associate a file and accumulated propeties - ******************************************************************************/ -struct accumulated_set { - struct str set_name; - unsigned prop_value; -}; - -static FINLINE void -init_accumulated_set - (struct mem_allocator* alloc, - struct accumulated_set* set) -{ - ASSERT(alloc && set); - str_init(alloc, &set->set_name); - set->prop_value = SG3_UNDEFINED_PROPERTY; -} - -static FINLINE void -release_accumulated_set - (struct accumulated_set* set) -{ - ASSERT(set); - str_release(&set->set_name); -} - -static INLINE res_T -copy_accumulated_set - (struct accumulated_set* dst, - const struct accumulated_set* src) -{ - res_T res = RES_OK; - ASSERT(dst && src); - ERR(str_copy(&dst->set_name, &src->set_name)); - dst->prop_value = src->prop_value; -exit: - return res; -error: - goto exit; -} - -#define DARRAY_NAME accumulated_set -#define DARRAY_DATA struct accumulated_set -#define DARRAY_FUNCTOR_INIT init_accumulated_set -#define DARRAY_FUNCTOR_COPY copy_accumulated_set -#define DARRAY_FUNCTOR_RELEASE release_accumulated_set -#include <rsys/dynamic_array.h> - -/******************************************************************************* - * Types to store reports amid sg3_accumulate_stl_file calls. - ******************************************************************************/ -struct sg3_report { - /* Record which set defined what */ - struct darray_trg_descriptions trg_descriptions; - /* Record unique (i.e. deduplicated) vertices and triangles */ - struct v_n_t* v_n_t; - /* Counts */ - unsigned trg_with_undef_sides_count; - unsigned trg_with_undef_intface_count; - unsigned merge_conflict_count; - unsigned properties_conflict_count; - int associated; - - ref_T ref; - struct sg3_device* dev; -}; - -/* Add new undefined triangle descriptions to a report */ -static res_T -report_enlarge_trg_descriptions - (struct sg3_report* report, - const size_t sz) -{ - res_T res = RES_OK; - size_t old_sz = - darray_trg_descriptions_size_get(&report->trg_descriptions); - if(sz <= old_sz) return RES_OK; - ASSERT(sz - old_sz < UINT_MAX); - ERR(darray_trg_descriptions_resize(&report->trg_descriptions, sz)); - report->trg_with_undef_sides_count += (unsigned)(sz - old_sz); - report->trg_with_undef_intface_count += (unsigned)(sz - old_sz); -exit: - return res; -error: - goto exit; -} - -/******************************************************************************* - * Local functions - ******************************************************************************/ -extern res_T -report_record_triangle - (struct sg3_report* report, - const struct triangle* triangle, - const unsigned triangle_unique_id, - const unsigned set_id, - const int merge_conflict); - -#endif /* SG3_REPORT_H__ */ diff --git a/src/star-geometry.h b/src/star-geometry.h @@ -52,7 +52,6 @@ struct senc_scene; * the object is silently destroyed and cannot be used anymore. */ struct sg3_device; struct sg3_geometry; -struct sg3_report; /******************************************************************************* * A type to list the different user properties attached to triangles. @@ -67,7 +66,7 @@ enum sg3_property_type { /******************************************************************************* * A type to list the different possible partitions of triangles. ******************************************************************************/ -enum sg3_report_dump_content { +enum sg3_dump_content { SG3_MERGE_CONFLICTS = BIT(0), SG3_PROPERTY_CONFLICTS = BIT(1), SG3_VALID_TRIANGLE = BIT(2), @@ -117,111 +116,16 @@ sg3_device_ref_put (struct sg3_device* dev); /******************************************************************************* - * star-geometry report. Associated to a geometry, it stores information - * related to it, including conflicts. A report cannot be associated to more - * than one geometry, even after geometry release. - * Reports main purpose is to be dumped. - ******************************************************************************/ -/* Create a report that can be used to accumulate information on a geometry. */ -SG3_API res_T -sg3_report_create - (struct sg3_device* dev, - struct sg3_report** report); - -/* Apply a validation callback on each triangle included in this report that - * is not already flagged with a merge error. If validate returns a non-RES_OK - * value, the validation stops and returns the same error value; on the other - * hand, validation goes to the end regardless of properties conflicts. - * The properties_conflict argument can be set to any value. Any non-0 value - * is accounted for a conflict and is kept as-is in report dumps, allowing - * different shades of conflict to be reported. - * If validation is processed again, the properties conflict count is reset, - * as well as the properties_conflict of the triangles. */ -SG3_API res_T -sg3_report_validate_properties - (struct sg3_report* report, - res_T(*validate) - (const unsigned itri, const unsigned properties[3], void* context, - int* properties_conflict), - void* context); /* Can be NULL */ - -/* Get the number of unique vertices. */ -SG3_API res_T -sg3_report_get_unique_vertices_count - (const struct sg3_report* report, - unsigned* count); - -/* Get the number of unique triangles. */ -SG3_API res_T -sg3_report_get_unique_triangles_count - (const struct sg3_report* report, - unsigned* count); - -/* Get the number of triangle with (at least) one undefined side. */ -SG3_API res_T -sg3_report_get_triangle_with_undefined_side_count - (const struct sg3_report* report, - unsigned* count); - -/* Get the number of triangle with undefined interface. */ -SG3_API res_T -sg3_report_get_triangle_with_undefined_interface_count - (const struct sg3_report* report, - unsigned* count); - -/* Get the number of triangle flagged with a merge conflict. */ -SG3_API res_T -sg3_report_get_merge_conflict_count - (const struct sg3_report* report, - unsigned* count); - -/* Get the number of triangle flagged with a property conflict. Only meaningful - * after sg3_report_validate_properties has been called. */ -SG3_API res_T -sg3_report_get_properties_conflict_count - (const struct sg3_report* report, - unsigned* count); - -/* Dump a report in the provided stream in the OBJ format. The report must have - * been associated to a geometry or dump will end in error. - * The OBJ dump is made of the vertices and triangles, without properties, that - * have been added to the geometry associated with this report. - * The part of the report that is dumped is defined by the flags argument, - * that should be ORed enum sg3_report_dump_content values. - * If more than 1 flag is used, triangle partitions are dumped in different - * OBJ groups. */ -SG3_API res_T -sg3_report_dump_as_obj - (const struct sg3_report* report, - FILE* stream, - int flags); - -/* Dump the report as C code. - * The associated geometry cannot be empty and must be conflict-free */ -SG3_API res_T -sg3_report_dump_as_C_code - (const struct sg3_report* report, - FILE* stream, - const char* name_prefix); - -SG3_API res_T -sg3_report_ref_get - (struct sg3_report* report); - -SG3_API res_T -sg3_report_ref_put - (struct sg3_report* report); - -/******************************************************************************* * star-geometry geometry. - * It stores decorated geometry accumulated through calls to sg3_geometry_add. - * If report is provided, it stores informations related to this geometry and - * its creation process, including merge conflicts. + * It stores decorated geometry accumulated through calls to sg3_geometry_add, + * information related to this geometry and its creation process, including merge + * conflicts. ******************************************************************************/ +/* Create a geometry that can be used to accumulate vertices and triangles + * decorated with properties. */ SG3_API res_T sg3_geometry_create (struct sg3_device* dev, - struct sg3_report* report, /* Can be NULL */ struct sg3_geometry** geometry); /* Add a new set of 3D vertices and triangles to the geometry; triangles can @@ -229,26 +133,25 @@ sg3_geometry_create * be let undefined using the SG3_UNDEFINED_PROPERTY special value. * Vertices can be duplicates and are silently deduplicated, always valid. * Triangles can be duplicates, but this can be ruled invalid due to property - * inconsistency. Consistency is to be understood as the consistency of the + * inconsistency. Triangle duplicates are silently deduplicated, even if + * invalid. Consistency is to be understood as the consistency of the * successive values for the same property across calls of sg3_geometry_add, * not as the consistency of the values of the 3 properties of a triangle at * some given time (this question has its own callback (validate) in the - * sg3_report_validate_properties API call). Triangle duplicates are silently - * deduplicated, even if invalid. + * sg3_geometry_validate_properties API call). * Duplicate triangles validity is either ruled by the user-provided * merge_triangle callback, or is just a matter of properties consistency if no * callback is provided. In either case, sg3_geometry_add never stops - * prematurely due to a merge conflict and sg3_geometry_add return code is - * RES_BAD_ARG if no other error code is encountered through the process and an - * inconsistency is found. - * - if provided, the callback must return the consistency status using the + * prematurely nor returns an error code due to a merge conflict. + * - if provided, the callback must return the consistency status using the * merge_conflict int* paramater (0 for consistent; any other value for - * inconsistent, this value being recorded in the report); regardless of the + * inconsistent, this value being recorded); regardless of the * merge_conflict status, the callback can change the properties of the * triangle before the SG3_UNDEFINED_PROPERTY overwriting step; * - if not, a non-SG3_UNDEFINED_PROPERTY is only consistent with itself and - * with SG3_UNDEFINED_PROPERTY; regardless of the merge_conflict status, - * a non-SG3_UNDEFINED_PROPERTY property is never overridden. + * with SG3_UNDEFINED_PROPERTY (if inconsistent, the merge_conflict status is + * set to 1 and recorded) ; regardless of the merge_conflict status, a + * non-SG3_UNDEFINED_PROPERTY property is never overridden. * When deduplicating triangles, the first occurence remains (with its * original index in user world). After consistency being computed, a final * step consists in rewriting SG3_UNDEFINED_PROPERTY properties if the merged @@ -256,7 +159,6 @@ sg3_geometry_create SG3_API res_T sg3_geometry_add (struct sg3_geometry* geometry, - /* The ID associated to this set of geometry in report */ /* Number of added triangles */ const unsigned triangles_count, /* User function that provides vertices ids for added triangles */ @@ -281,9 +183,9 @@ sg3_geometry_add * The reversed_triangle arg indicates if the triangle vertices' order is * the same it was when the triangle was first added. * The merge_conflict argument can be set to any value. Any non-0 value - * is accounted for a conflict and is kept as-is in report dumps, allowing - * different shades of conflict to be reported. - * triangle_properties and merged_properties contain the involved + * is accounted for a conflict and is kept as-is in dumps, allowing + * different shades of conflict. + * The triangle_properties and merged_properties args contain the involved * properties. */ res_T(*merge_triangle) /* Can be NULL */ (const unsigned global_id, const unsigned itri, const int reversed_triangle, @@ -291,6 +193,82 @@ sg3_geometry_add void* context, int* merge_conflict), void* context); /* Can be NULL */ +/* Apply a validation callback on each triangle included in this geometry that + * is not already flagged with a merge error. If validate returns a non-RES_OK + * value, the validation stops and returns the same error value; on the other + * hand, validation goes to the end regardless of properties conflicts. + * The properties_conflict argument can be set to any value. Any non-0 value + * is accounted for a conflict and is kept as-is in dumps, allowing different + * shades of conflict. + * If validation is processed again, the properties conflict count is reset, + * as well as the properties_conflict status of the triangles. */ +SG3_API res_T +sg3_geometry_validate_properties + (struct sg3_geometry* geometry, + res_T(*validate) + (const unsigned itri, const unsigned properties[3], void* context, + int* properties_conflict), + void* context); /* Can be NULL */ + +/* Get the number of unique vertices. */ +SG3_API res_T +sg3_geometry_get_unique_vertices_count + (const struct sg3_geometry* geometry, + unsigned* count); + +/* Get the number of unique triangles. */ +SG3_API res_T +sg3_geometry_get_unique_triangles_count + (const struct sg3_geometry* geometry, + unsigned* count); + +/* Get the number of triangle with (at least) one undefined side. */ +SG3_API res_T +sg3_geometry_get_triangle_with_undefined_side_count + (const struct sg3_geometry* geometry, + unsigned* count); + +/* Get the number of triangle with undefined interface. */ +SG3_API res_T +sg3_geometry_get_triangle_with_undefined_interface_count + (const struct sg3_geometry* geometry, + unsigned* count); + +/* Get the number of triangle flagged with a merge conflict. */ +SG3_API res_T +sg3_geometry_get_merge_conflict_count + (const struct sg3_geometry* geometry, + unsigned* count); + +/* Get the number of triangle flagged with a property conflict. Only meaningful + * after sg3_geometry_validate_properties has been called. */ +SG3_API res_T +sg3_geometry_get_properties_conflict_count + (const struct sg3_geometry* geometry, + unsigned* count); + +/* Dump a geometry in the provided stream in the OBJ format. + * The geometry can include conflicts, but cannot be empty. + * The OBJ dump is made of the vertices and triangles, without properties, that + * have been added to the geometry. + * The part of the geometry that is dumped is defined by the flags argument, + * that should be ORed enum sg3_dump_content values. + * If more than 1 flag is used, triangle partitions are dumped in different + * OBJ groups. */ +SG3_API res_T +sg3_geometry_dump_as_obj + (const struct sg3_geometry* geometry, + FILE* stream, + int flags); + +/* Dump the geometry as C code. + * The geometry cannot be empty and must be conflict-free */ +SG3_API res_T +sg3_geometry_dump_as_C_code + (const struct sg3_geometry* geometry, + FILE* stream, + const char* name_prefix); + SG3_API res_T sg3_geometry_ref_get (struct sg3_geometry* geometry); diff --git a/src/test_sg3_geometry.c b/src/test_sg3_geometry.c @@ -16,37 +16,163 @@ #include "star-geometry.h" #include "test_sg3_utils.h" +#include <rsys/double3.h> + +#include <stdio.h> + +static res_T +validate + (const unsigned itri, + const unsigned properties[3], + void* context, + int* properties_conflict) +{ + (void)itri; (void)properties; (void)context; + *properties_conflict = 0; + return RES_OK; +} + +static res_T +merge_trg + (const unsigned global_id, + const unsigned itri, + const int reversed_triangle, + unsigned triangle_properties[3], + const unsigned merged_properties[3], + void* context, + int* merge_conflict) +{ + ASSERT(merge_conflict); + (void)global_id; (void)reversed_triangle; (void)context; + (void)triangle_properties; (void)merged_properties; (void)merge_conflict; + *merge_conflict = (int)itri; + return RES_OK; +} + int main(int argc, char** argv) { struct mem_allocator allocator; struct sg3_device* dev; - struct sg3_report* report; - struct sg3_geometry* geometry; - struct sg3_geometry* geometry2; + struct sg3_geometry* geom; + unsigned count, i; + struct context ctx; (void)argc, (void)argv; OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); OK(sg3_device_create(NULL, &allocator, 1, &dev)); - BA(sg3_geometry_create(NULL, NULL, &geometry)); - BA(sg3_geometry_create(dev, NULL, NULL)); - OK(sg3_geometry_create(dev, NULL, &geometry)); + BA(sg3_geometry_create(NULL, &geom)); + BA(sg3_geometry_create(dev, NULL)); + OK(sg3_geometry_create(dev, &geom)); BA(sg3_geometry_ref_get(NULL)); - OK(sg3_geometry_ref_get(geometry)); + OK(sg3_geometry_ref_get(geom)); BA(sg3_geometry_ref_put(NULL)); - OK(sg3_geometry_ref_put(geometry)); - OK(sg3_geometry_ref_put(geometry)); + OK(sg3_geometry_ref_put(geom)); + OK(sg3_geometry_ref_put(geom)); + + OK(sg3_geometry_create(dev, &geom)); + + BA(sg3_geometry_validate_properties(NULL, NULL, NULL)); + BA(sg3_geometry_validate_properties(geom, NULL, NULL)); + BA(sg3_geometry_validate_properties(NULL, validate, NULL)); + OK(sg3_geometry_validate_properties(geom, validate, NULL)); + + BA(sg3_geometry_get_unique_vertices_count(NULL, NULL)); + BA(sg3_geometry_get_unique_vertices_count(geom, NULL)); + BA(sg3_geometry_get_unique_vertices_count(NULL, &count)); + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + + BA(sg3_geometry_get_unique_triangles_count(NULL, NULL)); + BA(sg3_geometry_get_unique_triangles_count(geom, NULL)); + BA(sg3_geometry_get_unique_triangles_count(NULL, &count)); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + + BA(sg3_geometry_get_triangle_with_undefined_side_count(NULL, NULL)); + BA(sg3_geometry_get_triangle_with_undefined_side_count(geom, NULL)); + BA(sg3_geometry_get_triangle_with_undefined_side_count(NULL, &count)); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + + BA(sg3_geometry_get_triangle_with_undefined_interface_count(NULL, NULL)); + BA(sg3_geometry_get_triangle_with_undefined_interface_count(geom, NULL)); + BA(sg3_geometry_get_triangle_with_undefined_interface_count(NULL, &count)); + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + + BA(sg3_geometry_get_merge_conflict_count(NULL, NULL)); + BA(sg3_geometry_get_merge_conflict_count(geom, NULL)); + BA(sg3_geometry_get_merge_conflict_count(NULL, &count)); + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + + BA(sg3_geometry_get_properties_conflict_count(NULL, NULL)); + BA(sg3_geometry_get_properties_conflict_count(geom, NULL)); + BA(sg3_geometry_get_properties_conflict_count(NULL, &count)); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + + BA(sg3_geometry_dump_as_obj(NULL, NULL, 0)); + BA(sg3_geometry_dump_as_obj(geom, NULL, 0)); + BA(sg3_geometry_dump_as_obj(NULL, stdout, 0)); + BA(sg3_geometry_dump_as_obj(NULL, NULL, SG3_ALL_TRIANGLES)); + BA(sg3_geometry_dump_as_obj(geom, stdout, 0)); + BA(sg3_geometry_dump_as_obj(geom, NULL, SG3_ALL_TRIANGLES)); + BA(sg3_geometry_dump_as_obj(NULL, stdout, SG3_ALL_TRIANGLES)); + /* Empty geometry */ + BA(sg3_geometry_dump_as_obj(geom, stdout, SG3_ALL_TRIANGLES)); + + BA(sg3_geometry_dump_as_C_code(NULL, NULL, NULL)); + BA(sg3_geometry_dump_as_C_code(geom, NULL, NULL)); + BA(sg3_geometry_dump_as_C_code(NULL, stdout, NULL)); + BA(sg3_geometry_dump_as_C_code(NULL, NULL, "test")); + BA(sg3_geometry_dump_as_C_code(geom, NULL, "test")); + BA(sg3_geometry_dump_as_C_code(geom, stdout, NULL)); + BA(sg3_geometry_dump_as_C_code(NULL, stdout, "test")); + /* Empty geometry */ + BA(sg3_geometry_dump_as_C_code(geom, stdout, "test")); + + /* A 3D cube. + * 2 enclosures (inside, outside) sharing the same triangles, + * but opposite sides */ + ctx.positions = cube_vertices; + ctx.indices = cube_indices; + ctx.scale = 1; + d3(ctx.offset, 0, 0, 0); + ctx.front_media = medium0; + ctx.back_media = medium1; + ctx.intface = intface0; + ctx.custom = NULL; + + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, NULL, NULL, &ctx)); + OK(sg3_geometry_dump_as_obj(geom, stdout, SG3_ALL_TRIANGLES)); + OK(sg3_geometry_dump_as_C_code(geom, stdout, "test")); + + /* Conflicts with merge_trg callback */ + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, NULL, merge_trg, &ctx)); + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + /* Due to merge_trg internals, all but the first triangle have conflict */ + CHK(count == ntriangles - 1); + OK(sg3_geometry_dump_as_obj(geom, stdout, SG3_ALL_TRIANGLES)); + /* BA because of conflicts */ + BA(sg3_geometry_dump_as_C_code(geom, stdout, "test")); + OK(sg3_geometry_ref_put(geom)); - OK(sg3_report_create(dev, &report)); - OK(sg3_geometry_create(dev, report, &geometry)); - /* Cannot associate 2 geometries to the same report */ - BA(sg3_geometry_create(dev, report, &geometry2)); - OK(sg3_report_ref_put(report)); + /* Conflicts without merge_trg callback */ + OK(sg3_geometry_create(dev, &geom)); + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, NULL, NULL, &ctx)); + ctx.front_media = medium1_front0; + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, NULL, NULL, &ctx)); + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + FOR_EACH(i, 0, ntriangles) if(medium0[i] != medium1_front0[i]) count--; + CHK(count == 0); + OK(sg3_geometry_dump_as_obj(geom, stdout, SG3_ALL_TRIANGLES)); + /* BA because of conflicts */ + BA(sg3_geometry_dump_as_C_code(geom, stdout, "test")); - OK(sg3_geometry_ref_put(geometry)); + OK(sg3_geometry_ref_put(geom)); OK(sg3_device_ref_put(dev)); check_memory_allocator(&allocator); diff --git a/src/test_sg3_geometry_2.c b/src/test_sg3_geometry_2.c @@ -0,0 +1,399 @@ +/* Copyright (C) 2016-2019 |Meso|Star> (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "star-geometry.h" +#include "test_sg3_utils.h" + +#include <rsys/double3.h> + +#include <stdio.h> + + /* Manage add_geometry behaviour */ +struct add_geom_ctx { + unsigned add_cpt, merge_cpt; + res_T add_res, merge_res; +}; + +static res_T +add_trg + (const unsigned global_id, + const unsigned iseg, + void* context) +{ + struct context* ctx = context; + struct add_geom_ctx* add_geom_ctx; + ASSERT(ctx); (void)global_id; (void)iseg; + add_geom_ctx = ctx->custom; + if(add_geom_ctx->add_res == RES_OK) ++add_geom_ctx->add_cpt; + return add_geom_ctx->add_res; +} + +static res_T +merge_trg + (const unsigned global_id, + const unsigned itri, + const int reversed_triangle, + unsigned triangle_properties[3], + const unsigned merged_properties[3], + void* context, + int* merge_conflict) +{ + struct context* ctx = context; + struct add_geom_ctx* add_geom_ctx; + int i; + ASSERT(ctx && triangle_properties && merged_properties && merge_conflict); + (void)global_id; (void)itri; (void)reversed_triangle; + (void)triangle_properties; (void)merged_properties; + add_geom_ctx = ctx->custom; + if(add_geom_ctx->merge_res == RES_OK) ++add_geom_ctx->merge_cpt; + FOR_EACH(i, 0, 3) + if(!sg3_compatible_property(triangle_properties[i], merged_properties[i])) + *merge_conflict = 1; + return add_geom_ctx->merge_res; +} + +static res_T +validate + (const unsigned itri, + const unsigned properties[3], + void* context, + int* properties_conflict) +{ + (void)itri; (void)properties; (void)context; + *properties_conflict = 0; + return RES_OK; +} + +static res_T +validate2 + (const unsigned itri, + const unsigned properties[3], + void* context, + int* properties_conflict) +{ + (void)itri; (void)properties; (void)context; + *properties_conflict = (itri % 2 == 0) ? 0 : itri; + return RES_OK; +} + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct sg3_device* dev; + struct sg3_geometry* geom; + struct context ctx; + struct add_geom_ctx add_geom_ctx; + unsigned property[12]; + unsigned i; + const unsigned property_count = sizeof(property) / sizeof(*property); + unsigned count; + (void)argc, (void)argv; + + OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); + OK(sg3_device_create(NULL, &allocator, 1, &dev)); + OK(sg3_geometry_create(dev, &geom)); + + /* A 3D cube. + * 2 enclosures (inside, outside) sharing the same triangles, + * but opposite sides */ + ctx.positions = cube_vertices; + ctx.indices = cube_indices; + ctx.scale = 1; + d3(ctx.offset, 0, 0, 0); + ctx.custom = &add_geom_ctx; + + add_geom_ctx.add_cpt = add_geom_ctx.merge_cpt = 0; + add_geom_ctx.add_res = add_geom_ctx.merge_res = RES_OK; + + /* Geometry with no media information on both sides */ + for(i = 0; i < property_count; i++) property[i] = SG3_UNDEFINED_PROPERTY; + ctx.front_media = property; + ctx.back_media = property; + ctx.intface = property; + + /* If add fails, add geometry fails the same way */ + add_geom_ctx.add_res = RES_BAD_ARG; + BA(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.add_cpt == 0); + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == 0); + add_geom_ctx.add_res = RES_MEM_ERR; + ME(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.add_cpt == 0); + CHK(count == 0); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* Successful add geometry with add callback */ + add_geom_ctx.add_res = RES_OK; + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.add_cpt == ntriangles); + CHK(add_geom_ctx.merge_cpt == 0); + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* Clear geometry */ + SG3(geometry_ref_put(geom)); + OK(sg3_geometry_create(dev, &geom)); + + /* Successful add geometry without add callback */ + add_geom_ctx.add_cpt = 0; + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, NULL, merge_trg, &ctx)); + CHK(add_geom_ctx.add_cpt == 0); + CHK(add_geom_ctx.merge_cpt == 0); + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* If merge fails, add geometry fails the same way */ + add_geom_ctx.merge_res = RES_BAD_ARG; + BA(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.merge_cpt == 0); + add_geom_ctx.merge_res = RES_MEM_ERR; + ME(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.merge_cpt == 0); + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == 0); /* merge failed but with a no-conflict status */ + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* Successful add geometry without merge callback */ + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, NULL, &ctx)); + CHK(add_geom_ctx.merge_cpt == 0); + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* Successful add geometry with merge callback */ + add_geom_ctx.merge_res = RES_OK; + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.merge_cpt == ntriangles); + add_geom_ctx.merge_cpt = 0; + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == 0); /* merge failed but with a no-conflict status */ + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* Geometry with media information on both sides */ + ctx.front_media = medium0; + ctx.back_media = medium1; + + /* Clear geometry */ + SG3(geometry_ref_put(geom)); + OK(sg3_geometry_create(dev, &geom)); + + /* Successful add geometry with add callback */ + add_geom_ctx.add_res = RES_OK; + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.add_cpt == ntriangles); + CHK(add_geom_ctx.merge_cpt == 0); + add_geom_ctx.add_cpt = 0; + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == 0); /* media where defined */ + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == ntriangles); /* interfaces where undefined */ + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* Clear geometry */ + SG3(geometry_ref_put(geom)); + OK(sg3_geometry_create(dev, &geom)); + + /* Successful add geometry with add callback and no defined properties */ + add_geom_ctx.add_res = RES_OK; + OK(sg3_geometry_add(geom, ntriangles, get_indices, NULL, nvertices, + get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.add_cpt == ntriangles); + CHK(add_geom_ctx.merge_cpt == 0); + add_geom_ctx.add_cpt = 0; + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == ntriangles); /* media where undefined */ + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == ntriangles); /* interfaces where undefined */ + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* Define interface */ + ctx.intface = intface0; + + /* Successful add geometry with merge callback and properties */ + add_geom_ctx.merge_res = RES_OK; + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.merge_cpt == ntriangles); + add_geom_ctx.merge_cpt = 0; + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == 0); /* media where defined */ + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == 0); /* interfaces where defined */ + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* Geometry with incompatible media information on both sides */ + ctx.front_media = medium1; + ctx.back_media = medium0; + + /* Add geometry without merge callback and conflicts */ + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, NULL, &ctx)); + CHK(add_geom_ctx.merge_cpt == 0); + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == 0); /* media where defined */ + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == 0); /* interfaces where defined */ + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* Incompatible interface */ + ctx.intface = intface1; + + /* Successful add geometry with merge callback */ + add_geom_ctx.merge_res = RES_OK; + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.merge_cpt == ntriangles); + add_geom_ctx.merge_cpt = 0; + OK(sg3_geometry_get_unique_vertices_count(geom, &count)); + CHK(count == nvertices); + OK(sg3_geometry_get_unique_triangles_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_triangle_with_undefined_side_count(geom, &count)); + CHK(count == 0); /* media where defined */ + OK(sg3_geometry_get_triangle_with_undefined_interface_count(geom, &count)); + CHK(count == 0); /* interfaces where defined */ + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == ntriangles); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + /* Clear geometry */ + SG3(geometry_ref_put(geom)); + OK(sg3_geometry_create(dev, &geom)); + + /* Successful add geometry with merge callback */ + OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, + nvertices, get_position, add_trg, merge_trg, &ctx)); + OK(sg3_geometry_get_merge_conflict_count(geom, &count)); + CHK(count == 0); + + OK(sg3_geometry_validate_properties(geom, validate, NULL)); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + OK(sg3_geometry_dump_as_obj(geom, stdout, SG3_ALL_TRIANGLES)); + + OK(sg3_geometry_validate_properties(geom, validate, NULL)); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == 0); + + OK(sg3_geometry_validate_properties(geom, validate2, NULL)); + OK(sg3_geometry_get_properties_conflict_count(geom, &count)); + CHK(count == ntriangles / 2); + + OK(sg3_geometry_ref_put(geom)); + OK(sg3_device_ref_put(dev)); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHK(mem_allocated_size() == 0); + return 0; +} diff --git a/src/test_sg3_report.c b/src/test_sg3_report.c @@ -56,80 +56,14 @@ main(int argc, char** argv) struct sg3_device* dev; struct sg3_report* report; struct sg3_geometry* geometry; - unsigned count, i; + unsigned count; struct context ctx; (void)argc, (void)argv; + - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(sg3_device_create(NULL, &allocator, 1, &dev)); - BA(sg3_report_create(NULL, &report)); - BA(sg3_report_create(dev, NULL)); - OK(sg3_report_create(dev, &report)); - - BA(sg3_report_ref_get(NULL)); - OK(sg3_report_ref_get(report)); - BA(sg3_report_ref_put(NULL)); - OK(sg3_report_ref_put(report)); - - BA(sg3_report_validate_properties(NULL, NULL, NULL)); - BA(sg3_report_validate_properties(report, NULL, NULL)); - BA(sg3_report_validate_properties(NULL, validate, NULL)); - /* Not associated to a geometry */ - BA(sg3_report_validate_properties(report, validate, NULL)); - - BA(sg3_report_get_unique_vertices_count(NULL, NULL)); - BA(sg3_report_get_unique_vertices_count(report, NULL)); - BA(sg3_report_get_unique_vertices_count(NULL, &count)); - /* Not associated to a geometry */ - BA(sg3_report_get_unique_vertices_count(report, &count)); - - BA(sg3_report_get_unique_triangles_count(NULL, NULL)); - BA(sg3_report_get_unique_triangles_count(report, NULL)); - BA(sg3_report_get_unique_triangles_count(NULL, &count)); - /* Not associated to a geometry */ - BA(sg3_report_get_unique_triangles_count(report, &count)); - - BA(sg3_report_get_triangle_with_undefined_side_count(NULL, NULL)); - BA(sg3_report_get_triangle_with_undefined_side_count(report, NULL)); - BA(sg3_report_get_triangle_with_undefined_side_count(NULL, &count)); - /* Not associated to a geometry */ - BA(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - - BA(sg3_report_get_triangle_with_undefined_interface_count(NULL, NULL)); - BA(sg3_report_get_triangle_with_undefined_interface_count(report, NULL)); - BA(sg3_report_get_triangle_with_undefined_interface_count(NULL, &count)); - /* Not associated to a geometry */ - BA(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - - BA(sg3_report_get_merge_conflict_count(NULL, NULL)); - BA(sg3_report_get_merge_conflict_count(report, NULL)); - BA(sg3_report_get_merge_conflict_count(NULL, &count)); - /* Not associated to a geometry */ - BA(sg3_report_get_merge_conflict_count(report, &count)); - - BA(sg3_report_get_properties_conflict_count(NULL, NULL)); - BA(sg3_report_get_properties_conflict_count(report, NULL)); - BA(sg3_report_get_properties_conflict_count(NULL, &count)); - /* Not associated to a geometry */ - BA(sg3_report_get_properties_conflict_count(report, &count)); - - BA(sg3_report_dump_as_obj(NULL, NULL, 0)); - BA(sg3_report_dump_as_obj(report, NULL, 0)); - BA(sg3_report_dump_as_obj(NULL, stdout, 0)); - BA(sg3_report_dump_as_obj(NULL, NULL, SG3_ALL_TRIANGLES)); - BA(sg3_report_dump_as_obj(report, stdout, 0)); - BA(sg3_report_dump_as_obj(report, NULL, SG3_ALL_TRIANGLES)); - BA(sg3_report_dump_as_obj(NULL, stdout, SG3_ALL_TRIANGLES)); - /* Not associated to a geometry */ - BA(sg3_report_dump_as_obj(report, stdout, SG3_ALL_TRIANGLES)); - BA(sg3_report_dump_as_C_code(report, stdout, "test")); - OK(sg3_geometry_create(dev, report, &geometry)); - OK(sg3_report_validate_properties(report, validate, NULL)); - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == 0); OK(sg3_report_get_unique_triangles_count(report, &count)); CHK(count == 0); OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); @@ -161,8 +95,8 @@ main(int argc, char** argv) OK(sg3_report_dump_as_C_code(report, stdout, "test")); /* Conflicts with merge_trg callback */ - /* BA because merge_trg detects conflicts */ - BA(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, + /* BA because merge_trg detects conflic */ + OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, nvertices, get_position, NULL, merge_trg, &ctx)); OK(sg3_report_get_merge_conflict_count(report, &count)); /* Due to merge_trg internals, all but the first triangle report conflict */ @@ -181,9 +115,8 @@ main(int argc, char** argv) BA(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, nvertices, get_position, NULL, NULL, &ctx)); OK(sg3_report_get_merge_conflict_count(report, &count)); - FOR_EACH(i, 0, ntriangles) - if(medium1_front0[i] != medium0[i]) count--; /* Count conflicts */ - CHK(count == 0); + /* Without merge_trg add stops at the first conflict */ + CHK(count == 1); BA(sg3_report_dump_as_C_code(report, stdout, "test")); OK(sg3_geometry_ref_put(geometry)); OK(sg3_report_ref_put(report)); diff --git a/src/test_sg3_report_2.c b/src/test_sg3_report_2.c @@ -1,412 +0,0 @@ -/* Copyright (C) 2016-2019 |Meso|Star> (contact@meso-star.com) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#include "star-geometry.h" -#include "test_sg3_utils.h" - -#include <rsys/double3.h> - -#include <stdio.h> - - /* Manage add_geometry behaviour */ -struct add_geom_ctx { - unsigned add_cpt, merge_cpt; - res_T add_res, merge_res; -}; - -static res_T -add_trg - (const unsigned global_id, - const unsigned iseg, - void* context) -{ - struct context* ctx = context; - struct add_geom_ctx* add_geom_ctx; - ASSERT(ctx); (void)global_id; (void)iseg; - add_geom_ctx = ctx->custom; - if(add_geom_ctx->add_res == RES_OK) ++add_geom_ctx->add_cpt; - return add_geom_ctx->add_res; -} - -static res_T -merge_trg - (const unsigned global_id, - const unsigned itri, - const int reversed_triangle, - unsigned triangle_properties[3], - const unsigned merged_properties[3], - void* context, - int* merge_conflict) -{ - struct context* ctx = context; - struct add_geom_ctx* add_geom_ctx; - int i; - ASSERT(ctx && triangle_properties && merged_properties && merge_conflict); - (void)global_id; (void)itri; (void)reversed_triangle; - (void)triangle_properties; (void)merged_properties; - add_geom_ctx = ctx->custom; - if(add_geom_ctx->merge_res == RES_OK) ++add_geom_ctx->merge_cpt; - FOR_EACH(i, 0, 3) - if(!sg3_compatible_property(triangle_properties[i], merged_properties[i])) - *merge_conflict = 1; - return add_geom_ctx->merge_res; -} - -static res_T -validate - (const unsigned itri, - const unsigned properties[3], - void* context, - int* properties_conflict) -{ - (void)itri; (void)properties; (void)context; - *properties_conflict = 0; - return RES_OK; -} - -static res_T -validate2 - (const unsigned itri, - const unsigned properties[3], - void* context, - int* properties_conflict) -{ - (void)itri; (void)properties; (void)context; - *properties_conflict = (itri % 2 == 0) ? 0 : itri; - return RES_OK; -} - -int -main(int argc, char** argv) -{ - struct mem_allocator allocator; - struct sg3_device* dev; - struct sg3_report* report; - struct sg3_geometry* geometry; - struct context ctx; - struct add_geom_ctx add_geom_ctx; - unsigned property[12]; - unsigned i; - const unsigned property_count = sizeof(property) / sizeof(*property); - unsigned count; - (void)argc, (void)argv; - - OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); - OK(sg3_device_create(NULL, &allocator, 1, &dev)); - OK(sg3_report_create(dev, &report)); - OK(sg3_geometry_create(dev, report, &geometry)); - - /* A 3D cube. - * 2 enclosures (inside, outside) sharing the same triangles, - * but opposite sides */ - ctx.positions = cube_vertices; - ctx.indices = cube_indices; - ctx.scale = 1; - d3(ctx.offset, 0, 0, 0); - ctx.custom = &add_geom_ctx; - - add_geom_ctx.add_cpt = add_geom_ctx.merge_cpt = 0; - add_geom_ctx.add_res = add_geom_ctx.merge_res = RES_OK; - - /* Geometry with no media information on both sides */ - for(i = 0; i < property_count; i++) property[i] = SG3_UNDEFINED_PROPERTY; - ctx.front_media = property; - ctx.back_media = property; - ctx.intface = property; - - /* If add fails, add geometry fails the same way */ - add_geom_ctx.add_res = RES_BAD_ARG; - BA(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - CHK(add_geom_ctx.add_cpt == 0); - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == 0); - add_geom_ctx.add_res = RES_MEM_ERR; - ME(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - CHK(add_geom_ctx.add_cpt == 0); - CHK(count == 0); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == 0); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == 0); - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == 0); - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == 0); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* Successful add geometry with add callback */ - add_geom_ctx.add_res = RES_OK; - OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - CHK(add_geom_ctx.add_cpt == ntriangles); - CHK(add_geom_ctx.merge_cpt == 0); - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == 0); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* Clear geometry */ - SG3(geometry_ref_put(geometry)); - /* Report has been already associated*/ - BA(sg3_geometry_create(dev, report, &geometry)); - OK(sg3_report_ref_put(report)); - OK(sg3_report_create(dev, &report)); - OK(sg3_geometry_create(dev, report, &geometry)); - - /* Successful add geometry without add callback */ - add_geom_ctx.add_cpt = 0; - OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, NULL, merge_trg, &ctx)); - CHK(add_geom_ctx.add_cpt == 0); - CHK(add_geom_ctx.merge_cpt == 0); - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == 0); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* If merge fails, add geometry fails the same way */ - add_geom_ctx.merge_res = RES_BAD_ARG; - BA(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - CHK(add_geom_ctx.merge_cpt == 0); - add_geom_ctx.merge_res = RES_MEM_ERR; - ME(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - CHK(add_geom_ctx.merge_cpt == 0); - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == 0); /* merge failed but with a no-conflict status */ - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* Successful add geometry without merge callback */ - OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, NULL, &ctx)); - CHK(add_geom_ctx.merge_cpt == 0); - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == 0); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* Successful add geometry with merge callback */ - add_geom_ctx.merge_res = RES_OK; - OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - CHK(add_geom_ctx.merge_cpt == ntriangles); - add_geom_ctx.merge_cpt = 0; - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == 0); /* merge failed but with a no-conflict status */ - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* Geometry with media information on both sides */ - ctx.front_media = medium0; - ctx.back_media = medium1; - - /* Clear geometry */ - SG3(geometry_ref_put(geometry)); - OK(sg3_report_ref_put(report)); - OK(sg3_report_create(dev, &report)); - OK(sg3_geometry_create(dev, report, &geometry)); - - /* Successful add geometry with add callback */ - add_geom_ctx.add_res = RES_OK; - OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - CHK(add_geom_ctx.add_cpt == ntriangles); - CHK(add_geom_ctx.merge_cpt == 0); - add_geom_ctx.add_cpt = 0; - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == 0); /* media where defined */ - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == ntriangles); /* interfaces where undefined */ - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == 0); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* Clear geometry */ - SG3(geometry_ref_put(geometry)); - OK(sg3_report_ref_put(report)); - OK(sg3_report_create(dev, &report)); - OK(sg3_geometry_create(dev, report, &geometry)); - - /* Successful add geometry with add callback and no defined properties */ - add_geom_ctx.add_res = RES_OK; - OK(sg3_geometry_add(geometry, ntriangles, get_indices, NULL, nvertices, - get_position, add_trg, merge_trg, &ctx)); - CHK(add_geom_ctx.add_cpt == ntriangles); - CHK(add_geom_ctx.merge_cpt == 0); - add_geom_ctx.add_cpt = 0; - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == ntriangles); /* media where undefined */ - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == ntriangles); /* interfaces where undefined */ - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == 0); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* Define interface */ - ctx.intface = intface0; - - /* Successful add geometry with merge callback and properties */ - add_geom_ctx.merge_res = RES_OK; - OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - CHK(add_geom_ctx.merge_cpt == ntriangles); - add_geom_ctx.merge_cpt = 0; - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == 0); /* media where defined */ - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == 0); /* interfaces where defined */ - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == 0); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* Geometry with incompatible media information on both sides */ - ctx.front_media = medium1; - ctx.back_media = medium0; - - /* Unsuccessful add geometry without merge callback */ - BA(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, NULL, &ctx)); - CHK(add_geom_ctx.merge_cpt == 0); - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == 0); /* media where defined */ - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == 0); /* interfaces where defined */ - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* Incompatible interface */ - ctx.intface = intface1; - - /* Successful add geometry with merge callback */ - add_geom_ctx.merge_res = RES_OK; - OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - CHK(add_geom_ctx.merge_cpt == ntriangles); - add_geom_ctx.merge_cpt = 0; - OK(sg3_report_get_unique_vertices_count(report, &count)); - CHK(count == nvertices); - OK(sg3_report_get_unique_triangles_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_triangle_with_undefined_side_count(report, &count)); - CHK(count == 0); /* media where defined */ - OK(sg3_report_get_triangle_with_undefined_interface_count(report, &count)); - CHK(count == 0); /* interfaces where defined */ - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == ntriangles); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - /* Clear geometry */ - SG3(geometry_ref_put(geometry)); - OK(sg3_report_ref_put(report)); - OK(sg3_report_create(dev, &report)); - OK(sg3_geometry_create(dev, report, &geometry)); - - /* Successful add geometry with merge callback */ - OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - OK(sg3_report_get_merge_conflict_count(report, &count)); - CHK(count == 0); - - OK(sg3_report_validate_properties(report, validate, NULL)); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - OK(sg3_report_dump_as_obj(report, stdout, SG3_ALL_TRIANGLES)); - - OK(sg3_report_validate_properties(report, validate, NULL)); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == 0); - - OK(sg3_report_validate_properties(report, validate2, NULL)); - OK(sg3_report_get_properties_conflict_count(report, &count)); - CHK(count == ntriangles / 2); - - OK(sg3_geometry_ref_put(geometry)); - OK(sg3_report_ref_put(report)); - OK(sg3_device_ref_put(dev)); - - check_memory_allocator(&allocator); - mem_shutdown_proxy_allocator(&allocator); - CHK(mem_allocated_size() == 0); - return 0; -}