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:
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;