commit 0741cfe75dee1c716bfa9212825dd2fb52773b27
parent 860462a6161bb46fc256f6b40924a3bc69e08d90
Author: Vincent Forest <vincent.forest@meso-star.com>
Date: Fri, 24 Feb 2017 14:23:58 +0100
Drastically improved the dump geometry mode
Replace the -O dump option by the -g one. Add dump options like the output
geometry format and the possibility to split the output data by geometry
or by object.
Diffstat:
10 files changed, 327 insertions(+), 27 deletions(-)
diff --git a/doc/cli b/doc/cli
@@ -4,7 +4,7 @@ solstice
-D <sun-dir-list>
-f # Force output overwrite
-h # Short help and exit
- -O # Switch in dump mode
+ -g <dump> # Switch in dump geometry
-o OUTPUT # defaulting to stdout if not defined
-q # don't print a message if no INPUT is submitted
-n INTEGER # Realisations count
@@ -14,6 +14,7 @@ solstice
INPUT # Input scene in YAML
solstice -r img=1280x720:pos=0,100,0:tgt=0,0,0:up=0,1,0:fov=70
+solstice -g format=obj:split-group=1
-d and -D are exclusive
@@ -38,6 +39,15 @@ solstice -r img=1280x720:pos=0,100,0:tgt=0,0,0:up=0,1,0:fov=70
<rendering-option> ::=
<fov> | <img> | <position> | <target> | <up>
+<dump> ::=
+ format=<dump-format>[:split=<split-mode>]
+
+<dump-format> ::=
+ obj
+
+<split-mode> ::=
+ geometry | object | none
+
<fov> ::=
fov=<real3>
diff --git a/src/solstice.c b/src/solstice.c
@@ -520,7 +520,8 @@ solstice_init
solstice->nrealisations = args->nrealisations;
solstice->output_hits = args->output_hits;
- solstice->dump_obj = args->dump_obj;
+ solstice->dump_format = args->dump_format;
+ solstice->dump_split_mode = args->dump_split_mode;
exit:
return res;
@@ -560,6 +561,8 @@ solstice_run(struct solstice* solstice)
const double* sun_dirs = NULL;
size_t nsun_dirs = 0;
size_t i;
+ int dump;
+ int draw;
res_T res = RES_OK;
ASSERT(solstice);
@@ -568,12 +571,15 @@ solstice_run(struct solstice* solstice)
ASSERT(nsun_dirs%3 == 0);
nsun_dirs /= 3/*#dims*/;
+ dump = solstice->dump_format != SOLSTICE_ARGS_DUMP_NONE;
+ draw = solstice->framebuffer != NULL;
+
if(!nsun_dirs) {
- if(solstice->dump_obj) {
- res = solstice_dump_obj(solstice);
+ if(dump) {
+ res = solstice_dump(solstice);
if(res != RES_OK) goto error;
} else {
- ASSERT(solstice->framebuffer);
+ ASSERT(draw);
res = solstice_draw(solstice);
if(res != RES_OK) goto error;
}
@@ -584,11 +590,11 @@ solstice_run(struct solstice* solstice)
res = solstice_update_entities(solstice, sun_dir);
if(res != RES_OK) goto error;
- if(solstice->framebuffer) {
+ if(draw) {
res = solstice_draw(solstice);
if(res != RES_OK) goto error;
- } else if(solstice->dump_obj) {
- res = solstice_dump_obj(solstice);
+ } else if(dump) {
+ res = solstice_dump(solstice);
if(res != RES_OK) goto error;
} else {
res = ssol_sun_set_direction(solstice->sun, sun_dir);
diff --git a/src/solstice.h b/src/solstice.h
@@ -18,6 +18,7 @@
#include "parser/solparser_material.h"
#include "receivers/srcvl.h"
+#include "solstice_args.h"
#include <rsys/dynamic_array_double.h>
#include <rsys/hash_table.h>
@@ -25,7 +26,6 @@
#include <rsys/str.h>
struct solparser;
-struct solstice_args;
struct solstice_node;
struct ssol_device;
struct ssol_material;
@@ -87,11 +87,14 @@ struct solstice {
struct ssol_camera* camera;
struct ssol_image* framebuffer;
+ /* Dump geometry */
+ enum solstice_args_dump_format dump_format;
+ enum solstice_args_dump_split_mode dump_split_mode;
+
struct darray_double sun_dirs; /* List of double3 */
size_t nrealisations; /* # realisations */
FILE* output; /* Output stream */
- int dump_obj; /* Dump the geometry */
int output_hits; /* Output per receiver hits */
struct mem_allocator* allocator;
diff --git a/src/solstice_args.c b/src/solstice_args.c
@@ -54,7 +54,7 @@ print_help(const char* program)
" -n REALISATIONS number of realisations. Default is %lu.\n",
SOLSTICE_ARGS_DEFAULT.nrealisations);
printf(
-" -O switch in dump geometry mode.\n");
+" -g <dump> switch in dump geometry mode and configure it.\n");
printf(
" -o OUTPUT write results to OUTPUT. If not defined, write results to\n"
" standard output.\n");
@@ -298,6 +298,128 @@ error:
goto exit;
}
+static res_T
+parse_dump_format(const char* str, enum solstice_args_dump_format* fmt)
+{
+ res_T res = RES_OK;
+ ASSERT(str && fmt);
+
+ if(!strcmp(str, "obj")) {
+ *fmt = SOLSTICE_ARGS_DUMP_OBJ;
+ } else {
+ fprintf(stderr, "Invalid dump format `%s'.\n", str);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_dump_split_mode(const char* str, enum solstice_args_dump_split_mode* mode)
+{
+ res_T res = RES_OK;
+ ASSERT(str && mode);
+
+ if(!strcmp(str, "geometry")) {
+ *mode = SOLSTICE_ARGS_DUMP_SPLIT_GEOMETRY;
+ } else if(!strcmp(str, "none")) {
+ *mode = SOLSTICE_ARGS_DUMP_SPLIT_NONE;
+ } else if(!strcmp(str, "object")) {
+ *mode = SOLSTICE_ARGS_DUMP_SPLIT_OBJECT;
+ } else {
+ fprintf(stderr, "Invalid dump split mode `%s'.\n", str);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_dump_option(const char* str, struct solstice_args* args)
+{
+ char buf[128];
+ char* key;
+ char* val;
+ char* ctx;
+ res_T res = RES_OK;
+ ASSERT(str && args);
+
+ if(strlen(str) >= sizeof(buf) - 1/*NULL char*/) {
+ fprintf(stderr,
+ "Could not duplicate the dump geometry option string `%s'\n", str);
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ strncpy(buf, str, sizeof(buf));
+
+ key = strtok_r(buf, "=", &ctx);
+ val = strtok_r(NULL, "", &ctx);
+
+ if(!val) {
+ fprintf(stderr, "Missing a value to the dump option `%s'.\n", key);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+ if(!strcmp(key, "format")) {
+ res = parse_dump_format(val, &args->dump_format);
+ } else if(!strcmp(key, "split")) {
+ res = parse_dump_split_mode(val, &args->dump_split_mode);
+ } else {
+ fprintf(stderr, "Invalid dump option `%s'.\n", val);
+ res = RES_BAD_ARG;
+ goto error;
+ }
+ if(res != RES_OK) goto error;
+
+ if(args->dump_format == SOLSTICE_ARGS_DUMP_NONE) {
+ fprintf(stderr, "No dump format is defined.\n");
+ res = RES_BAD_ARG;
+ goto error;
+ }
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
+parse_dump_options(const char* str, struct solstice_args* args)
+{
+ char buf[512];
+ char* tk;
+ char* ctx;
+ res_T res = RES_OK;
+ ASSERT(args && str);
+ (void)str, (void)args;
+
+ if(strlen(str) >= sizeof(buf) - 1/*NULL char*/) {
+ fprintf(stderr,
+ "Could not duplicate the dump geometry options string `%s'.\n", str);
+ res = RES_MEM_ERR;
+ goto error;
+ }
+ strncpy(buf, str, sizeof(buf));
+ tk = strtok_r(buf, ":", &ctx);
+ do {
+ res = parse_dump_option(tk, args);
+ tk = strtok_r(NULL, ":", &ctx);
+ } while(tk);
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
/*******************************************************************************
* Local function
******************************************************************************/
@@ -311,7 +433,7 @@ solstice_args_init(struct solstice_args* args, const int argc, char** argv)
*args = SOLSTICE_ARGS_DEFAULT;
optind = 0;
- while((opt = getopt(argc, argv, "D:fHhn:Oo:qR:r:t:")) != -1) {
+ while((opt = getopt(argc, argv, "D:fg:Hhn:o:qR:r:t:")) != -1) {
switch(opt) {
case 'D':
res = parse_sun_dir_list(optarg, args);
@@ -327,7 +449,7 @@ solstice_args_init(struct solstice_args* args, const int argc, char** argv)
res = cstr_to_ulong(optarg, &args->nrealisations);
if(res == RES_OK && !args->nrealisations) res = RES_BAD_ARG;
break;
- case 'O': args->dump_obj = 1; break;
+ case 'g': res = parse_dump_options(optarg, args); break;
case 'o': args->output_filename = optarg; break;
case 'q': args->quiet = 1; break;
case 'R': args->receivers_filename = optarg; break;
@@ -347,14 +469,16 @@ solstice_args_init(struct solstice_args* args, const int argc, char** argv)
}
}
- if(!args->rendering && !args->dump_obj && !args->nsun_dirs) {
+ if(!args->rendering
+ && args->dump_format == SOLSTICE_ARGS_DUMP_NONE
+ && !args->nsun_dirs) {
fprintf(stderr, "Missing sun direction.\n");
res = RES_BAD_ARG;
goto error;
}
- if(args->dump_obj && args->rendering) {
- fprintf(stderr, "The '-O' and '-r' options are exclusive\n");
+ if(args->dump_format != SOLSTICE_ARGS_DUMP_NONE && args->rendering) {
+ fprintf(stderr, "The '-g' and '-r' options are exclusive\n");
res = RES_BAD_ARG;
goto error;
}
diff --git a/src/solstice_args.h.in b/src/solstice_args.h.in
@@ -24,6 +24,17 @@ struct solstice_args_spherical {
double elevation; /* In radians */
};
+enum solstice_args_dump_format {
+ SOLSTICE_ARGS_DUMP_OBJ,
+ SOLSTICE_ARGS_DUMP_NONE
+};
+
+enum solstice_args_dump_split_mode {
+ SOLSTICE_ARGS_DUMP_SPLIT_GEOMETRY,
+ SOLSTICE_ARGS_DUMP_SPLIT_NONE,
+ SOLSTICE_ARGS_DUMP_SPLIT_OBJECT
+};
+
struct solstice_args {
const char* output_filename;
const char* input_filename; /* May be NULL <=> read data from stdin */
@@ -47,8 +58,10 @@ struct solstice_args {
unsigned long height;
} img;
+ enum solstice_args_dump_format dump_format;
+ enum solstice_args_dump_split_mode dump_split_mode;
+
int force_overwriting;
- int dump_obj;
int rendering;
int output_hits; /* Output the per receiver hits */
int quiet;
@@ -80,8 +93,10 @@ static const struct solstice_args SOLSTICE_ARGS_NULL = SOLSTICE_ARGS_NULL__;
@SOLSTICE_ARGS_DEFAULT_IMG_HEIGHT@ \
}, \
\
+ SOLSTICE_ARGS_DUMP_NONE, /* Dump format */ \
+ SOLSTICE_ARGS_DUMP_SPLIT_NONE, /* Dump split mode */ \
+ \
0, /* Force overwriting */ \
- 0, /* Dump */ \
0, /* Rendering */ \
0, /* Output hits */ \
0, /* Quiet */ \
diff --git a/src/solstice_c.h b/src/solstice_c.h
@@ -20,6 +20,8 @@
#include "parser/solparser.h"
#include <rsys/ref_count.h>
+#include <rsys/str.h>
+
#include <solstice/sanim.h>
enum solstice_node_type {
@@ -32,6 +34,7 @@ enum solstice_node_type {
struct solstice_node {
struct sanim_node anim;
+ struct str name;
enum solstice_node_type type;
struct ssol_instance* instance; /* Available for geometry nodes */
@@ -50,7 +53,7 @@ solstice_solve
(struct solstice* solstice);
extern LOCAL_SYM res_T
-solstice_dump_obj
+solstice_dump
(struct solstice* solstice);
extern LOCAL_SYM res_T
@@ -110,6 +113,15 @@ solstice_node_ref_put
(struct solstice_node* node);
extern LOCAL_SYM res_T
+solstice_node_set_name
+ (struct solstice_node* node,
+ const char* name);
+
+extern LOCAL_SYM const char*
+solstice_node_get_name
+ (const struct solstice_node* node);
+
+extern LOCAL_SYM res_T
solstice_node_geometry_set_primary
(struct solstice_node* node,
const int is_primary);
diff --git a/src/solstice_dump_obj.c b/src/solstice_dump_obj.c
@@ -19,6 +19,7 @@
struct dump_context {
FILE* output;
size_t ids_offset;
+ enum solstice_args_dump_split_mode split_mode;
};
/*******************************************************************************
@@ -29,8 +30,20 @@ dump_instantiated_shaded_shape
(struct ssol_instantiated_shaded_shape* sshape, struct dump_context* ctx)
{
unsigned i, ntris, nverts;
+ enum ssol_material_type type;
+ const char* mtl;
ASSERT(sshape && ctx);
+ SSOL(material_get_type(sshape->mtl_front, &type));
+ switch(type) {
+ case SSOL_MATERIAL_MATTE: mtl = "matte"; break;
+ case SSOL_MATERIAL_MIRROR: mtl = "mirror"; break;
+ case SSOL_MATERIAL_VIRTUAL: mtl = "virtual"; break;
+ default: FATAL("Unexpected Solstice Solver material type.\n"); break;
+ }
+
+ fprintf(ctx->output, "usemtl %s\n", mtl);
+
SSOL(shape_get_vertices_count(sshape->shape, &nverts));
FOR_EACH(i, 0, nverts) {
double pos[3];
@@ -50,7 +63,12 @@ dump_instantiated_shaded_shape
(unsigned long)(ids[2] + 1 + ctx->ids_offset));
}
- ctx->ids_offset += nverts;
+ if(ctx->split_mode == SOLSTICE_ARGS_DUMP_SPLIT_OBJECT) {
+ fprintf(ctx->output, "---\n");
+ ctx->ids_offset = 0;
+ } else {
+ ctx->ids_offset += nverts;
+ }
}
static res_T
@@ -63,7 +81,6 @@ dump_instance(struct ssol_instance* instance, void* context)
SSOL(instance_get_shaded_shapes_count(instance, &n));
FOR_EACH(i, 0, n) {
struct ssol_instantiated_shaded_shape sshape;
-
SSOL(instance_get_shaded_shape(instance, i, &sshape));
dump_instantiated_shaded_shape(&sshape, ctx);
}
@@ -71,23 +88,55 @@ dump_instance(struct ssol_instance* instance, void* context)
return RES_OK;
}
+static res_T
+dump_geometry
+ (const struct sanim_node* n, const double transform[12], void* data)
+{
+ struct solstice_node* node;
+ struct dump_context* ctx = data;
+ res_T res = RES_OK;
+ ASSERT(n && data);
+ (void)transform;
+
+ node = CONTAINER_OF(n, struct solstice_node, anim);
+ if(node->type != SOLSTICE_NODE_GEOMETRY) return RES_OK;
+ fprintf(ctx->output, "g %s\n", solstice_node_get_name(node));
+ res = dump_instance(node->instance, data);
+ if(res != RES_OK) return res;
+
+ if(ctx->split_mode == SOLSTICE_ARGS_DUMP_SPLIT_GEOMETRY) {
+ fprintf(ctx->output, "---\n");
+ ctx->ids_offset = 0;
+ }
+ return RES_OK;
+}
+
/*******************************************************************************
* Local functions
******************************************************************************/
res_T
-solstice_dump_obj(struct solstice* solstice)
+solstice_dump(struct solstice* solstice)
{
struct dump_context ctx;
+ double dummy_dir[3] = {0, 0, 1};
+ size_t i, n;
res_T res = RES_OK;
- ASSERT(solstice);
+ ASSERT(solstice && solstice->dump_format == SOLSTICE_ARGS_DUMP_OBJ);
ctx.output = solstice->output;
ctx.ids_offset = 0;
+ ctx.split_mode = solstice->dump_split_mode;
+
+ n = darray_nodes_size_get(&solstice->roots);
+ FOR_EACH(i, 0, n) {
+ struct solstice_node* node = darray_nodes_data_get(&solstice->roots)[i];
- res = ssol_scene_for_each_instance(solstice->scene, dump_instance, &ctx);
- if(res != RES_OK) {
- fprintf(stderr, "Could not dump the solstice geometry.\n");
- goto error;
+ fprintf(solstice->output, "# %s\n", solstice_node_get_name(node));
+ res = sanim_node_visit_tree(&node->anim, dummy_dir, &ctx, dump_geometry);
+ if(res != RES_OK) {
+ fprintf(stderr, "Could not dump the solstice geometry.\n");
+ goto error;
+ }
}
exit:
diff --git a/src/solstice_entity.c b/src/solstice_entity.c
@@ -255,6 +255,12 @@ create_node
goto error;
}
+ res = solstice_node_set_name(node, str_cget(name));
+ if(res != RES_OK) {
+ fprintf(stderr, "Could not setup the solstice node name.\n");
+ goto error;
+ }
+
/* Setup the primary parameter for the geometry entity */
if(entity->type == SOLPARSER_ENTITY_GEOMETRY) {
res = solstice_node_geometry_set_primary(node, entity->primary);
diff --git a/src/solstice_node.c b/src/solstice_node.c
@@ -37,6 +37,7 @@ node_create
}
ref_init(&node->ref);
+ str_init(allocator, &node->name);
node->type = type;
node->anim = SANIM_NODE_NULL;
node->allocator = allocator;
@@ -61,6 +62,7 @@ node_release(ref_T* ref)
node = CONTAINER_OF(ref, struct solstice_node, ref);
if(node->instance) SSOL(instance_ref_put(node->instance));
+ str_release(&node->name);
SANIM(node_is_initialized(&node->anim, &is_init));
if(is_init) {
@@ -222,6 +224,20 @@ solstice_node_ref_put(struct solstice_node* node)
}
res_T
+solstice_node_set_name(struct solstice_node* node, const char* name)
+{
+ ASSERT(node);
+ return str_set(&node->name, name);
+}
+
+const char*
+solstice_node_get_name(const struct solstice_node* node)
+{
+ ASSERT(node);
+ return str_cget(&node->name);
+}
+
+res_T
solstice_node_geometry_set_primary
(struct solstice_node* node, const int is_primary)
{
diff --git a/src/test_solstice_args.c b/src/test_solstice_args.c
@@ -459,6 +459,64 @@ test_input(void)
cmd_delete(cmd);
}
+static void
+test_dump(void)
+{
+ struct solstice_args args = SOLSTICE_ARGS_NULL;
+ char** cmd = NULL;
+
+ cmd = cmd_create(0, "test", "-D", "0,90", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_OK);
+ CHECK(args.dump_format, SOLSTICE_ARGS_DUMP_NONE);
+ CHECK(args.dump_split_mode, SOLSTICE_ARGS_DUMP_SPLIT_NONE);
+ solstice_args_release(&args);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-g", "format=obj", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_OK);
+ CHECK(args.dump_format, SOLSTICE_ARGS_DUMP_OBJ);
+ CHECK(args.dump_split_mode, SOLSTICE_ARGS_DUMP_SPLIT_NONE);
+ solstice_args_release(&args);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-g", "split=geometry:format=obj", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_OK);
+ CHECK(args.dump_format, SOLSTICE_ARGS_DUMP_OBJ);
+ CHECK(args.dump_split_mode, SOLSTICE_ARGS_DUMP_SPLIT_GEOMETRY);
+ solstice_args_release(&args);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-g", "format=obj:split=object", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_OK);
+ CHECK(args.dump_format, SOLSTICE_ARGS_DUMP_OBJ);
+ CHECK(args.dump_split_mode, SOLSTICE_ARGS_DUMP_SPLIT_OBJECT);
+ solstice_args_release(&args);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-g", "format=obj::::split=none", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_OK);
+ CHECK(args.dump_format, SOLSTICE_ARGS_DUMP_OBJ);
+ CHECK(args.dump_split_mode, SOLSTICE_ARGS_DUMP_SPLIT_NONE);
+ solstice_args_release(&args);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-g", "split=object", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_BAD_ARG);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-g", "format=stl", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_BAD_ARG);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-g", "format=obj:dummy", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_BAD_ARG);
+ cmd_delete(cmd);
+
+ cmd = cmd_create(0, "test", "-g", "format=obj:split", NULL);
+ CHECK(solstice_args_init(&args, cmd_size(cmd), cmd), RES_BAD_ARG);
+ cmd_delete(cmd);
+}
+
int
main(int argc, char** argv)
{
@@ -472,6 +530,7 @@ main(int argc, char** argv)
test_quiet();
test_receivers();
test_input();
+ test_dump();
CHECK(mem_allocated_size(), 0);
return 0;
}