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 0966c671e2044a5b6aa3857300ab3bb912a11606
parent 5e7f33dfc6a5ab1120f194dcd469ff659c98bc15
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Tue, 10 Dec 2019 12:36:14 +0100

Adding geometry now proceed to the end even when detecting conflicts

Diffstat:
Msrc/sg3_geometry.c | 33++++++++++++++-------------------
Msrc/star-geometry.h | 66+++++++++++++++++++++++++++---------------------------------------
Msrc/test_sg3_report.c | 13+++++++------
Msrc/test_sg3_report_2.c | 2+-
4 files changed, 49 insertions(+), 65 deletions(-)

diff --git a/src/sg3_geometry.c b/src/sg3_geometry.c @@ -185,6 +185,7 @@ 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; @@ -271,13 +272,11 @@ sg3_geometry_add reversed = trg_make_key(&trg_key, tmp.vertex_ids); p_trg = htable_trg_find(&geom->unique_triangles_ids, &trg_key); if(p_trg) { - struct triangle* upd_ptr; /* Duplicate triangle. Need to check duplicate validity */ struct unsigned3 utrg_key; int ureversed = trg_make_key(&utrg_key, trg[*p_trg].vertex_ids); int same = (reversed == ureversed); int already_conflict; - unsigned* uprop; ASSERT(trg_key_eq(&trg_key, &utrg_key)); unique_id = *p_trg; /* Use report or tmp storage for merge_conflict status */ @@ -291,34 +290,30 @@ sg3_geometry_add else p_trgd = &trgd; if(!same) SWAP(unsigned, tmp.properties[SG3_FRONT], tmp.properties[SG3_BACK]); - uprop = trg[*p_trg].properties; already_conflict = p_trgd->merge_conflict; if(merge_trg) { /* Let the client app rule. */ - ERR(merge_trg(trg[*p_trg].global_id, i, same, uprop, tmp.properties, - ctx, &p_trgd->merge_conflict)); - /* If merge_triangle returns OK add_geometry will continue regardless - * of conflicts */ + ERR(merge_trg(trg[*p_trg].global_id, i, same, trg[*p_trg].properties, + tmp.properties, ctx, &p_trgd->merge_conflict)); } else { FOR_EACH(j, 0, SG3_PROP_TYPES_COUNT__) { - if(!sg3_compatible_property(uprop[j], tmp.properties[j])) { - res = RES_BAD_ARG; + if(!sg3_compatible_property(trg[*p_trg].properties[j], + tmp.properties[j])) + { p_trgd->merge_conflict = 1; break; } } } - if(geom->report && p_trgd->merge_conflict) - if(!already_conflict) geom->report->merge_conflict_count++; - if(res != RES_OK) goto error; - /* Legit duplicate (or accepted by merge_triangle): replace undef media */ - upd_ptr = darray_triangle_data_get(&geom->v_n_t->unique_triangles) - + *p_trg; - /* Replace possible undefined media */ + if(p_trgd->merge_conflict && !already_conflict) { + if(geom->report) geom->report->merge_conflict_count++; + found_inconsistency = 1; + } + /* Replace SG3_UNDEFINED_PROPERTY properties */ FOR_EACH(j, 0, SG3_PROP_TYPES_COUNT__) { - if(upd_ptr->properties[j] == SG3_UNDEFINED_PROPERTY + if(trg[*p_trg].properties[j] == SG3_UNDEFINED_PROPERTY && tmp.properties[j] != SG3_UNDEFINED_PROPERTY) { - upd_ptr->properties[j] = tmp.properties[j]; + trg[*p_trg].properties[j] = tmp.properties[j]; if(j == SG3_FRONT || j == SG3_BACK) geom->sides_with_defined_medium_count++; } @@ -367,7 +362,7 @@ exit: darray_uint_release(&unique_vertice_ids); /* Update sizes */ geom->triangle_count_including_duplicates += actual_ntris; - return res; + return found_inconsistency ? RES_BAD_ARG : res; error: goto exit; } diff --git a/src/star-geometry.h b/src/star-geometry.h @@ -183,8 +183,8 @@ sg3_report_get_properties_conflict_count unsigned* count); /* Dump a report in the provided stream in the OBJ format. The report must have - * been associatd to a geometry or dump will end in error. - * The OBJ dump is made of vertices and triangles, without and property, that + * 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. @@ -228,43 +228,31 @@ sg3_geometry_create * be decorated with 3 properties (front and back media and interface) that can * 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. 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, the property consistency question is to be - * understood as the consistency of the different values for the same property - * across calls of sg3_geometry_add, and 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). - * Valid triangle duplicates are silently deduplicated, the first invalid - * duplicate triggers an error (sg3_geometry_add stops and returns non-RES_OK). - * The value SG3_UNDEFINED_PROPERTY that can be used to denote undefined - * properties cannot create a conflict. - * The way properties consistency is decided depends of the merge_triangle - * callback being provided or not: + * Triangles can be duplicates, but this can be ruled invalid due to property + * inconsistency. 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. + * 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 * merge_conflict int* paramater (0 for consistent; any other value for - * inconsistent, this value being recorded in the report); sg3_geometry_add - * never stops/returns an error due to merge_conflict value, but do if - * merge_triangle return is not RES_OK (see below); + * inconsistent, this value being recorded in the report); 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; the first occuring inconsistency makes - * sg3_geometry_add stop and return RES_BAD_ARG and the report records the - * merge_conflict value of 1. + * with SG3_UNDEFINED_PROPERTY; 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, regardless of deduplication); the only - * way deduplication can change a triangle is to change a property from - * SG3_UNDEFINED_PROPERTY to any defined value. - * The add_triangle and merge_triangle callbacks can be used for external - * attribute and app-data management. By returning RES_OK even though an - * inconsistency exists, these callbacks can let sg3_geometry_add process - * through the end and build a full report; in this scenario, the client code - * has to proceed according to the inconsistency despite sg3_geometry_add - * returning RES_OK. - * If any user callback returns any non-RES_OK value, sg3_geometry_add - * stops and returns the same error value. In this case the geometry is - * partially added without any possible undo, but is in a state that allows - * further calls to sg3_geometry_add. */ + * original index in user world). After consistency being computed, a final + * step consists in rewriting SG3_UNDEFINED_PROPERTY properties if the merged + * property is defined. */ SG3_API res_T sg3_geometry_add (struct sg3_geometry* geometry, @@ -288,15 +276,15 @@ sg3_geometry_add (const unsigned global_id, const unsigned itri, void* context), /* Called if the itri_th triangle of the current sg3_geometry_add is equal * to the global_id_th global triangle so that the client app can merge - * its own triangle data and rule merge validity. + * its own triangle data, rule merge validity, and possibly change the + * recorded properties. * 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 properties. - * If return is not RES_OK, sg3_geometry_add stops immediately and returns - * whatever value merge_triangle returned. */ + * triangle_properties and merged_properties contain the involved + * properties. */ res_T(*merge_triangle) /* Can be NULL */ (const unsigned global_id, const unsigned itri, const int reversed_triangle, unsigned triangle_properties[3], const unsigned merged_properties[3], diff --git a/src/test_sg3_report.c b/src/test_sg3_report.c @@ -56,10 +56,10 @@ main(int argc, char** argv) struct sg3_device* dev; struct sg3_report* report; struct sg3_geometry* geometry; - unsigned count; + 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)); @@ -161,8 +161,8 @@ main(int argc, char** argv) OK(sg3_report_dump_as_C_code(report, stdout, "test")); /* Conflicts with merge_trg callback */ - /* OK because merge_trg returns RES_OK */ - OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_properties, + /* BA because merge_trg detects conflicts */ + BA(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,8 +181,9 @@ 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)); - /* Without merge_trg add stops at the first conflict */ - CHK(count == 1); + FOR_EACH(i, 0, ntriangles) + if(medium1_front0[i] != medium0[i]) count--; /* Count conflicts */ + CHK(count == 0); 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 @@ -350,7 +350,7 @@ main(int argc, char** argv) 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 == 1); /* Without merge_trg add stops at the first conflict */ + CHK(count == ntriangles); OK(sg3_report_get_properties_conflict_count(report, &count)); CHK(count == 0);