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 e4d1fb74cbb9621d625adfed182c990f1a72c554
parent ec8bd77a3b42a4c7e397d09c7ac5f16faf327f80
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed,  4 Dec 2019 16:44:43 +0100

Improve tests

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/sg3_geometry.c | 3+--
Msrc/sg3_report.c | 179++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
Msrc/sg3_report.h | 16++++++++++++----
Msrc/star-geometry.h | 26+++++++++++++++++++++++++-
Msrc/test_sg3_geometry.c | 2--
Msrc/test_sg3_report.c | 45+++++++++++++++++++++++++++++++++------------
Asrc/test_sg3_report_2.c | 276+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/test_sg3_utils.h | 98++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
9 files changed, 595 insertions(+), 51 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -123,6 +123,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) endif() ################################################################################ diff --git a/src/sg3_geometry.c b/src/sg3_geometry.c @@ -37,7 +37,6 @@ geometry_release(ref_T* ref) sg3_report_ref_put(geometry->report); /* Don't reset geometry->report->associated!!! */ } - MEM_RM(geometry->dev->allocator, geometry); } @@ -355,7 +354,7 @@ exit: geom->set_id++; darray_uint_release(&unique_vertice_ids); /* Update sizes */ - geom->triangle_count_including_duplicates += ntris; + geom->triangle_count_including_duplicates += actual_ntris; return res; error: goto exit; diff --git a/src/sg3_report.c b/src/sg3_report.c @@ -30,7 +30,6 @@ report_release(ref_T* ref) ASSERT(ref); report = CONTAINER_OF(ref, struct sg3_report, ref); v_n_t_ref_put(report->v_n_t); - darray_accumulated_set_release(&report->accumulated_sets); darray_trg_descriptions_release(&report->trg_descriptions); MEM_RM(report->dev->allocator, report); } @@ -44,15 +43,27 @@ report_record_triangle 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; + size_t sz; int i; + char keep_prop_def[SG3_PROP_TYPES_COUNT__]; - ASSERT(report && triangle - && set_id < darray_accumulated_set_size_get(&report->accumulated_sets)); + ASSERT(report && triangle); + sz = darray_trg_descriptions_size_get(&report->trg_descriptions); + if(triangle_unique_id >= sz) { + ERR(darray_trg_descriptions_resize(&report->trg_descriptions, + 1 + triangle_unique_id)); + ASSERT(0 <= 1 + triangle_unique_id - sz + && 1 + triangle_unique_id - sz < UINT_MAX); + report->undef_side_count += (unsigned)(1 + triangle_unique_id - sz); + report->undef_intface_count += (unsigned)(1 + triangle_unique_id - sz); + } trg_d = (darray_trg_descriptions_data_get(&report->trg_descriptions) + triangle_unique_id); /* Record information */ @@ -61,14 +72,18 @@ report_record_triangle struct definition* defs; int done = 0; size_t j; - if(triangle->properties[i] == SG3_UNDEFINED_PROPERTY) continue; + 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]) { - /* Property already there without conflict; just add set_id */ + /* 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 */ @@ -77,25 +92,22 @@ report_record_triangle } } if(!done) { - /* Need to add the set_id for this value */ + /* Need to add the set_id for this property_value */ ERR(darray_uint_push_back(&defs[j].set_ids, &set_id)); done = 1; } break; } } - ASSERT(merge_conflict|| done); if(!done) { - /* This value was not listed already */ - struct definition new_def; - new_def.property_value = triangle->properties[i]; - ASSERT(merge_conflict == (darray_definition_size_get(definitions) > 0)); - darray_uint_init(report->dev->allocator, &new_def.set_ids); - ERR(darray_uint_push_back(&new_def.set_ids, &set_id)); - darray_definition_push_back(definitions, &new_def); - if(!trg_d->merge_conflict - && (darray_definition_size_get(definitions) > 1)) - { + /* 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++; @@ -103,6 +115,20 @@ report_record_triangle } } + 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->undef_side_count > 0); + report->undef_side_count--; + } + + if (!keep_prop_def[SG3_INTFACE] && trg_d->property_defined[SG3_INTFACE]) { + /* Interface is now defined */ + ASSERT(report->undef_intface_count > 0); + report->undef_intface_count--; + } + exit: return res; error: @@ -136,11 +162,15 @@ dump_partition else if(partition == SG3_MERGE_CONFLICTS) dump = trg_descriptions[i].merge_conflict; else { - ASSERT(partition == SG3_MERGE_CONFLICTS); + ASSERT(partition == SG3_PROPERTY_CONFLICTS); dump = trg_descriptions[i].properties_conflict; } if(!dump) continue; - fprintf(stream, "f %u %u %u\n", SPLIT3(triangles[i].vertex_ids)); + 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]); } } @@ -168,10 +198,11 @@ sg3_report_create goto error; } report->dev = dev; + report->undef_side_count = 0; + report->undef_intface_count = 0; report->merge_conflict_count = 0; report->properties_conflict_count = 0; report->associated = 0; - darray_accumulated_set_init(dev->allocator, &report->accumulated_sets); darray_trg_descriptions_init(dev->allocator, &report->trg_descriptions); ref_init(&report->ref); @@ -237,6 +268,96 @@ error: } 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->undef_side_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->undef_intface_count; +exit: + return res; +error: + goto exit; +} + +res_T sg3_report_get_merge_conflict_count (const struct sg3_report* report, unsigned* count) @@ -286,7 +407,7 @@ sg3_report_dump_as_obj { res_T res = RES_OK; const struct vertex* vertices; - size_t sz, i; + size_t vsz, tsz, i; if(!report || !stream || !flags || !report->associated) { if(report && !report->associated) log_err(report->dev, @@ -295,16 +416,15 @@ sg3_report_dump_as_obj res = RES_BAD_ARG; goto error; } - vertices = darray_vertex_cdata_get(&report->v_n_t->unique_vertices); /* Headers */ fprintf(stream, "# Dump of star-geometry report\n"); fprintf(stream, "# Geometry counts:\n"); - sz = darray_vertex_size_get(&report->v_n_t->unique_vertices); - ASSERT(sz <= UINT_MAX); - fprintf(stream, "# . %u vertices\n", (unsigned)0000000000); - sz = darray_triangle_size_get(&report->v_n_t->unique_triangles); - ASSERT(sz <= UINT_MAX); - fprintf(stream, "# . %u triangles\n", (unsigned)sz); + 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); @@ -313,7 +433,8 @@ sg3_report_dump_as_obj report->merge_conflict_count); /* Dump vertices */ - FOR_EACH(i, 0, sz) + 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 */ diff --git a/src/sg3_report.h b/src/sg3_report.h @@ -93,6 +93,8 @@ 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 @@ -102,9 +104,11 @@ init_trg_descriptions { int i; ASSERT(alloc && data); - FOR_EACH(i, 0, 3) - darray_definition_init(alloc, data->defs + i); + 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 @@ -117,6 +121,10 @@ copy_trg_descriptions 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: @@ -209,13 +217,13 @@ error: * Types to store reports amid sg3_accumulate_stl_file calls. ******************************************************************************/ struct sg3_report { - /* Record the name + property of accumulated sets */ - struct darray_accumulated_set accumulated_sets; /* 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 undef_side_count; + unsigned undef_intface_count; unsigned merge_conflict_count; unsigned properties_conflict_count; int associated; diff --git a/src/star-geometry.h b/src/star-geometry.h @@ -65,7 +65,7 @@ enum sg3_property_type { }; /******************************************************************************* - * A type to list the different user properties attached to triangles. + * A type to list the different possible partitions of triangles. ******************************************************************************/ enum sg3_report_dump_content { SG3_MERGE_CONFLICTS = BIT(0), @@ -134,6 +134,30 @@ sg3_report_validate_properties 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 diff --git a/src/test_sg3_geometry.c b/src/test_sg3_geometry.c @@ -16,8 +16,6 @@ #include "star-geometry.h" #include "test_sg3_utils.h" -#include <rsys/logger.h> - int main(int argc, char** argv) { diff --git a/src/test_sg3_report.c b/src/test_sg3_report.c @@ -16,8 +16,6 @@ #include "star-geometry.h" #include "test_sg3_utils.h" -#include <rsys/logger.h> - #include <stdio.h> static res_T @@ -61,6 +59,30 @@ main(int argc, char** argv) /* 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)); @@ -85,6 +107,14 @@ main(int argc, char** argv) 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)); + 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)); @@ -92,16 +122,7 @@ main(int argc, char** argv) OK(sg3_report_dump_as_obj(report, stdout, SG3_ALL_TRIANGLES)); OK(sg3_geometry_ref_put(geometry)); OK(sg3_report_ref_put(report)); - - OK(sg3_report_create(dev, &report)); - OK(sg3_geometry_create(dev, report, &geometry)); - - - - - OK(sg3_geometry_ref_put(geometry)); - OK(sg3_report_ref_put(report)); - + OK(sg3_device_ref_put(dev)); check_memory_allocator(&allocator); diff --git a/src/test_sg3_report_2.c b/src/test_sg3_report_2.c @@ -0,0 +1,276 @@ +/* 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, + const 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; + ASSERT(ctx && triangle_properties && merged_properties && merge_conflict); + (void)global_id; (void)itri; (void)reversed_triangle; + (void)triangle_properties; (void)merged_properties; (void)merge_conflict; + add_geom_ctx = ctx->custom; + if(add_geom_ctx->merge_res == RES_OK) ++add_geom_ctx->merge_cpt; + 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; +} + +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; + ctx.reverse_vrtx = 0; + ctx.reverse_med = 0; + 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_media, + get_intface, 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_media, + get_intface, 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); + + /* Successful add geometry with add callback */ + add_geom_ctx.add_res = RES_OK; + OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_media, + get_intface, 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); + + /* 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_media, + get_intface, 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); + + /* 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_media, + get_intface, 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_media, + get_intface, 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); + + /* Successful add geometry without merge callback */ + OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_media, + get_intface, 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); + + /* Successful add geometry with merge callback */ + add_geom_ctx.merge_res = RES_OK; + OK(sg3_geometry_add(geometry, ntriangles, get_indices, get_media, + get_intface, 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); + + /* 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, NULL, 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; + + /* 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, NULL, 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; + + /* Successful add geometry with merge callback */ + add_geom_ctx.merge_res = RES_OK; + OK(sg3_geometry_add(geometry, ntriangles, get_indices, NULL, NULL, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.merge_cpt == ntriangles); + add_geom_ctx.merge_cpt = 0; + + /* Geometry with incompatible media information on both sides */ + ctx.front_media = medium1; + ctx.back_media = medium0; + + /* Unsuccessful add geometry without merge callback */ + OK(sg3_geometry_add(geometry, ntriangles, get_indices, NULL, NULL, + nvertices, get_position, add_trg, NULL, &ctx)); + CHK(add_geom_ctx.merge_cpt == 0); + + /* Successful add geometry with merge callback */ + add_geom_ctx.merge_res = RES_OK; + OK(sg3_geometry_add(geometry, ntriangles, get_indices, NULL, NULL, + nvertices, get_position, add_trg, merge_trg, &ctx)); + CHK(add_geom_ctx.merge_cpt == ntriangles); + add_geom_ctx.merge_cpt = 0; + + + + + OK(sg3_report_validate_properties(report, validate, NULL)); + count = 1; + OK(sg3_report_get_merge_conflict_count(report, &count)); + CHK(count == 0); + count = 1; + 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_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; +} diff --git a/src/test_sg3_utils.h b/src/test_sg3_utils.h @@ -21,6 +21,7 @@ #define OK(Cond) CHK((Cond) == RES_OK) #define BA(Cond) CHK((Cond) == RES_BAD_ARG) +#define ME(Cond) CHK((Cond) == RES_MEM_ERR) /******************************************************************************* @@ -30,12 +31,107 @@ static INLINE void check_memory_allocator(struct mem_allocator* allocator) { if(MEM_ALLOCATED_SIZE(allocator)) { - char dump[1024]; + char dump[80192]; MEM_DUMP(allocator, dump, sizeof(dump)); fprintf(stderr, "%s\n", dump); FATAL("Memory leaks.\n"); } } +/******************************************************************************* + * Geometry + ******************************************************************************/ +/* 3D cube */ +static const double cube_vertices[8/*#vertices*/ * 3/*#coords per vertex*/] = { + 0.0, 0.0, 0.0, + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 1.0, 1.0, 0.0, + 0.0, 0.0, 1.0, + 1.0, 0.0, 1.0, + 0.0, 1.0, 1.0, + 1.0, 1.0, 1.0 +}; +static const unsigned nvertices = sizeof(cube_vertices) / sizeof(double[3]); + +/* The following array lists the indices toward the 3D vertices of each + * triangle. + * ,2---,3 ,2----3 + * ,' | ,'/| ,'/| \ | + * 6----7' / | 6' / | \ | Y + * |', | / ,1 | / ,0---,1 | + * | ',|/,' |/,' | ,' o--X + * 4----5' 4----5' / + * Front, right Back, left and Z + * and Top faces bottom faces */ +static const unsigned +cube_indices[12/*#triangles*/ * 3/*#indices per triangle*/] = { + 0, 2, 1, 1, 2, 3, /* Front face */ + 0, 4, 2, 2, 4, 6, /* Left face*/ + 4, 5, 6, 6, 5, 7, /* Back face */ + 3, 7, 1, 1, 7, 5, /* Right face */ + 2, 6, 3, 3, 6, 7, /* Top face */ + 0, 1, 4, 4, 1, 5 /* Bottom face */ +}; +static const unsigned +ntriangles = sizeof(cube_indices) / (3 * sizeof(*cube_indices)); + +struct context { + const double* positions; + const unsigned* indices; + const unsigned* front_media; + const unsigned* back_media; + const unsigned* intface; + void* custom; + double offset[3]; + double scale; + char reverse_vrtx, reverse_med; +}; + +static const unsigned medium0[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +static const unsigned medium1[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; +static const unsigned medium2[12] = { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }; +static const unsigned medium1_3[12] = { 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1 }; +static const unsigned medium1_back0[12] = { 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 }; +static const unsigned medium1_front0[12] = { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + +static const unsigned intface0[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +static INLINE void +get_indices(const unsigned itri, unsigned ids[3], void* context) +{ + const struct context* ctx = context; + ASSERT(ids && ctx); + ids[0] = ctx->indices[itri * 3 + 0]; + ids[ctx->reverse_vrtx ? 2 : 1] = ctx->indices[itri * 3 + 1]; + ids[ctx->reverse_vrtx ? 1 : 2] = ctx->indices[itri * 3 + 2]; +} + +static INLINE void +get_position(const unsigned ivert, double pos[3], void* context) +{ + const struct context* ctx = context; + ASSERT(pos && ctx); + pos[0] = ctx->positions[ivert * 3 + 0] * ctx->scale + ctx->offset[0]; + pos[1] = ctx->positions[ivert * 3 + 1] * ctx->scale + ctx->offset[1]; + pos[2] = ctx->positions[ivert * 3 + 2] * ctx->scale + ctx->offset[2]; +} + +static INLINE void +get_media(const unsigned itri, unsigned medium[2], void* context) +{ + const struct context* ctx = context; + ASSERT(medium && ctx); + medium[ctx->reverse_med ? 1 : 0] = ctx->front_media[itri]; + medium[ctx->reverse_med ? 0 : 1] = ctx->back_media[itri]; +} + +static INLINE void +get_intface(const unsigned itri, unsigned* intface, void* context) +{ + const struct context* ctx = context; + ASSERT(intface && ctx); + *intface = ctx->intface[itri]; +} #endif /* TEST_SG3_UTILS_H */