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:
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;
+}