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 d3f57d495c3a457ae1e6020310556c742f9ef229
parent 5366b16fb09731a902a2a9f1c3b0b340f5513025
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Fri, 20 Dec 2019 10:33:06 +0100

Continue working on API

The bigger change is that callbacks for sg3_geometry_add are now grouped in a struct

Diffstat:
Msrc/sg3.h | 120+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/sg3_geometry.c | 116++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
Msrc/test_sg3_geometry.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Msrc/test_sg3_geometry_2.c | 67++++++++++++++++++++++++++++++++-----------------------------------
Msrc/test_sg3_utils.h | 23+++++++++++++++++++----
5 files changed, 281 insertions(+), 142 deletions(-)

diff --git a/src/sg3.h b/src/sg3.h @@ -75,6 +75,14 @@ enum sg3_dump_content { }; /******************************************************************************* + * A type to list the different qualifiers of C code variable output. + ******************************************************************************/ +enum sg3_cdump_qualifiers { + SG3_CDUMP_CONST = BIT(0), + SG3_CDUMP_STATIC = BIT(1) +}; + +/******************************************************************************* * The value that should be used for properties attached to triangles (i.e. * media or interface) when not defined. * SG3_UNDEFINED_PROPERTY can be used for a property that has already been @@ -82,6 +90,56 @@ enum sg3_dump_content { ******************************************************************************/ #define SG3_UNDEFINED_PROPERTY UINT_MAX + /******************************************************************************* + * A type to hold callbacks for sg3_geometry_add. + ******************************************************************************/ +struct sg3_geometry_add_callbacks { + /* User function that provides vertices ids for added triangles */ + void(*get_indices) + (const unsigned itri, unsigned ids[3], void* context); + /* User function that provides properties for added triangles */ + void(*get_properties) /* Can be NULL <=> SG3_UNDEFINED_PROPERTY used */ + (const unsigned itri, + /* It is OK to have side and interface properties sharing the same IDs, + * i.e. side and interface IDs both starting from 0 */ + unsigned properties[SG3_PROP_TYPES_COUNT__], + void* context); + /* User function that provides coordinates for added vertices */ + void(*get_position) + (const unsigned ivert, double pos[3], void* context); + /* Called for each new triangle so that the client app can manage its own + * triangle data/properties/attributes. + * If return is not RES_OK, sg3_geometry_add stops immediately and returns + * whatever value add_triangle returned. */ + res_T(*add_triangle) /* Can be NULL */ + (const unsigned global_id, const unsigned itri, void* context); + /* Called if the 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, 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_status 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. + * 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, + unsigned triangle_properties[SG3_PROP_TYPES_COUNT__], + const unsigned merged_properties[SG3_PROP_TYPES_COUNT__], + void* context, + int* merge_conflict_status); + /* Called if the itri_th triangle is degenerated. According to the value + * of abort, sg3_geometry_add will stop and return RES_BAD_ARG or continue + * silently. */ + res_T(*degenerated_triangle) /* Can be NULL <=> Drop triangle, don't abort */ + (const unsigned itri, void* context, int* abort); +}; +#define SG3_ADD_CALLBACKS_NULL__ { NULL, NULL, NULL, NULL, NULL, NULL } + BEGIN_DECLS /******************************************************************************* @@ -128,6 +186,14 @@ sg3_geometry_create (struct sg3_device* dev, struct sg3_geometry** geometry); +/* Reserve memory according to anticipated geometry size. */ +SG3_API res_T +sg3_geometry_reserve + (struct sg3_geometry* geometry, + const unsigned vertices_count, + const unsigned triangles_count, + const unsigned properties_count); + /* Add a new set of 3D vertices and triangles to the geometry; triangles can * be decorated with 3 properties (front and back media and interface) that can * be let undefined using the SG3_UNDEFINED_PROPERTY special value. @@ -159,46 +225,9 @@ sg3_geometry_create SG3_API res_T sg3_geometry_add (struct sg3_geometry* geometry, - /* Number of added triangles */ const unsigned triangles_count, - /* User function that provides vertices ids for added triangles */ - void(*indices)(const unsigned itri, unsigned ids[3], void* context), - /* User function that provides properties for added triangles */ - void(*properties) /* Can be NULL <=> SG3_UNDEFINED_PROPERTY used */ - (const unsigned itri, - /* It is OK to have side and interface properties sharing the same IDs, - * i.e. side and interface IDs both starting from 0 */ - unsigned properties[SG3_PROP_TYPES_COUNT__], - void* context), - /* Number of added vertices */ const unsigned vertices_count, - /* User function that provides coordinates for added vertices */ - void(*position)(const unsigned ivert, double pos[3], void* context), - /* Called for each new triangle so that the client app can manage its own - * triangle data/properties/attributes. - * If return is not RES_OK, sg3_geometry_add stops immediately and returns - * whatever value add_triangle returned. */ - res_T(*add_triangle) /* Can be NULL */ - (const unsigned global_id, const unsigned itri, void* context), - /* Called if the 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, 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_status 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. - * 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, - unsigned triangle_properties[SG3_PROP_TYPES_COUNT__], - const unsigned merged_properties[SG3_PROP_TYPES_COUNT__], - void* context, - int* merge_conflict_status), + const struct sg3_geometry_add_callbacks* callbacks, void* context); /* Can be NULL */ /* Apply a validation callback on each triangle included in this geometry that @@ -322,15 +351,20 @@ sg3_geometry_dump_as_vtk /* Dump the geometry as C code. * The geometry cannot be empty and must be conflict-free. * The C code defines the 3 variables: - * - const double <name_prefix>_vertices[<N1>] = { .... }; - * - const unsigned <name_prefix>_triangles[<N2>] = { .... }; - * - const unsigned <name_prefix>_properties[<N2>] = { .... }; -* Where <N1> is 3 * vertices_count and <N2> is 3 * triangles_count. */ + * - [static] [const] double <name_prefix>_vertices[<N1>] = { .... }; + * - [static] [const] unsigned <name_prefix>_vertices_count = N1; + * - [static] [const] unsigned <name_prefix>_triangles[<N2>] = { .... }; + * - [static] [const] unsigned <name_prefix>_triangles_count = N2; + * - [static] [const] unsigned <name_prefix>_properties[<N2>] = { .... }; + * Where <N1> is 3 * vertices_count and <N2> is 3 * triangles_count. + * The two qualifiers static and const are output or not according to flags; + * flags must be ORed enum sg3_cdump_qualifiers values. */ SG3_API res_T sg3_geometry_dump_as_C_code (const struct sg3_geometry* geometry, FILE* stream, - const char* name_prefix); /* Can be NULL or "" */ + const char* name_prefix, /* Can be NULL or "" */ + const int flags); SG3_API res_T sg3_geometry_ref_get diff --git a/src/sg3_geometry.c b/src/sg3_geometry.c @@ -331,17 +331,34 @@ error: } res_T +sg3_geometry_reserve + (struct sg3_geometry* geom, + const unsigned vertices_count, + const unsigned triangles_count, + const unsigned properties_count) +{ + res_T res = RES_OK; + if(!geom) return RES_BAD_ARG; + + ERR(darray_triangle_reserve(&geom->unique_triangles, triangles_count)); + ERR(darray_vertex_reserve(&geom->unique_vertices, vertices_count)); + ERR(htable_vrtx_reserve(&geom->unique_vertices_ids, vertices_count)); + ERR(htable_trg_reserve(&geom->unique_triangles_ids, triangles_count)); + ERR(darray_trg_descriptions_reserve(&geom->trg_descriptions, + properties_count)); + +end: + return res; +error: + goto end; +} + +res_T sg3_geometry_add (struct sg3_geometry* geom, const unsigned ntris, - void(*indices)(const unsigned, unsigned*, void*), - void(*properties)(const unsigned, unsigned*, void*), /* Can be NULL */ const unsigned nverts, - void(*position)(const unsigned, double*, void*), - res_T(*add_trg)(const unsigned, const unsigned, void*), /* Can be NULL */ - res_T(*merge_trg) /* Can be NULL */ - (const unsigned, const unsigned, const int, unsigned*, const unsigned*, - void*, int*), + const struct sg3_geometry_add_callbacks* callbacks, void* ctx) /* Can be NULL */ { res_T res = RES_OK; @@ -354,8 +371,10 @@ sg3_geometry_add struct triangle* trg; /* Tmp table of IDs to record unique IDs of the currently added vertices */ struct darray_uint unique_vertice_ids; + int unique_vertice_ids_initialized = 0; - if(!geom || !indices || !position) { + if(!geom || !callbacks || !callbacks->get_indices || !callbacks->get_position) + { res = RES_BAD_ARG; goto error; } @@ -366,6 +385,7 @@ sg3_geometry_add /* Make room for new geometry; suppose no more duplicates */ darray_uint_init(alloc, &unique_vertice_ids); + unique_vertice_ids_initialized = 1; ERR(darray_uint_reserve(&unique_vertice_ids, nverts)); ERR(darray_vertex_reserve(&geom->unique_vertices, nuverts + nverts)); ERR(darray_triangle_reserve(&geom->unique_triangles, nutris + ntris)); @@ -378,7 +398,7 @@ sg3_geometry_add unsigned* p_vrtx; struct vertex tmp; unsigned unique_v; - position(i, tmp.coord, ctx); + callbacks->get_position(i, tmp.coord, ctx); p_vrtx = htable_vrtx_find(&geom->unique_vertices_ids, &tmp); if(p_vrtx) { /* Duplicate vertex */ @@ -408,7 +428,7 @@ sg3_geometry_add /* Triangle index in user world regardless of deduplication. */ tmp.global_id = (geom->triangle_count_including_duplicates + i); - indices(i, tmp.vertex_ids, ctx); + callbacks->get_indices(i, tmp.vertex_ids, ctx); FOR_EACH(j, 0, 3) { if(tmp.vertex_ids[j] >= nverts) { res = RES_BAD_ARG; @@ -422,13 +442,23 @@ sg3_geometry_add || tmp.vertex_ids[0] == tmp.vertex_ids[2] || tmp.vertex_ids[1] == tmp.vertex_ids[2]) { - log_err(geom->dev, "%s: triangle %u is degenerate.\n", - FUNC_NAME, tmp.global_id); - res = RES_BAD_ARG; - goto error; + int abort = 0; + if(callbacks->degenerated_triangle) { + /* Let the client app rule. */ + ERR(callbacks->degenerated_triangle(i, ctx, &abort)); + } else { + log_warn(geom->dev, "%s: triangle %u is degenerated.\n", + FUNC_NAME, i); + } + if(abort) { + res = RES_BAD_ARG; + goto error; + } + else continue; } /* Get properties */ - if(properties) properties(i, tmp.properties, ctx); + if(callbacks->get_properties) + callbacks->get_properties(i, tmp.properties, ctx); /* Find duplicate triangles */ reversed = trg_make_key(&trg_key, tmp.vertex_ids); p_trg = htable_trg_find(&geom->unique_triangles_ids, &trg_key); @@ -446,10 +476,11 @@ sg3_geometry_add if(!same) SWAP(unsigned, tmp.properties[SG3_FRONT], tmp.properties[SG3_BACK]); already_conflict = trg_descriptions[i].merge_conflict; - if(merge_trg) { + if(callbacks->merge_triangle) { /* Let the client app rule. */ - ERR(merge_trg(trg[*p_trg].global_id, i, same, trg[*p_trg].properties, - tmp.properties, ctx, &trg_descriptions[i].merge_conflict)); + ERR(callbacks->merge_triangle(trg[*p_trg].global_id, i, same, + trg[*p_trg].properties, 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], @@ -475,8 +506,8 @@ sg3_geometry_add /* New triangle */ ASSERT(nutris + actual_nutris < UINT_MAX); unique_id = (unsigned)(nutris + actual_nutris); - if(add_trg) - ERR(add_trg(tmp.global_id, i, ctx)); + if(callbacks->add_triangle) + ERR(callbacks->add_triangle(tmp.global_id, i, ctx)); ERR(geometry_enlarge_trg_descriptions(geom, 1 + unique_id)); trg_descriptions = darray_trg_descriptions_data_get(&geom->trg_descriptions); @@ -502,10 +533,12 @@ sg3_geometry_add ASSERT(nutris + actual_nutris == htable_trg_size_get(&geom->unique_triangles_ids)); exit: - geom->set_id++; - darray_uint_release(&unique_vertice_ids); - /* Update sizes */ - geom->triangle_count_including_duplicates += actual_ntris; + if(geom) { + geom->set_id++; + geom->triangle_count_including_duplicates += actual_ntris; + } + if(unique_vertice_ids_initialized) + darray_uint_release(&unique_vertice_ids); return res; error: goto exit; @@ -904,15 +937,18 @@ exit: error: goto exit; } + res_T sg3_geometry_dump_as_C_code (const struct sg3_geometry* geom, FILE* stream, - const char* name_prefix) + const char* name_prefix, + const int flags) { res_T res = RES_OK; const struct vertex* vertices; const struct triangle* triangles; + const char* qualifiers; size_t vsz, tsz, i; if(!geom || !stream || geom->merge_conflict_count @@ -934,7 +970,10 @@ sg3_geometry_dump_as_C_code } if(!name_prefix) name_prefix = ""; /* Headers */ - fprintf(stream, "/* Dump of star-geometry. */\n"); + if(name_prefix && name_prefix[0] != '\0') + fprintf(stream, "/* Dump of star-geometry '%s'. */\n", name_prefix); + else + fprintf(stream, "/* Dump of star-geometry. */\n"); vsz = darray_vertex_size_get(&geom->unique_vertices); ASSERT(3 * vsz <= UINT_MAX); tsz = darray_triangle_size_get(&geom->unique_triangles); @@ -949,11 +988,18 @@ sg3_geometry_dump_as_C_code } /* Dump vertices */ + if(flags & SG3_CDUMP_CONST && flags & SG3_CDUMP_STATIC) + qualifiers = "static const "; + else if(flags & SG3_CDUMP_CONST) + qualifiers = "const "; + else if(flags & SG3_CDUMP_STATIC) + qualifiers = "static "; + else qualifiers = ""; vertices = darray_vertex_cdata_get(&geom->unique_vertices); fprintf(stream, - "const double %s_vertices[%u] =\n" + "%sdouble %s_vertices[%u] =\n" " {\n", - name_prefix, (unsigned)(3 * vsz)); + qualifiers, name_prefix, (unsigned)(3 * vsz)); FOR_EACH(i, 0, vsz - 1) fprintf(stream, " %f, %f, %f,\n", SPLIT3(vertices[i].coord)); @@ -961,13 +1007,15 @@ sg3_geometry_dump_as_C_code " %f, %f, %f\n", SPLIT3(vertices[vsz - 1].coord)); fprintf(stream, "};\n"); + fprintf(stream, "%sunsigned %s_vertices_count = %u;\n", + qualifiers, name_prefix, (unsigned)vsz); /* Dump triangles */ triangles = darray_triangle_cdata_get(&geom->unique_triangles); fprintf(stream, - "const unsigned %s_triangles[%u] =\n" + "%sunsigned %s_triangles[%u] =\n" " {\n", - name_prefix, (unsigned)(3 * tsz)); + qualifiers, name_prefix, (unsigned)(3 * tsz)); FOR_EACH(i, 0, tsz - 1) fprintf(stream, " %u, %u, %u,\n", SPLIT3(triangles[i].vertex_ids)); @@ -975,16 +1023,18 @@ sg3_geometry_dump_as_C_code " %u, %u, %u\n", SPLIT3(triangles[tsz - 1].vertex_ids)); fprintf(stream, "};\n"); + fprintf(stream, "%sunsigned %s_triangles_count = %u;\n", + qualifiers, name_prefix, (unsigned)tsz); /* Dump properties */ triangles = darray_triangle_cdata_get(&geom->unique_triangles); fprintf(stream, - "const unsigned %s_properties[%u] =\n" + "%sunsigned %s_properties[%u] =\n" " {\n", - name_prefix, (unsigned)(3 * tsz)); + qualifiers, name_prefix, (unsigned)(3 * tsz)); FOR_EACH(i, 0, tsz - 1) fprintf(stream, - " %u, %u, %u\n", SPLIT3(triangles[i].properties)); + " %u, %u, %u,\n", SPLIT3(triangles[i].properties)); fprintf(stream, " %u, %u, %u\n", SPLIT3(triangles[tsz - 1].properties)); fprintf(stream, diff --git a/src/test_sg3_geometry.c b/src/test_sg3_geometry.c @@ -16,8 +16,6 @@ #include "sg3.h" #include "test_sg3_utils.h" -#include <rsys/double3.h> - #include <stdio.h> static res_T @@ -42,13 +40,26 @@ merge_trg void* context, int* merge_conflict) { - ASSERT(merge_conflict); + ASSERT(triangle_properties && merged_properties && 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; } +static res_T +degenerated_triangle + (const unsigned itri, + void* context, + int* abort) +{ + struct context* ctx = context; + ASSERT(abort && ctx); + (void)itri; + *abort = *(int*)ctx->custom; + return RES_OK; +} + int main(int argc, char** argv) { @@ -57,10 +68,12 @@ main(int argc, char** argv) struct sg3_geometry* geom; double coord[3]; unsigned indices[3]; + const unsigned degenerated[3] = { 0 , 0, 0 }; unsigned properties[SG3_PROP_TYPES_COUNT__]; + struct sg3_geometry_add_callbacks callbacks = SG3_ADD_CALLBACKS_NULL__; unsigned global_id; unsigned count, i; - struct context ctx; + struct context ctx = CONTEXT_NULL__; (void)argc, (void)argv; OK(mem_init_proxy_allocator(&allocator, &mem_default_allocator)); @@ -130,34 +143,52 @@ main(int argc, char** argv) /* BA because geometry is empty */ BA(sg3_geometry_dump_as_vtk(geom, stdout)); - 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(NULL, stdout, "test")); + BA(sg3_geometry_dump_as_C_code(NULL, NULL, NULL, 0)); + BA(sg3_geometry_dump_as_C_code(geom, NULL, NULL, 0)); + BA(sg3_geometry_dump_as_C_code(NULL, stdout, NULL, 0)); + BA(sg3_geometry_dump_as_C_code(NULL, NULL, "test", 0)); + BA(sg3_geometry_dump_as_C_code(geom, NULL, "test", 0)); + BA(sg3_geometry_dump_as_C_code(NULL, stdout, "test", 0)); /* BA because geometry is empty */ - BA(sg3_geometry_dump_as_C_code(geom, stdout, NULL)); - BA(sg3_geometry_dump_as_C_code(geom, stdout, "test")); + BA(sg3_geometry_dump_as_C_code(geom, stdout, NULL, 0)); + BA(sg3_geometry_dump_as_C_code(geom, stdout, "test", 0)); + + BA(sg3_geometry_add(NULL, 0, 0, &callbacks, NULL)); + BA(sg3_geometry_add(geom, ntriangles, nvertices, NULL, NULL)); + /* Mandatory callbacks are NULL */ + callbacks.get_indices = NULL; + callbacks.get_position = get_position; + BA(sg3_geometry_add(geom, 0, 0, &callbacks, NULL)); + callbacks.get_indices = get_indices; + callbacks.get_position = NULL; + BA(sg3_geometry_add(geom, 0, 0, &callbacks, NULL)); + callbacks.get_indices = NULL; + callbacks.get_position = NULL; + BA(sg3_geometry_add(geom, 0, 0, &callbacks, NULL)); + /* Add 0 items */ + callbacks.get_indices = get_indices; + callbacks.get_position = get_position; + OK(sg3_geometry_add(geom, 0, 0, &callbacks, NULL)); /* 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)); + callbacks.get_indices = get_indices; + callbacks.get_properties = get_properties; + callbacks.get_position = get_position; + + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); OK(sg3_geometry_dump_as_obj(geom, stdout, SG3_ALL_TRIANGLES)); OK(sg3_geometry_dump_as_vtk(geom, stdout)); - OK(sg3_geometry_dump_as_C_code(geom, stdout, NULL)); - OK(sg3_geometry_dump_as_C_code(geom, stdout, "test")); + OK(sg3_geometry_dump_as_C_code(geom, stdout, NULL, 0)); + OK(sg3_geometry_dump_as_C_code(geom, stdout, "test", + SG3_CDUMP_STATIC | SG3_CDUMP_CONST)); BA(sg3_geometry_get_unique_vertex(NULL, ntriangles, NULL)); BA(sg3_geometry_get_unique_vertex(geom, ntriangles, NULL)); @@ -201,31 +232,43 @@ main(int argc, char** argv) CHK(global_id == 0); /* Conflicts with merge_trg callback */ - OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, - nvertices, get_position, NULL, merge_trg, &ctx)); + callbacks.merge_triangle = merge_trg; + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &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)); OK(sg3_geometry_dump_as_vtk(geom, stdout)); /* BA because of conflicts */ - BA(sg3_geometry_dump_as_C_code(geom, stdout, "test")); + BA(sg3_geometry_dump_as_C_code(geom, stdout, "test", SG3_CDUMP_STATIC)); OK(sg3_geometry_ref_put(geom)); /* 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)); + callbacks.merge_triangle = NULL; + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &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_add(geom, ntriangles, nvertices, &callbacks, &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)); OK(sg3_geometry_dump_as_vtk(geom, stdout)); /* BA because of conflicts */ - BA(sg3_geometry_dump_as_C_code(geom, stdout, "test")); + BA(sg3_geometry_dump_as_C_code(geom, stdout, "test", SG3_CDUMP_CONST)); + + /* Degenerated triangles */ + ctx.indices = degenerated; + /* Without callback : OK */ + OK(sg3_geometry_add(geom, 1, nvertices, &callbacks, &ctx)); + /* With callback : OK */ + callbacks.degenerated_triangle = degenerated_triangle; + ctx.custom = &i; + i = 0; + OK(sg3_geometry_add(geom, 1, nvertices, &callbacks, &ctx)); + /* With callback : KO */ + i= 1; + BA(sg3_geometry_add(geom, 1, nvertices, &callbacks, &ctx)); OK(sg3_geometry_ref_put(geom)); OK(sg3_device_ref_put(dev)); diff --git a/src/test_sg3_geometry_2.c b/src/test_sg3_geometry_2.c @@ -16,8 +16,6 @@ #include "sg3.h" #include "test_sg3_utils.h" -#include <rsys/double3.h> - #include <stdio.h> /* Manage add_geometry behaviour */ @@ -94,7 +92,8 @@ main(int argc, char** argv) struct mem_allocator allocator; struct sg3_device* dev; struct sg3_geometry* geom; - struct context ctx; + struct context ctx = CONTEXT_NULL__; + struct sg3_geometry_add_callbacks callbacks = SG3_ADD_CALLBACKS_NULL__; struct add_geom_ctx add_geom_ctx; unsigned property[12]; unsigned i; @@ -111,8 +110,6 @@ main(int argc, char** argv) * 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; @@ -124,18 +121,23 @@ main(int argc, char** argv) ctx.back_media = property; ctx.intface = property; + callbacks.get_indices = get_indices; + callbacks.get_properties = get_properties; + callbacks.get_position = get_position; + callbacks.add_triangle = add_trg; + callbacks.merge_triangle = merge_trg; + /* 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)); + + BA(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &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)); + ME(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.add_cpt == 0); CHK(count == 0); OK(sg3_geometry_get_unique_triangles_count(geom, &count)); @@ -151,8 +153,7 @@ main(int argc, char** argv) /* 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)); + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.add_cpt == ntriangles); CHK(add_geom_ctx.merge_cpt == 0); OK(sg3_geometry_get_unique_vertices_count(geom, &count)); @@ -174,8 +175,8 @@ main(int argc, char** argv) /* 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)); + callbacks.add_triangle = NULL; + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.add_cpt == 0); CHK(add_geom_ctx.merge_cpt == 0); OK(sg3_geometry_get_unique_vertices_count(geom, &count)); @@ -193,12 +194,11 @@ main(int argc, char** argv) /* 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)); + callbacks.add_triangle = add_trg; + BA(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &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)); + ME(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.merge_cpt == 0); OK(sg3_geometry_get_unique_vertices_count(geom, &count)); CHK(count == nvertices); @@ -214,8 +214,8 @@ main(int argc, char** argv) 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)); + callbacks.merge_triangle = NULL; + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.merge_cpt == 0); OK(sg3_geometry_get_unique_vertices_count(geom, &count)); CHK(count == nvertices); @@ -232,8 +232,8 @@ main(int argc, char** argv) /* 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)); + callbacks.merge_triangle = merge_trg; + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.merge_cpt == ntriangles); add_geom_ctx.merge_cpt = 0; OK(sg3_geometry_get_unique_vertices_count(geom, &count)); @@ -260,10 +260,8 @@ main(int argc, char** argv) /* Successful add geometry with add callback * First half of the triangles, then all of them */ add_geom_ctx.add_res = RES_OK; - OK(sg3_geometry_add(geom, ntriangles / 2, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); - OK(sg3_geometry_add(geom, ntriangles, get_indices, get_properties, - nvertices, get_position, add_trg, merge_trg, &ctx)); + OK(sg3_geometry_add(geom, ntriangles / 2, nvertices, &callbacks, &ctx)); + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.add_cpt == ntriangles); CHK(add_geom_ctx.merge_cpt == ntriangles / 2); add_geom_ctx.add_cpt = 0; @@ -288,8 +286,8 @@ main(int argc, char** argv) /* 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)); + callbacks.get_properties = NULL; + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.add_cpt == ntriangles); CHK(add_geom_ctx.merge_cpt == 0); add_geom_ctx.add_cpt = 0; @@ -311,8 +309,8 @@ main(int argc, char** argv) /* 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)); + callbacks.get_properties = get_properties; + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.merge_cpt == ntriangles); add_geom_ctx.merge_cpt = 0; OK(sg3_geometry_get_unique_vertices_count(geom, &count)); @@ -333,8 +331,8 @@ main(int argc, char** argv) 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)); + callbacks.merge_triangle = NULL; + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.merge_cpt == 0); OK(sg3_geometry_get_unique_vertices_count(geom, &count)); CHK(count == nvertices); @@ -354,8 +352,8 @@ main(int argc, char** argv) /* 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)); + callbacks.merge_triangle = merge_trg; + OK(sg3_geometry_add(geom, ntriangles, nvertices, &callbacks, &ctx)); CHK(add_geom_ctx.merge_cpt == ntriangles); add_geom_ctx.merge_cpt = 0; OK(sg3_geometry_get_unique_vertices_count(geom, &count)); @@ -376,8 +374,7 @@ main(int argc, char** argv) 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_add(geom, ntriangles, nvertices, &callbacks, &ctx)); OK(sg3_geometry_get_merge_conflict_count(geom, &count)); CHK(count == 0); diff --git a/src/test_sg3_utils.h b/src/test_sg3_utils.h @@ -53,6 +53,17 @@ static const double cube_vertices[8/*#vertices*/ * 3/*#coords per vertex*/] = { 1.0, 1.0, 1.0 }; static const unsigned nvertices = sizeof(cube_vertices) / sizeof(double[3]); +/* Distorded cube */ +static const double box_vertices[8/*#vertices*/ * 3/*#coords per vertex*/] = { + 0.1, 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.1, + 1.0, 0.0, 1.0, + 0.0, 1.0, 1.0, + 1.0, 1.1, 1.0 +}; /* The following array lists the indices toward the 3D vertices of each * triangle. @@ -85,7 +96,11 @@ struct context { void* custom; double offset[3]; double scale; + char reverse_vrtx, reverse_med; }; +#define CONTEXT_NULL__ {\ + NULL, NULL, NULL, NULL, NULL, NULL, {0,0,0}, 1, 0, 0\ +} static const unsigned medium0[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned medium1[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; @@ -103,8 +118,8 @@ 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[1] = ctx->indices[itri * 3 + 1]; - ids[2] = ctx->indices[itri * 3 + 2]; + 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 @@ -122,8 +137,8 @@ get_properties(const unsigned itri, unsigned medium[3], void* context) { const struct context* ctx = context; ASSERT(medium && ctx); - medium[SG3_FRONT] = ctx->front_media[itri]; - medium[SG3_BACK] = ctx->back_media[itri]; + medium[ctx->reverse_med ? SG3_BACK : SG3_FRONT] = ctx->front_media[itri]; + medium[ctx->reverse_med ? SG3_FRONT : SG3_BACK] = ctx->back_media[itri]; medium[SG3_INTFACE] = ctx->intface[itri]; }