commit e6728748b90a6da11dba299c18f0b24dec3a55bc
parent 00622de9cfa91fd88b811687f77afb5158adda67
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date: Mon, 6 Mar 2017 09:49:30 +0100
Merge branch 'develop' into feature_hyperbols
Diffstat:
6 files changed, 222 insertions(+), 102 deletions(-)
diff --git a/src/parser/solparser.c b/src/parser/solparser.c
@@ -217,7 +217,6 @@ struct solparser {
struct solparser_sun sun; /* The loaded sun */
/* Entity */
- struct htable_yaml2sols yaml2entities; /* Cache of entities */
struct htable_str2sols str2entities;
struct darray_entity entities;
@@ -416,7 +415,6 @@ parser_clear(struct solparser* parser)
parser->sun_key = 0;
/* Entities */
- htable_yaml2sols_clear(&parser->yaml2entities);
htable_str2sols_clear(&parser->str2entities);
darray_entity_clear(&parser->entities);
@@ -468,7 +466,6 @@ parser_release(ref_T* ref)
solparser_sun_release(&parser->sun);
/* Entities */
- htable_yaml2sols_release(&parser->yaml2entities);
htable_str2sols_release(&parser->str2entities);
darray_entity_release(&parser->entities);
@@ -2790,7 +2787,6 @@ parse_entity
enum { ANCHORS, CHILDREN, DATA, NAME, TRANSFORM, PRIMARY };
struct solparser_entity solent;
struct solparser_entity* psolent;
- const size_t *pisolent;
size_t isolent = SIZE_MAX;
intptr_t i, n;
int mask = 0; /* Register the parsed attributes */
@@ -2799,14 +2795,6 @@ parse_entity
solparser_entity_init(parser->allocator, &solent);
- pisolent = htable_yaml2sols_find(&parser->yaml2entities, &entity);
- if(pisolent) {
- isolent = *pisolent;
- res = entity_register_name(parser, entity, htable, *pisolent);
- if(res != RES_OK) goto error;
- goto exit;
- }
-
if(entity->type != YAML_MAPPING_NODE) {
log_err(parser, entity, "expect an entity definition.\n");
res = RES_BAD_ARG;
@@ -2928,12 +2916,6 @@ parse_entity
res = entity_register_name(parser, entity, htable, isolent);
if(res != RES_OK) goto error;
- res = htable_yaml2sols_set(&parser->yaml2entities, &entity, &isolent);
- if(res != RES_OK) {
- log_err(parser, entity, "could not register the entity.\n");
- goto error;
- }
-
exit:
solparser_entity_release(&solent);
out_isolent->i = isolent;
@@ -3664,7 +3646,6 @@ solparser_create
solparser_sun_init(mem_allocator, &parser->sun);
/* Entities */
- htable_yaml2sols_init(mem_allocator, &parser->yaml2entities);
htable_str2sols_init(mem_allocator, &parser->str2entities);
darray_entity_init(mem_allocator, &parser->entities);
diff --git a/src/parser/solparser_pivot.h b/src/parser/solparser_pivot.h
@@ -18,15 +18,9 @@
#include <rsys/double3.h>
-enum solparser_target_type {
- SOLPARSER_TARGET_ANCHOR,
- SOLPARSER_TARGET_DIRECTION,
- SOLPARSER_TARGET_POSITION,
- SOLPARSER_TARGET_SUN,
-
- SOLPARSER_TARGET_TYPES_COUNT__
-};
-
+/*******************************************************************************
+ * Anchor
+ ******************************************************************************/
struct solparser_anchor_id { size_t i; };
struct solparser_anchor {
@@ -67,6 +61,18 @@ solparser_anchor_copy_and_release
return str_copy_and_release(&dst->name, &src->name);
}
+/*******************************************************************************
+ * Target
+ ******************************************************************************/
+enum solparser_target_type {
+ SOLPARSER_TARGET_ANCHOR,
+ SOLPARSER_TARGET_DIRECTION,
+ SOLPARSER_TARGET_POSITION,
+ SOLPARSER_TARGET_SUN,
+
+ SOLPARSER_TARGET_TYPES_COUNT__
+};
+
struct solparser_target {
enum solparser_target_type type;
union {
@@ -75,10 +81,14 @@ struct solparser_target {
struct solparser_anchor_id anchor;
} data;
};
-#define SOLPARSER_TARGET_NULL__ { SOLPARSER_TARGET_TYPES_COUNT__, {{0,0,0}} }
+#define SOLPARSER_TARGET_NULL__ { 0 }
static const struct solparser_target SOLPARSER_TARGET_NULL =
SOLPARSER_TARGET_NULL__;
+
+/*******************************************************************************
+ * X pivot
+ ******************************************************************************/
struct solparser_pivot_id { size_t i; };
struct solparser_x_pivot {
@@ -92,12 +102,16 @@ static const struct solparser_x_pivot SOLPARSER_X_PIVOT_NULL =
static INLINE void
solparser_x_pivot_init
-(struct mem_allocator* allocator, struct solparser_x_pivot* x_pivot)
+ (struct mem_allocator* allocator, struct solparser_x_pivot* x_pivot)
{
- (void) allocator;
+ (void)allocator;
ASSERT(x_pivot);
*x_pivot = SOLPARSER_X_PIVOT_NULL;
}
+
+/*******************************************************************************
+ * ZX pivot
+ ******************************************************************************/
struct solparser_zx_pivot {
double spacing;
double ref_point[3];
@@ -112,7 +126,7 @@ static INLINE void
solparser_zx_pivot_init
(struct mem_allocator* allocator, struct solparser_zx_pivot* zx_pivot)
{
- (void) allocator;
+ (void)allocator;
ASSERT(zx_pivot);
*zx_pivot = SOLPARSER_ZX_PIVOT_NULL;
}
diff --git a/src/solstice.c b/src/solstice.c
@@ -44,7 +44,6 @@
#include <unistd.h>
#endif
-
#include <solstice/ssol.h>
/*******************************************************************************
@@ -95,10 +94,99 @@ clear_nodes(struct darray_nodes* nodes)
}
static res_T
+auto_look_at
+ (struct ssol_scene* scn,
+ const double fov_x, /* Horizontal field of view in radian */
+ const double proj_ratio, /* Width / height */
+ const double up[3], /* Up vector */
+ double position[3],
+ double target[3])
+{
+ float flower[3], fupper[3];
+ double lower[3], upper[3];
+ double up_abs[3];
+ double axis_min[3];
+ double axis_x[3];
+ double axis_z[3];
+ double tmp[3];
+ double radius;
+ double depth;
+ res_T res;
+ ASSERT(scn && fov_x && proj_ratio && up);
+
+ res = ssol_scene_compute_aabb(scn, flower, fupper);
+ if(res != RES_OK) {
+ fprintf(stderr, "Couldn't compute the scene bounding box.\n");
+ goto error;
+ }
+
+ if(flower[0] > fupper[0]
+ || flower[1] > fupper[1]
+ || flower[2] > fupper[2]) { /* Empty scene */
+ d3_set(position, SOLSTICE_ARGS_DEFAULT.camera.pos);
+ d3_set(target, SOLSTICE_ARGS_DEFAULT.camera.tgt);
+ goto exit;
+ }
+
+ d3_set_f3(upper, fupper);
+ d3_set_f3(lower, flower);
+
+ /* The target is the scene centroid */
+ d3_muld(target, d3_add(target, lower, upper), 0.5);
+
+ /* Define which up dimension is minimal and use its unit vector to compute a
+ * vector orthogonal to `up'. This ensures that the unit vector and `up' are
+ * not collinear and thus that their cross product is not a zero vector. */
+ up_abs[0] = fabs(up[0]);
+ up_abs[1] = fabs(up[1]);
+ up_abs[2] = fabs(up[2]);
+ if(up_abs[0] < up_abs[1]) {
+ if(up_abs[0] < up_abs[2]) d3(axis_min, 1, 0, 0);
+ else d3(axis_min, 0, 0, 1);
+ } else {
+ if(up_abs[1] < up_abs[2]) d3(axis_min, 0, 1, 0);
+ else d3(axis_min, 0, 0, 1);
+ }
+ d3_normalize(axis_x, d3_cross(axis_x, up, axis_min));
+ d3_normalize(axis_z, d3_cross(axis_z, up, axis_x));
+
+ /* Approximate whether on the XYZ or the ZYX basis the visible part of the
+ * model is maximise */
+ if(fabs(d3_dot(axis_x, upper)) < fabs(d3_dot(axis_z, upper))) {
+ SWAP(double, axis_x[0], axis_z[0]);
+ SWAP(double, axis_x[1], axis_z[1]);
+ SWAP(double, axis_x[2], axis_z[2]);
+ }
+
+ /* Ensure that the whole model is visible */
+ radius = d3_len(d3_sub(tmp, upper, lower)) * 0.5;
+ if(proj_ratio < 1) {
+ depth = radius / sin(fov_x/2.0);
+ } else {
+ depth = radius / sin(fov_x/(2.0*proj_ratio));
+ }
+
+ /* Define the camera position */
+ d3_sub(position, target, d3_muld(tmp, axis_z, depth));
+
+ /* Empirically move the position to find a better point of view */
+ d3_add(position, position, d3_muld(tmp, up, radius)); /*Empirical offset*/
+ d3_add(position, position, d3_muld(tmp, axis_x, radius)); /*Empirical offset*/
+ d3_normalize(tmp, d3_sub(tmp, target, position));
+ d3_sub(position, target, d3_muld(tmp, tmp, depth));
+
+exit:
+ return res;
+error:
+ goto exit;
+}
+
+static res_T
setup_camera(struct solstice* solstice, const struct solstice_args* args)
{
struct ssol_camera* cam = NULL;
double proj_ratio = 0;
+ double pos[3], tgt[3];
res_T res = RES_OK;
ASSERT(solstice && args);
@@ -122,8 +210,16 @@ setup_camera(struct solstice* solstice, const struct solstice_args* args)
goto error;
}
- res = ssol_camera_look_at
- (cam, args->camera.pos, args->camera.tgt, args->camera.up);
+ if(!args->camera.auto_look_at) {
+ d3_set(pos, args->camera.pos);
+ d3_set(tgt, args->camera.tgt);
+ } else {
+ res = auto_look_at(solstice->scene, MDEG2RAD(args->camera.fov_x),
+ proj_ratio, args->camera.up, pos, tgt);
+ if(res != RES_OK) goto error;
+ }
+
+ res = ssol_camera_look_at(cam, pos, tgt, args->camera.up);
if(res != RES_OK) {
fprintf(stderr,
"Invalid camera point of view:\n"
@@ -462,13 +558,6 @@ solstice_init
goto error;
}
- if(args->rendering) {
- res = setup_camera(solstice, args);
- if(res != RES_OK) goto error;
- res = setup_framebuffer(solstice, args);
- if(res != RES_OK) goto error;
- }
-
res = setup_sun_dirs(solstice, args);
if(res != RES_OK) goto error;
@@ -505,6 +594,13 @@ solstice_init
solstice->dump_format = args->dump_format;
solstice->dump_split_mode = args->dump_split_mode;
+ if(args->rendering) {
+ res = setup_camera(solstice, args);
+ if(res != RES_OK) goto error;
+ res = setup_framebuffer(solstice, args);
+ if(res != RES_OK) goto error;
+ }
+
exit:
return res;
error:
diff --git a/src/solstice_args.c b/src/solstice_args.c
@@ -238,6 +238,7 @@ parse_rendering_option(const char* str, struct solstice_args* args)
fprintf(stderr, "Invalid camera position `%s'.\n", val);
goto error;
}
+ args->camera.auto_look_at = 0; /* Disable auto look at */
} else if(!strcmp(key, "tgt")) {
res = cstr_to_list_double(val, ',', args->camera.tgt, &len, 3);
if(res == RES_OK && len != 3) res = RES_BAD_ARG;
@@ -245,6 +246,7 @@ parse_rendering_option(const char* str, struct solstice_args* args)
fprintf(stderr, "Invalid camera target `%s'.\n", val);
goto error;
}
+ args->camera.auto_look_at = 0; /* Disable auto look at */
} else if(!strcmp(key, "up")) {
res = cstr_to_list_double(val, ',', args->camera.up, &len, 3);
if(res == RES_OK && len != 3) res = RES_BAD_ARG;
diff --git a/src/solstice_args.h.in b/src/solstice_args.h.in
@@ -51,6 +51,7 @@ struct solstice_args {
double tgt[3];
double up[3];
double fov_x; /* In radians */
+ int auto_look_at;
} camera;
struct {
@@ -85,7 +86,8 @@ static const struct solstice_args SOLSTICE_ARGS_NULL = SOLSTICE_ARGS_NULL__;
{ @SOLSTICE_ARGS_DEFAULT_CAMERA_POS@ }, \
{ @SOLSTICE_ARGS_DEFAULT_CAMERA_TGT@ }, \
{ @SOLSTICE_ARGS_DEFAULT_CAMERA_UP@ }, \
- @SOLSTICE_ARGS_DEFAULT_CAMERA_FOV@ \
+ @SOLSTICE_ARGS_DEFAULT_CAMERA_FOV@, \
+ 1, \
}, \
\
{ /* Image */ \
diff --git a/src/solstice_entity.c b/src/solstice_entity.c
@@ -35,6 +35,33 @@ update_instance_transform
return ssol_instance_set_transform(node->instance, transform);
}
+static res_T
+merge_name
+ (struct str* RESTRICT output,
+ const struct str* name0,
+ const struct str* name1)
+{
+ res_T res = RES_OK;
+ ASSERT(output && name0 && name1);
+ ASSERT(output != name0 && output != name1);
+
+ res = str_copy(output, name0);
+ if(res != RES_OK) goto error;
+
+ res = str_append_char(output, '.');
+ if(res != RES_OK) goto error;
+
+ res = str_append(output, str_cget(name1));
+ if(res != RES_OK) goto error;
+
+exit:
+ return res;
+error:
+ fprintf(stderr, "Could not build the name from `%s' and `%s'.\n",
+ str_cget(name0), str_cget(name1));
+ goto exit;
+}
+
static INLINE int
srcvl_side_to_ssol_mask(const enum srcvl_side side)
{
@@ -100,7 +127,7 @@ error:
static res_T
get_anchor_node
(struct solstice* solstice,
- struct solparser_anchor_id anchor_id,
+ const struct solparser_anchor_id anchor_id,
struct solstice_node** out_node)
{
struct solstice_node* node = NULL;
@@ -114,7 +141,6 @@ get_anchor_node
} else {
res = solstice_node_target_create(solstice->allocator, &node);
if(res != RES_OK) goto error;
-
res = htable_anchor_set(&solstice->anchors, &anchor_id.i, &node);
if(res != RES_OK) goto error;
}
@@ -127,6 +153,48 @@ error:
goto exit;
}
+static res_T
+setup_tracking
+ (struct solstice* solstice,
+ struct sanim_tracking* tracking,
+ const struct solparser_target* target)
+{
+ struct solstice_node* anchor_node = NULL;
+ struct str anchor_name;
+ res_T res = RES_OK;
+ ASSERT(solstice && tracking && target);
+
+ str_init(solstice->allocator, &anchor_name);
+
+ switch(target->type) {
+ case SOLPARSER_TARGET_ANCHOR:
+ tracking->policy = TRACKING_NODE_TARGET;
+ res = get_anchor_node(solstice, target->data.anchor, &anchor_node);
+ if(res != RES_OK) goto error;
+ solstice_node_target_get_tracking(anchor_node, tracking);
+ break;
+ case SOLPARSER_TARGET_DIRECTION:
+ tracking->policy = TRACKING_OUT_DIR;
+ d3_set(tracking->data.out_dir.u, target->data.direction);
+ break;
+ case SOLPARSER_TARGET_POSITION:
+ tracking->policy = TRACKING_POINT;
+ d3_set(tracking->data.point.target, target->data.position);
+ tracking->data.point.target_is_local = 0; /* TODO */
+ break;
+ case SOLPARSER_TARGET_SUN:
+ tracking->policy = TRACKING_SUN;
+ break;
+ default: FATAL("Unreachable code.\n"); break;
+ }
+
+exit:
+ str_release(&anchor_name);
+ return res;
+error:
+ goto exit;
+}
+
static struct solstice_node*
create_x_pivot_node
@@ -135,7 +203,6 @@ create_x_pivot_node
{
double n[3];
struct solstice_node* node = NULL;
- struct solstice_node* target = NULL;
const struct solparser_x_pivot* parser_x_pivot = NULL;
struct sanim_pivot anim_pivot = SANIM_PIVOT_NULL;
struct sanim_tracking anim_tracking = SANIM_TRACKING_NULL;
@@ -148,28 +215,8 @@ create_x_pivot_node
d3_set(anim_pivot.data.pivot1.ref_normal, d3(n, 0, 0, 1));
d3_set(anim_pivot.data.pivot1.ref_point, parser_x_pivot->ref_point);
- /* Setup the tracking descriptor */
- switch (parser_x_pivot->target.type) {
- case SOLPARSER_TARGET_ANCHOR:
- anim_tracking.policy = TRACKING_NODE_TARGET;
- target = *htable_anchor_find
- (&solstice->anchors, &parser_x_pivot->target.data.anchor.i);
- solstice_node_target_get_tracking(target, &anim_tracking);
- break;
- case SOLPARSER_TARGET_DIRECTION:
- anim_tracking.policy = TRACKING_OUT_DIR;
- d3_set(anim_tracking.data.out_dir.u, parser_x_pivot->target.data.direction);
- break;
- case SOLPARSER_TARGET_POSITION:
- anim_tracking.policy = TRACKING_POINT;
- d3_set(anim_tracking.data.point.target, parser_x_pivot->target.data.position);
- anim_tracking.data.point.target_is_local = 0; /* TODO */
- break;
- case SOLPARSER_TARGET_SUN:
- anim_tracking.policy = TRACKING_SUN;
- break;
- default: FATAL("Unreachable code.\n"); break;
- }
+ res = setup_tracking(solstice, &anim_tracking, &parser_x_pivot->target);
+ if(res != RES_OK) goto error;
res = solstice_node_pivot_create
(solstice->allocator, &anim_pivot, &anim_tracking, &node);
@@ -194,7 +241,6 @@ create_zx_pivot_node
const struct solparser_entity* entity)
{
struct solstice_node* node = NULL;
- struct solstice_node* target = NULL;
const struct solparser_zx_pivot* parser_zx_pivot = NULL;
struct sanim_pivot anim_pivot = SANIM_PIVOT_NULL;
struct sanim_tracking anim_tracking = SANIM_TRACKING_NULL;
@@ -207,35 +253,15 @@ create_zx_pivot_node
anim_pivot.data.pivot2.spacing = parser_zx_pivot->spacing;
d3_set(anim_pivot.data.pivot2.ref_point, parser_zx_pivot->ref_point);
- /* Setup the tracking descriptor */
- switch (parser_zx_pivot->target.type) {
- case SOLPARSER_TARGET_ANCHOR:
- anim_tracking.policy = TRACKING_NODE_TARGET;
- CHECK(RES_OK,
- get_anchor_node(solstice, parser_zx_pivot->target.data.anchor, &target));
- solstice_node_target_get_tracking(target, &anim_tracking);
- break;
- case SOLPARSER_TARGET_DIRECTION:
- anim_tracking.policy = TRACKING_OUT_DIR;
- d3_set(anim_tracking.data.out_dir.u, parser_zx_pivot->target.data.direction);
- break;
- case SOLPARSER_TARGET_POSITION:
- anim_tracking.policy = TRACKING_POINT;
- d3_set(anim_tracking.data.point.target, parser_zx_pivot->target.data.position);
- anim_tracking.data.point.target_is_local = 0; /* TODO */
- break;
- case SOLPARSER_TARGET_SUN:
- anim_tracking.policy = TRACKING_SUN;
- break;
- default: FATAL("Unreachable code.\n"); break;
- }
+ res = setup_tracking(solstice, &anim_tracking, &parser_zx_pivot->target);
+ if(res != RES_OK) goto error;
res = solstice_node_pivot_create
(solstice->allocator, &anim_pivot, &anim_tracking, &node);
- if (res != RES_OK) goto error;
+ if(res != RES_OK) goto error;
res = darray_nodes_push_back(&solstice->pivots, &node);
- if (res != RES_OK) goto error;
+ if(res != RES_OK) goto error;
exit:
return node;
@@ -257,12 +283,14 @@ create_node
struct solstice_node* child = NULL;
struct solstice_receiver* rcv = NULL;
struct str child_name;
+ struct str anchor_name;
double rotation[3];
size_t i;
res_T res = RES_OK;
ASSERT(solstice && entity && name);
str_init(solstice->allocator, &child_name);
+ str_init(solstice->allocator, &anchor_name);
/* Create the entity node */
switch(entity->type) {
@@ -333,6 +361,9 @@ create_node
id = solparser_entity_get_anchor(entity, i);
anchor = solparser_get_anchor(solstice->parser, id);
+ res = merge_name(&anchor_name, name, &anchor->name);
+ if(res != RES_OK) goto error;
+
res = get_anchor_node(solstice, id, &tgt);
if(res != RES_OK) goto error;
@@ -353,15 +384,8 @@ create_node
id = solparser_entity_get_child(entity, i);
child_entity = solparser_get_entity(solstice->parser, id);
- #define CALL(Func) \
- if(RES_OK != (res = Func)) { \
- fprintf(stderr, "Could not build the absolute entity name.\n"); \
- goto error; \
- } (void)0
- CALL(str_copy(&child_name, name));
- CALL(str_append_char(&child_name, '.'));
- CALL(str_append(&child_name, str_cget(&child_entity->name)));
- #undef CALL
+ res = merge_name(&child_name, name, &child_entity->name);
+ if(res != RES_OK) goto error;
child = create_node(solstice, child_entity, &child_name);
if(!child) goto error;
@@ -375,6 +399,7 @@ create_node
exit:
str_release(&child_name);
+ str_release(&anchor_name);
return node;
error:
if(child) solstice_node_ref_put(child);