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