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 c6424b5d931a5fbaa9e54e73fe146b33c7bc653c
parent bfcb670e830daabbcd391dd9b1adad72f365b5db
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed, 12 Oct 2016 16:01:39 +0200

Add pivot nodes.

Diffstat:
Mcmake/CMakeLists.txt | 1+
Msrc/sanim.h | 30++++++++++++++++++++++++++++++
Msrc/sanim_node.c | 36++++++++++++++++++++++++++++++++++++
Msrc/sanim_node_c.h | 2++
Asrc/test_sanim_node_pivot.c | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 173 insertions(+), 0 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -100,6 +100,7 @@ if(NOT NO_TEST) new_test(test_sanim_device) new_test(test_sanim_node_transform) + new_test(test_sanim_node_pivot) endif() ################################################################################ diff --git a/src/sanim.h b/src/sanim.h @@ -54,6 +54,30 @@ struct sanim_node { struct sanim_node_data* data; }; +/* types to describe pivots */ +enum pivot_type { + SINGLE_AXIS, + TWO_AXIS, + + PIVOT_TYPE_COUNT__ +}; + +struct sanim_pivot_1 { + double angle; +}; + +struct sanim_pivot_2 { + double angle; +}; + +struct sanim_pivot { + enum pivot_type type; + union data { + struct sanim_pivot_1 pivot1; + struct sanim_pivot_2 pivot2; + } data; +}; + BEGIN_DECLS /******************************************************************************* @@ -85,6 +109,12 @@ sanim_node_initialize struct sanim_node* node); SANIM_API res_T +sanim_node_initialize_pivot + (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + const struct sanim_pivot* pivot, + struct sanim_node* node); + +SANIM_API res_T sanim_node_release (struct sanim_node* node); diff --git a/src/sanim_node.c b/src/sanim_node.c @@ -37,6 +37,16 @@ is_ascendant return 0; } +static int +is_after_pivot(const struct sanim_node_data* data) { + ASSERT(data); + while (data) { + if (data->pivot) return 1; + data = data->father; + } + return 0; +} + static double* node_get_transform(struct sanim_node_data* data, double transform[16]) { double tmp[12]; @@ -75,6 +85,7 @@ sanim_node_add_child if (!node || !child) return RES_BAD_ARG; if (child->data->father) return RES_BAD_ARG; if (is_ascendant(node->data, child->data)) return RES_BAD_ARG; + if (child->data->pivot && is_after_pivot(node->data)) return RES_BAD_ARG; child->data->father = node->data; res = darray_children_push_back(&node->data->children, &child->data); @@ -111,6 +122,7 @@ sanim_node_initialize darray_children_init(alloc, &node->data->children); node->data->father = NULL; node->data->allocator = alloc; + node->data->pivot = NULL; d3_splat(node->data->translation, 0); d3_splat(node->data->rotations, 0); @@ -125,6 +137,30 @@ error: } res_T +sanim_node_initialize_pivot + (struct mem_allocator* allocator, + const struct sanim_pivot* pivot, + struct sanim_node* node) +{ + res_T res; + + if (!pivot) return RES_BAD_ARG; + res = sanim_node_initialize(allocator, node); + if (res != RES_OK) goto error; + + *node->data->pivot = *pivot; + +exit: + return res; +error: + if (node->data) { + darray_children_release(&node->data->children); + node->data = NULL; + } + goto exit; +} + +res_T sanim_node_release (struct sanim_node* node) { diff --git a/src/sanim_node_c.h b/src/sanim_node_c.h @@ -17,6 +17,7 @@ #define SANIM_NODE_C_H struct mem_allocator; +struct sanim_pivot; #include <rsys/dynamic_array.h> @@ -31,6 +32,7 @@ struct sanim_node_data { struct sanim_node_data* father; /* can be NULL: root node */ struct darray_children children; struct mem_allocator* allocator; + struct sanim_pivot* pivot; }; diff --git a/src/test_sanim_node_pivot.c b/src/test_sanim_node_pivot.c @@ -0,0 +1,104 @@ +/* Copyright (C) CNRS 2016 +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "sanim.h" +#include "test_sanim_utils.h" + +#include <rsys/double33.h> + +int +main(int argc, char** argv) +{ + struct mem_allocator allocator; + struct my_type t1, t2, t3, t; + double transl[3], rot[3], transform[12], transform2[12]; + (void) argc, (void) argv; + + mem_init_proxy_allocator(&allocator, &mem_default_allocator); + + /* test a typical use in my_type */ + CHECK(my_type_init(NULL, &t1), RES_OK); + CHECK(my_type_release(NULL), RES_BAD_ARG); + CHECK(my_type_release(&t1), RES_OK); + CHECK(my_type_init(&allocator, &t1), RES_OK); + CHECK(my_type_init(&allocator, NULL), RES_BAD_ARG); + CHECK(my_type_init(&allocator, &t2), RES_OK); + + CHECK(my_type_add_child(NULL, &t1), RES_BAD_ARG); + CHECK(my_type_add_child(&t1, NULL), RES_BAD_ARG); + CHECK(my_type_add_child(&t1, &t1), RES_BAD_ARG); + CHECK(my_type_add_child(&t1, &t2), RES_OK); + CHECK(my_type_add_child(&t1, &t2), RES_BAD_ARG); + CHECK(my_type_add_child(&t2, &t1), RES_BAD_ARG); + + d3_splat(transl, +1); + CHECK(my_type_set_translation(NULL, transl), RES_BAD_ARG); + CHECK(my_type_set_translation(&t1, NULL), RES_BAD_ARG); + CHECK(my_type_set_translation(&t1, transl), RES_OK); + + d3_splat(transl, -1); + CHECK(my_type_set_translation(&t2, transl), RES_OK); + + CHECK(my_type_get_world_transform(NULL, transform), RES_BAD_ARG); + CHECK(my_type_get_world_transform(&t2, NULL), RES_BAD_ARG); + CHECK(my_type_get_world_transform(&t2, transform), RES_OK); + CHECK(d33_is_identity(transform), 1); + CHECK(d3_is_zero(transform + 9), 1); + + d3(rot, PI, 0, 0); + CHECK(my_type_set_rotations(NULL, rot), RES_BAD_ARG); + CHECK(my_type_set_rotations(&t1, NULL), RES_BAD_ARG); + CHECK(my_type_set_rotations(&t1, rot), RES_OK); + CHECK(my_type_set_rotations(&t2, rot), RES_OK); + d3(transl, 0, +1, 0); + CHECK(my_type_set_translation(&t1, transl), RES_OK); + CHECK(my_type_set_translation(&t2, transl), RES_OK); + + CHECK(my_type_get_world_transform(&t2, transform), RES_OK); + CHECK(d33_is_identity_eps(transform, 1e-10), 1); + CHECK(d3_is_zero_eps(transform + 9, 1e-10), 1); + + /* check 1 node with 3 rotations VS 3 chained nodes with 1 rotation each */ + d3(rot, 0.17, -0.52, 0.31); + d3(transl, 0.3, 2, -1); + CHECK(my_type_init(&allocator, &t), RES_OK); + CHECK(my_type_set_translation(&t, transl), RES_OK); + CHECK(my_type_set_rotations(&t, rot), RES_OK); + CHECK(my_type_get_world_transform(&t, transform), RES_OK); + CHECK(my_type_init(&allocator, &t3), RES_OK); + CHECK(my_type_add_child(&t2, &t3), RES_OK); + d3(rot, 0.17, 0, 0); + CHECK(my_type_set_translation(&t1, transl), RES_OK); + CHECK(my_type_set_rotations(&t1, rot), RES_OK); + d3(transl, 0, 0, 0); + d3(rot, 0, -0.52, 0); + CHECK(my_type_set_translation(&t2, transl), RES_OK); + CHECK(my_type_set_rotations(&t2, rot), RES_OK); + d3(rot, 0, 0, 0.31); + CHECK(my_type_set_translation(&t3, transl), RES_OK); + CHECK(my_type_set_rotations(&t3, rot), RES_OK); + CHECK(my_type_get_world_transform(&t3, transform2), RES_OK); + CHECK(d33_eq_eps(transform, transform2, 1e-10), 1); + + CHECK(my_type_release(&t1), RES_OK); + CHECK(my_type_release(&t2), RES_OK); + CHECK(my_type_release(&t3), RES_OK); + CHECK(my_type_release(&t), RES_OK); + + check_memory_allocator(&allocator); + mem_shutdown_proxy_allocator(&allocator); + CHECK(mem_allocated_size(), 0); + return 0; +}