star-gs

Literate program for a geometric sensitivity calculation
git clone git://git.meso-star.fr/star-gs.git
Log | Files | Refs | README | LICENSE

commit 3189140dad103c739756fe68006a5dbbee4fab90
parent 45f0350c938e644e3338635b6dcdad43ab641303
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Sun, 25 Apr 2021 17:53:56 +0200

Create the Star-3D sampling scene view

Diffstat:
Msrc/sgs.c | 7+++++++
Msrc/sgs.h | 5+++++
Msrc/sgs_args.c | 28+++++++++++++++-------------
Msrc/sgs_geometry.c | 192+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/sgs_geometry.h | 39++++++++++++++++++++++++---------------
Msrc/sgs_geometry_box.c | 2++
Msrc/sgs_geometry_c.h | 9+++++++--
Msrc/sgs_geometry_slope.c | 2++
8 files changed, 216 insertions(+), 68 deletions(-)

diff --git a/src/sgs.c b/src/sgs.c @@ -109,6 +109,13 @@ sgs_get_allocator(struct sgs* sgs) return sgs->allocator; } +struct s3d_device* +sgs_get_s3d_device(struct sgs* sgs) +{ + ASSERT(sgs); + return sgs->s3d; +} + void sgs_fprint_copyright(FILE* stream) { diff --git a/src/sgs.h b/src/sgs.h @@ -24,6 +24,7 @@ /* Forward declarations */ struct mem_allocator; +struct s3d_device; struct sgs; struct sgs_args; @@ -59,4 +60,8 @@ extern LOCAL_SYM struct mem_allocator* sgs_get_allocator (struct sgs* sgs); +extern LOCAL_SYM struct s3d_device* +sgs_get_s3d_device + (struct sgs* sgs); + #endif /* SGS_H */ diff --git a/src/sgs_args.c b/src/sgs_args.c @@ -97,7 +97,7 @@ static res_T parse_box_parameters(const char* str, void* ptr) { char buf[128]; - struct sgs_args_geometry* geom = ptr; + struct sgs_geometry_box_args* box = ptr; char* key; char* val; char* ctx; @@ -116,13 +116,11 @@ parse_box_parameters(const char* str, void* ptr) key = strtok_r(buf, "=", &ctx); val = strtok_r(NULL, "", &ctx); - geom->type = SGS_GEOMETRY_BOX; - if(!strcmp(key, "low")) { - res = cstr_to_list_double(val, ',', geom->args.box.lower, &len, 3); + res = cstr_to_list_double(val, ',', box->lower, &len, 3); if(res == RES_OK && len != 3) res = RES_BAD_ARG; } else if(!strcmp(key, "upp")) { - res = cstr_to_list_double(val, ',', geom->args.box.upper, &len, 3); + res = cstr_to_list_double(val, ',', box->upper, &len, 3); if(res == RES_OK && len != 3) res = RES_BAD_ARG; } else { fprintf(stderr, SGS_LOG_ERROR_PREFIX @@ -147,7 +145,7 @@ static res_T parse_slope_parameters(const char* str, void* ptr) { char buf[128]; - struct sgs_args_geometry* geom = ptr; + struct sgs_geometry_slope_args* slope = ptr; char* key; char* val; char* ctx; @@ -166,16 +164,14 @@ parse_slope_parameters(const char* str, void* ptr) key = strtok_r(buf, "=", &ctx); val = strtok_r(NULL, "", &ctx); - geom->type = SGS_GEOMETRY_SLOPE; - if(!strcmp(key, "low")) { - res = cstr_to_list_double(val, ',', geom->args.slope.lower, &len, 3); + res = cstr_to_list_double(val, ',', slope->lower, &len, 3); if(res == RES_OK && len != 3) res = RES_BAD_ARG; } else if(!strcmp(key, "upp")) { - res = cstr_to_list_double(val, ',', geom->args.slope.upper, &len, 2); + res = cstr_to_list_double(val, ',', slope->upper, &len, 2); if(res == RES_OK && len != 2) res = RES_BAD_ARG; } else if(!strcmp(key, "heights")) { - res = cstr_to_list_double(val, ',', geom->args.slope.heights, &len, 2); + res = cstr_to_list_double(val, ',', slope->heights, &len, 2); if(res == RES_OK && len != 2) res = RES_BAD_ARG; } else { fprintf(stderr, SGS_LOG_ERROR_PREFIX @@ -211,7 +207,10 @@ sgs_args_init(struct sgs_args* args, int argc, char** argv) while((opt = getopt(argc, argv, "b:dhs:t:v")) != -1) { switch(opt) { case 'b': - res = cstr_parse_list(optarg, ':', parse_box_parameters, &args->geom); + args->geom.type = SGS_GEOMETRY_BOX; + args->geom.args.box = SGS_GEOMETRY_BOX_ARGS_DEFAULT; + res = cstr_parse_list + (optarg, ':', parse_box_parameters, &args->geom.args.box); break; case 'd': args->dump_geometry = 1; break; case 'h': @@ -220,7 +219,10 @@ sgs_args_init(struct sgs_args* args, int argc, char** argv) args->quit = 1; break; case 's': - res = cstr_parse_list(optarg, ':', parse_slope_parameters, &args->geom); + args->geom.type = SGS_GEOMETRY_SLOPE; + args->geom.args.slope = SGS_GEOMETRY_SLOPE_ARGS_DEFAULT; + res = cstr_parse_list + (optarg, ':', parse_slope_parameters, &args->geom.args.slope); break; case 't': res = cstr_to_uint(optarg, &args->nthreads); diff --git a/src/sgs_geometry.c b/src/sgs_geometry.c @@ -18,33 +18,89 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "sgs.h" -#include "sgs_c.h" #include "sgs_geometry.h" #include "sgs_geometry_c.h" #include "sgs_log.h" #include <star/s3d.h> +#include <rsys/cstr.h> + +struct mesh { + const double* vertices; + const size_t* triangles; + size_t nvertices; + size_t ntriangles; +}; +static const struct mesh MESH_NULL = {NULL, NULL, 0, 0}; + /******************************************************************************* * Helper functions ******************************************************************************/ static void -geometry_get_vertex(const unsigned ivert, float pos[3], void* ctx) +mesh_get_vertex(const unsigned ivert, float pos[3], void* ctx) { - struct sgs_geometry* geom = ctx; - ASSERT(pos && ctx && ivert < geometry_get_nvertices(geom)); - pos[0] = (float)darray_double_cdata_get(&geom->verts)[ivert*3+0]; - pos[1] = (float)darray_double_cdata_get(&geom->verts)[ivert*3+1]; - pos[2] = (float)darray_double_cdata_get(&geom->verts)[ivert*3+2]; + struct mesh* mesh = ctx; + ASSERT(pos && ctx && ivert < mesh->nvertices); + pos[0] = (float)mesh->vertices[ivert*3+0]; + pos[1] = (float)mesh->vertices[ivert*3+1]; + pos[2] = (float)mesh->vertices[ivert*3+2]; } static void -geometry_get_triangle(const unsigned itri, unsigned ids[3], void* ctx) +mesh_get_triangle(const unsigned itri, unsigned ids[3], void* ctx) { - struct sgs_geometry* geom = ctx; - ASSERT(ids && ctx && itri < geometry_get_ntriangles(geom)); - ids[0] = (unsigned)darray_size_t_cdata_get(&geom->tris)[itri*3+0]; - ids[1] = (unsigned)darray_size_t_cdata_get(&geom->tris)[itri*3+1]; - ids[2] = (unsigned)darray_size_t_cdata_get(&geom->tris)[itri*3+2]; + struct mesh* mesh = ctx; + ASSERT(ids && ctx && itri < mesh->ntriangles); + ids[0] = (unsigned)mesh->triangles[itri*3+0]; + ids[1] = (unsigned)mesh->triangles[itri*3+1]; + ids[2] = (unsigned)mesh->triangles[itri*3+2]; +} + +static res_T +mesh_create_view + (struct sgs* sgs, + struct mesh* mesh, + const int view_mask, + struct s3d_scene_view** out_view) +{ + struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL; + struct s3d_shape* shape = NULL; + struct s3d_scene* scene = NULL; + struct s3d_scene_view* view = NULL; + res_T res = RES_OK; + ASSERT(sgs && mesh && out_view); + + /* Setup the Star-3D vertex data */ + vdata.usage = S3D_POSITION; + vdata.type = S3D_FLOAT3; + vdata.get = mesh_get_vertex; + + /* Setup the Star-3D ray-tracing scene */ + res = s3d_shape_create_mesh(sgs_get_s3d_device(sgs), &shape); + if(res != RES_OK) goto error; + res = s3d_mesh_setup_indexed_vertices(shape, (unsigned)mesh->ntriangles, + mesh_get_triangle, (unsigned)mesh->nvertices, &vdata, 1, mesh); + if(res != RES_OK) goto error; + res = s3d_scene_create(sgs_get_s3d_device(sgs), &scene); + if(res != RES_OK) goto error; + res = s3d_scene_attach_shape(scene, shape); + if(res != RES_OK) goto error; + + /* Create the scene view */ + res = s3d_scene_view_create(scene, view_mask, &view); + if(res != RES_OK) goto error; + +exit: + if(shape) S3D(shape_ref_put(shape)); + if(scene) S3D(scene_ref_put(scene)); + *out_view = view; + return res; +error: + if(view) { + S3D(scene_view_ref_put(view)); + view = NULL; + } + goto exit; } static void @@ -183,41 +239,101 @@ error: res_T geometry_setup_view_rt(struct sgs_geometry* geom) { - struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL; - struct s3d_shape* shape = NULL; - struct s3d_scene* scene = NULL; - unsigned ntris = 0; - unsigned nverts = 0; + struct mesh mesh = MESH_NULL; res_T res = RES_OK; ASSERT(geom); - nverts = (unsigned)geometry_get_nvertices(geom); - ntris = (unsigned)geometry_get_ntriangles(geom); + /* Clean up an eventual previous scene view */ + if(geom->view_rt) { + S3D(scene_view_ref_put(geom->view_rt)); + geom->view_rt = NULL; + } - /* Setup the Star-3D vertex data */ - vdata.usage = S3D_POSITION; - vdata.type = S3D_FLOAT3; - vdata.get = geometry_get_vertex; + /* Setup the mesh used during the ray-tracing */ + mesh.vertices = darray_double_cdata_get(&geom->verts); + mesh.triangles = darray_size_t_cdata_get(&geom->tris); + mesh.nvertices = darray_double_size_get(&geom->verts)/3/*#coords per vertex*/; + mesh.ntriangles = darray_size_t_size_get(&geom->tris)/3/*#ids per triangle*/; - /* Setup the Star-3D ray-tracing scene */ - res = s3d_shape_create_mesh(geom->sgs->s3d, &shape); - if(res != RES_OK) goto error; - res = s3d_mesh_setup_indexed_vertices - (shape, ntris, geometry_get_triangle, nverts, &vdata, 1, geom); - if(res != RES_OK) goto error; - res = s3d_scene_create(geom->sgs->s3d, &scene); - if(res != RES_OK) goto error; - res = s3d_scene_attach_shape(scene, shape); - if(res != RES_OK) goto error; + /* Create the scene view */ + res = mesh_create_view(geom->sgs, &mesh, S3D_TRACE, &geom->view_rt); + if(res != RES_OK) { + sgs_log_err(geom->sgs, + "Error creating the Star-3D scene view to ray-trace -- %s.\n", + res_to_cstr(res)); + goto error; + } + +exit: + return res; +error: + if(geom->view_rt) { + S3D(scene_view_ref_put(geom->view_rt)); + geom->view_rt = NULL; + } + goto exit; +} + +res_T +geometry_setup_view_sp(struct sgs_geometry* geom, const int sampling_mask) +{ + struct darray_size_t tris_sp; + struct mesh mesh = MESH_NULL; + const int* types = NULL; + const size_t* ids = NULL; + size_t itri = 0; + size_t ntris = 0; + res_T res = RES_OK; + ASSERT(geom && sampling_mask); + + darray_size_t_init(sgs_get_allocator(geom->sgs), &tris_sp); + + /* Clean up an eventual previous scene view */ + if(geom->view_sp) { + S3D(scene_view_ref_put(geom->view_sp)); + geom->view_sp = NULL; + } + + /* Fetch the geometry data */ + ntris = geometry_get_ntriangles(geom); + ids = darray_size_t_cdata_get(&geom->tris); + types = darray_int_cdata_get(&geom->tris_type); + + /* Find the triangles to sample */ + FOR_EACH(itri, 0, ntris) { + if((types[itri] & sampling_mask) != 0) { + /* Register the triangle as a triangle to sample */ + res = darray_size_t_push_back(&tris_sp, &ids[itri*3+0]); + if(res != RES_OK) goto error; + res = darray_size_t_push_back(&tris_sp, &ids[itri*3+1]); + if(res != RES_OK) goto error; + res = darray_size_t_push_back(&tris_sp, &ids[itri*3+2]); + if(res != RES_OK) goto error; + } + } + + /* Setup the mesh to sample */ + mesh.vertices = darray_double_cdata_get(&geom->verts); + mesh.triangles = darray_size_t_cdata_get(&tris_sp); + mesh.nvertices = darray_double_size_get(&geom->verts)/3/*#coords per vertex*/; + mesh.ntriangles = darray_size_t_size_get(&tris_sp)/3/*#ids per triangle*/; /* Create the scene view */ - res = s3d_scene_view_create(scene, S3D_TRACE, &geom->view_rt); - if(res != RES_OK) goto error; + res = mesh_create_view(geom->sgs, &mesh, S3D_SAMPLE, &geom->view_sp); + if(res != RES_OK) { + sgs_log_err(geom->sgs, + "Error creating the Star-3D scene view to sample -- %s.\n", + res_to_cstr(res)); + goto error; + } exit: - if(shape) S3D(shape_ref_put(shape)); - if(scene) S3D(scene_ref_put(scene)); + darray_size_t_release(&tris_sp); return res; error: + if(geom->view_sp) { + S3D(scene_view_ref_put(geom->view_sp)); + geom->view_sp = NULL; + } goto exit; } diff --git a/src/sgs_geometry.h b/src/sgs_geometry.h @@ -31,16 +31,16 @@ enum sgs_geometry_type { }; enum sgs_surface_type { - SGS_SURFACE_X_NEG, /* -X face */ - SGS_SURFACE_X_POS, /* +X face */ - SGS_SURFACE_Y_NEG, /* -Y face */ - SGS_SURFACE_Y_POS, /* +Y face */ - SGS_SURFACE_Z_NEG, /* -Z face */ - SGS_SURFACE_Z_POS, /* +Z face */ - SGS_SURFACE_Z_SLOPE, /* +Z face representing a slope */ - SGS_SURFACE_Z_LVL0, /* +Z face representing the 1st level along X */ - SGS_SURFACE_Z_LVL1, /* +Z face representing the 2nd level along X */ - SGS_SURFACE_Z_STEP /* +Z face representing the step between the 2 levels */ + SGS_SURFACE_X_NEG = BIT(0), /* -X face */ + SGS_SURFACE_X_POS = BIT(1), /* +X face */ + SGS_SURFACE_Y_NEG = BIT(2), /* -Y face */ + SGS_SURFACE_Y_POS = BIT(3), /* +Y face */ + SGS_SURFACE_Z_NEG = BIT(4), /* -Z face */ + SGS_SURFACE_Z_POS = BIT(5), /* +Z face */ + SGS_SURFACE_Z_SLOPE = BIT(6), /* +Z face representing a slope */ + SGS_SURFACE_Z_LVL0 = BIT(7), /* +Z face representing the 1st level along X */ + SGS_SURFACE_Z_LVL1 = BIT(8), /* +Z face representing the 2nd level along X */ + SGS_SURFACE_Z_STEP = BIT(9) /* +Z face representing the step between the 2 levels */ }; /* A simple axis aligned bounding box @@ -54,8 +54,9 @@ enum sgs_surface_type { struct sgs_geometry_box_args { double lower[3]; /* Lower bound */ double upper[3]; /* Upper bound */ + int sampling_mask; /* Combination of enum sgs_surface_type */ }; -#define SGS_GEOMETRY_BOX_ARGS_DEFAULT__ {{0,0,0}, {1,1,1}} +#define SGS_GEOMETRY_BOX_ARGS_DEFAULT__ {{0,0,0}, {1,1,1}, SGS_SURFACE_Z_POS} static const struct sgs_geometry_box_args SGS_GEOMETRY_BOX_ARGS_DEFAULT = SGS_GEOMETRY_BOX_ARGS_DEFAULT__; @@ -76,12 +77,13 @@ struct sgs_geometry_slope_args { double lower[3]; /* 3D lower bound */ double upper[2]; /* 2D upper bound in the XY plane */ double heights[2]; /* The slope heights in Z along the X axis */ + int sampling_mask; /* Combination of enum sgs_surface_type */ }; -#define SGS_GEOMETRY_SLOPE_ARGS_DEFAULT__ {{0,0}, {1,1}, {0.5,1}} +#define SGS_GEOMETRY_SLOPE_ARGS_DEFAULT__ \ + {{0,0,0}, {1,1}, {0.5,1}, SGS_SURFACE_Z_SLOPE} static const struct sgs_geometry_slope_args SGS_GEOMETRY_SLOPE_ARGS_DEFAULT = SGS_GEOMETRY_SLOPE_ARGS_DEFAULT__; - /* A "box" whose +Z face forms a step along the X axis * o---o * /' /| @@ -96,12 +98,19 @@ static const struct sgs_geometry_slope_args SGS_GEOMETRY_SLOPE_ARGS_DEFAULT = * . . . . l----s---o . . . . . . * lower step */ struct sgs_geometry_step_args { - double lower[2]; /* 2D lower bound in the XY plane */ + double lower[3]; /* 3D lower bound */ double upper[2]; /* 2D upper bound in the XY plane */ double heights[2]; /* The slope heights in Z along the X axis */ double step; /* X coordinate of the step */ + int sampling_mask; /* Combination of enum sgs_surface_type */ }; -#define SGS_GEOMETRY_STEP_ARGS_DEFAULT__ {{0,0}, {1,1}, {0.5,1}, 0.5} +#define SGS_GEOMETRY_STEP_ARGS_DEFAULT__ { \ + {0,0,0}, \ + {1,1}, \ + {0.5,1}, \ + 0.5, \ + SGS_SURFACE_Z_LVL0 | SGS_SURFACE_Z_LVL1 | SGS_SURFACE_Z_STEP \ +} static const struct sgs_geometry_step_args SGS_GEOMETRY_STEP_ARGS_DEFAULT = SGS_GEOMETRY_STEP_ARGS_DEFAULT__; diff --git a/src/sgs_geometry_box.c b/src/sgs_geometry_box.c @@ -135,6 +135,8 @@ sgs_geometry_box_create if(res != RES_OK) goto error; res = geometry_setup_view_rt(geom); if(res != RES_OK) goto error; + res = geometry_setup_view_sp(geom, args->sampling_mask); + if(res != RES_OK) goto error; exit: *out_geom = geom; diff --git a/src/sgs_geometry_c.h b/src/sgs_geometry_c.h @@ -34,8 +34,8 @@ struct sgs_geometry { struct darray_size_t tris; struct darray_int tris_type; /* List of enum sgs_surface_type */ - struct s3d_scene_view* view_sp; struct s3d_scene_view* view_rt; + struct s3d_scene_view* view_sp; enum sgs_geometry_type type; @@ -53,6 +53,11 @@ extern LOCAL_SYM res_T geometry_setup_view_rt (struct sgs_geometry* geom); +extern LOCAL_SYM res_T +geometry_setup_view_sp + (struct sgs_geometry* geom, + const int sampling_mask); /* Combination of enum sgs_surface_type */ + /* Return the number of vertices */ static FINLINE size_t geometry_get_nvertices(const struct sgs_geometry* geom) @@ -61,7 +66,7 @@ geometry_get_nvertices(const struct sgs_geometry* geom) return darray_double_size_get(&geom->verts) / 3/*#coords per vertex*/; } -/* Return the number of triangles */ +/* Return the overall number of triangles */ static FINLINE size_t geometry_get_ntriangles(const struct sgs_geometry* geom) { diff --git a/src/sgs_geometry_slope.c b/src/sgs_geometry_slope.c @@ -139,6 +139,8 @@ sgs_geometry_slope_create if(res != RES_OK) goto error; res = geometry_setup_view_rt(geom); if(res != RES_OK) goto error; + res = geometry_setup_view_sp(geom, args->sampling_mask); + if(res != RES_OK) goto error; exit: *out_geom = geom;