solstice-anim

Geometry animation library of the solstice app
git clone git://git.meso-star.com/solstice-anim.git
Log | Files | Refs | README | LICENSE

commit 2d0a891a65ab0dab24bd695873c1cb7ef0e9f002
parent 354b81789c7838643a54dff8f964284f5d23cae9
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Thu, 10 Nov 2016 16:41:54 +0100

Add node tracking stuff for pivots.

Diffstat:
Msrc/sanim.h | 13++++++++++++-
Msrc/sanim_node.c | 77++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/test_sanim_node.c | 8++++++++
Msrc/test_sanim_node_pivot.c | 61++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/test_sanim_utils.c | 5+++++
Msrc/test_sanim_utils.h | 3+++
6 files changed, 150 insertions(+), 17 deletions(-)

diff --git a/src/sanim.h b/src/sanim.h @@ -84,6 +84,7 @@ struct sanim_pivot { enum tracking_policy { TRACKING_SUN, /* orient the device to face the sun */ TRACKING_POINT, /* direct the output flux towards a point */ + TRACKING_NODE_TARGET, /* direct the output flux towards a ponctual animated target */ TRACKING_OUT_DIR, /* direct the output flux towards a given dir */ TRACKING_TYPES_COUNT @@ -96,6 +97,10 @@ struct sanim_policy_point { char target_is_local; }; +struct sanim_policy_node_target { + const struct sanim_node* tracked_node; +}; + struct sanim_policy_out_dir { double u[3]; /* in world space */ }; @@ -104,6 +109,7 @@ struct sanim_tracking { enum tracking_policy policy; union { struct sanim_policy_point point; + struct sanim_policy_node_target node_target; struct sanim_policy_out_dir out_dir; } data; }; @@ -155,6 +161,11 @@ sanim_node_visit_tree const struct sanim_node* n, const double transform[12], void* data)); SANIM_API res_T +sanim_node_track_me + (const struct sanim_node* node, + struct sanim_tracking* tracking); + +SANIM_API res_T sanim_node_release (struct sanim_node* node); @@ -185,7 +196,7 @@ sanim_node_get_rotations SANIM_API res_T sanim_node_get_transform - (struct sanim_node* node, + (const struct sanim_node* node, double transform[12]); /* 3x4 column major matrix */ SANIM_API res_T diff --git a/src/sanim_node.c b/src/sanim_node.c @@ -182,7 +182,7 @@ get_pivot_transform(const struct pivot_data* pivot, double transform[12]) { static double* node_get_own_transform - (struct sanim_node* node, + (const struct sanim_node* node, const int include_pivot, double transform[12]) { @@ -202,7 +202,7 @@ node_get_own_transform } static double* -compose_node_transform(struct sanim_node* node, double accum[12]) { +compose_node_transform(const struct sanim_node* node, double accum[12]) { double local[12]; ASSERT(node && node->data && accum); if (node->data->pivot_data) { @@ -216,11 +216,11 @@ compose_node_transform(struct sanim_node* node, double accum[12]) { static void node_get_transform - (struct sanim_node* node, + (const struct sanim_node* node, const int include_own_pivot, double transform[12]) { - struct sanim_node* father; + const struct sanim_node* father; ASSERT(node && node->data && transform); father = node->data->father; node_get_own_transform(node, include_own_pivot, transform); @@ -304,7 +304,8 @@ pivot_solve_single_axis_line pivot_data = node->data->pivot_data; ASSERT(pivot_data); ASSERT(pivot_data->pivot.type == PIVOT_SINGLE_AXIS); - ASSERT(pivot_data->tracking.policy == TRACKING_POINT); + ASSERT(pivot_data->tracking.policy == TRACKING_POINT + || pivot_data->tracking.policy == TRACKING_NODE_TARGET); ASSERT(d3_is_normalized(in_dir)); ref_normal_2D = pivot_data->pivot.data.pivot1.ref_normal + 1; @@ -323,11 +324,24 @@ pivot_solve_single_axis_line } /* get target point in local space */ - if (pivot_data->tracking.data.point.target_is_local) { - d3_set(local_target, pivot_data->tracking.data.point.target); + if (pivot_data->tracking.policy == TRACKING_POINT) { + if (pivot_data->tracking.data.point.target_is_local) { + d3_set(local_target, pivot_data->tracking.data.point.target); + } + else { + d3_sub(local_target, pivot_data->tracking.data.point.target, mat + 9); + d33_muld3(local_target, inv, local_target); + } } else { - d3_sub(local_target, pivot_data->tracking.data.point.target, mat + 9); + double transform[12]; + const struct sanim_node* target + = node->data->pivot_data->tracking.data.node_target.tracked_node; + ASSERT(target && target->data); + ASSERT(pivot_data->tracking.policy == TRACKING_NODE_TARGET); + if (is_after_pivot(target)) return RES_BAD_ARG; + SANIM(node_get_transform(target, transform)); + d3_sub(local_target, transform + 9, mat + 9); d33_muld3(local_target, inv, local_target); } @@ -454,6 +468,7 @@ pivot_solve_single_axis res = pivot_solve_single_axis_sun(node, in_dir); break; case TRACKING_POINT: + case TRACKING_NODE_TARGET: /* track the X line that includes ref_point */ res = pivot_solve_single_axis_line(node, in_dir); break; @@ -529,7 +544,8 @@ pivot_solve_two_axis_point pivot_data = node->data->pivot_data; ASSERT(pivot_data); ASSERT(pivot_data->pivot.type == PIVOT_TWO_AXIS); - ASSERT(pivot_data->tracking.policy == TRACKING_POINT); + ASSERT(pivot_data->tracking.policy == TRACKING_POINT + || pivot_data->tracking.policy == TRACKING_NODE_TARGET); ASSERT(d3_is_normalized(in_dir)); d3_set(ref_point, pivot_data->pivot.data.pivot2.ref_point); @@ -542,11 +558,24 @@ pivot_solve_two_axis_point ASSERT(d3_is_normalized(local_in)); /* get target point in local space */ - if (pivot_data->tracking.data.point.target_is_local) { - d3_set(local_target, pivot_data->tracking.data.point.target); + if (pivot_data->tracking.policy == TRACKING_POINT) { + if (pivot_data->tracking.data.point.target_is_local) { + d3_set(local_target, pivot_data->tracking.data.point.target); + } + else { + d3_sub(local_target, pivot_data->tracking.data.point.target, mat + 9); + d33_muld3(local_target, inv, local_target); + } } else { - d3_sub(local_target, pivot_data->tracking.data.point.target, mat + 9); + double transform[12]; + const struct sanim_node* target + = node->data->pivot_data->tracking.data.node_target.tracked_node; + ASSERT(target && target->data); + ASSERT(pivot_data->tracking.policy == TRACKING_NODE_TARGET); + if (is_after_pivot(target)) return RES_BAD_ARG; + SANIM(node_get_transform(target, transform)); + d3_sub(local_target, transform + 9, mat + 9); d33_muld3(local_target, inv, local_target); } @@ -666,6 +695,7 @@ pivot_solve_two_axis res = pivot_solve_two_axis_sun(node, in_dir); break; case TRACKING_POINT: + case TRACKING_NODE_TARGET: res = pivot_solve_two_axis_point(node, in_dir); break; case TRACKING_OUT_DIR: @@ -685,7 +715,8 @@ copy_and_normalise_pivot_data dest->pivot.type = pivot->type; switch (pivot->type) { case PIVOT_SINGLE_AXIS: - if (!d3_normalize(dest->pivot.data.pivot1.ref_normal, pivot->data.pivot1.ref_normal)) + if (!d3_normalize( + dest->pivot.data.pivot1.ref_normal, pivot->data.pivot1.ref_normal)) return RES_BAD_ARG; if (dest->pivot.data.pivot1.ref_normal[0]) /* ref_normal not in the YZ plane */ @@ -707,7 +738,12 @@ copy_and_normalise_pivot_data break; case TRACKING_POINT: d3_set(dest->tracking.data.point.target, tracking->data.point.target); - dest->tracking.data.point.target_is_local = tracking->data.point.target_is_local; + dest->tracking.data.point.target_is_local + = tracking->data.point.target_is_local; + break; + case TRACKING_NODE_TARGET: + dest->tracking.data.node_target.tracked_node + = tracking->data.node_target.tracked_node; break; case TRACKING_OUT_DIR: if (!d3_normalize(dest->tracking.data.out_dir.u, tracking->data.out_dir.u)) @@ -926,6 +962,17 @@ sanim_node_visit_tree } res_T +sanim_node_track_me + (const struct sanim_node* node, + struct sanim_tracking* tracking) +{ + if (!node || !node->data || !tracking) return RES_BAD_ARG; + tracking->policy = TRACKING_NODE_TARGET; + tracking->data.node_target.tracked_node = node; + return RES_OK; +} + +res_T sanim_node_release (struct sanim_node* node) { @@ -982,7 +1029,7 @@ sanim_node_get_rotations } res_T -sanim_node_get_transform(struct sanim_node* node, double transform[12]) +sanim_node_get_transform(const struct sanim_node* node, double transform[12]) { if (!node || !node->data || !transform) return RES_BAD_ARG; diff --git a/src/test_sanim_node.c b/src/test_sanim_node.c @@ -129,6 +129,14 @@ main(int argc, char** argv) CHECK(my_type_recursive_copy(&allocator, t1, &t1), RES_BAD_ARG); CHECK(my_type_recursive_copy(&allocator, t1, &ptr), RES_OK); + tracking.policy = TRACKING_POINT; + tracking.data.node_target.tracked_node = NULL; + CHECK(my_type_track_me(NULL, &tracking), RES_BAD_ARG); + CHECK(my_type_track_me(t1, NULL), RES_BAD_ARG); + CHECK(my_type_track_me(t1, &tracking), RES_OK); + CHECK(tracking.policy, TRACKING_NODE_TARGET); + CHECK(&t1->node, tracking.data.node_target.tracked_node); + /* release memory */ CHECK(my_type_ref_put(t1), RES_OK); CHECK(my_type_ref_put(t2), RES_OK); diff --git a/src/test_sanim_node_pivot.c b/src/test_sanim_node_pivot.c @@ -22,7 +22,7 @@ int main(int argc, char** argv) { struct mem_allocator allocator; - struct my_type *t1, *t2, *t3; + struct my_type *t1, *t2, *t3, *target; struct sanim_pivot pivot; struct sanim_tracking tracking; double transform[12]; @@ -257,6 +257,65 @@ main(int argc, char** argv) CHECK(my_type_ref_put(t2), RES_OK); CHECK(my_type_ref_put(t3), RES_OK); + /* 1 axis tracking an invalid node target */ + + d3(pivot.data.pivot1.ref_normal, 0, 0, 1); + d3(pivot.data.pivot1.ref_point, 0, 0, 0); + CHECK(my_type_track_me(t3, &tracking), RES_OK); + + CHECK(my_type_create(&allocator, &t1), RES_OK); + CHECK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2), RES_OK); + CHECK(my_type_create(&allocator, &t3), RES_OK); + + CHECK(my_type_add_child(t1, t2), RES_OK); + CHECK(my_type_add_child(t2, t3), RES_OK); + + CHECK(my_type_set_translation(t1, transl), RES_OK); + CHECK(my_type_set_rotations(t1, rot), RES_OK); + CHECK(my_type_set_translation(t2, transl), RES_OK); + CHECK(my_type_set_translation(t3, transl), RES_OK); + + d3(in_dir, 1, 0.1, 0); + /* target if after a pivot */ + CHECK(my_type_solve_pivot(t2, in_dir), RES_BAD_ARG); + + CHECK(my_type_ref_put(t1), RES_OK); + CHECK(my_type_ref_put(t2), RES_OK); + CHECK(my_type_ref_put(t3), RES_OK); + + /* 1 axis tracking a node target */ + + CHECK(my_type_create(&allocator, &target), RES_OK); + d3(tmp, 0, 0, 10 * sqrt(2)); + CHECK(my_type_set_translation(target, tmp), RES_OK); + + d3(pivot.data.pivot1.ref_normal, 0, 0, 1); + d3(pivot.data.pivot1.ref_point, 0, 0, 0); + CHECK(my_type_track_me(target, &tracking), RES_OK); + + CHECK(my_type_create(&allocator, &t1), RES_OK); + CHECK(my_type_pivot_create(&allocator, &pivot, &tracking, &t2), RES_OK); + CHECK(my_type_create(&allocator, &t3), RES_OK); + + CHECK(my_type_add_child(t1, t2), RES_OK); + CHECK(my_type_add_child(t2, t3), RES_OK); + + CHECK(my_type_set_translation(t1, transl), RES_OK); + CHECK(my_type_set_rotations(t1, rot), RES_OK); + CHECK(my_type_set_translation(t2, transl), RES_OK); + CHECK(my_type_set_translation(t3, transl), RES_OK); + + d3(in_dir, 1, 0.1, 0); + CHECK(my_type_solve_pivot(t2, in_dir), RES_OK); + CHECK(my_type_get_transform(t3, transform), RES_OK); + d33_muld3(n, transform, pivot.data.pivot1.ref_normal); + CHECK(d3_eq_eps(n, d3(tmp, -sqrt(2) / 2, 0, +sqrt(2) / 2), 1e-7), 1); + + CHECK(my_type_ref_put(t1), RES_OK); + CHECK(my_type_ref_put(t2), RES_OK); + CHECK(my_type_ref_put(t3), RES_OK); + CHECK(my_type_ref_put(target), RES_OK); + /* * 2 axis pivots * (using only one axis at a time) diff --git a/src/test_sanim_utils.c b/src/test_sanim_utils.c @@ -314,6 +314,11 @@ my_type_is_pivot(struct my_type* t, int* pivot) { return sanim_node_is_pivot(&t->node, pivot); } +res_T +my_type_track_me(const struct my_type* t, struct sanim_tracking* tracking) { + return sanim_node_track_me(&t->node, tracking); +} + char d3_is_zero_eps(const double v[3], const double eps) { int x; diff --git a/src/test_sanim_utils.h b/src/test_sanim_utils.h @@ -82,6 +82,9 @@ res_T my_type_is_pivot(struct my_type* t, int* pivot); res_T +my_type_track_me(const struct my_type* t, struct sanim_tracking* tracking); + +res_T my_type_get_father (const struct my_type* t, const struct my_type** father);