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 c7b767c0ca9c3eafdf1698ebbc2f8cdabb0c606e
parent c887a616d14d62e83555860570106fce20d74210
Author: Christophe Coustet <christophe.coustet@meso-star.com>
Date:   Wed,  9 Nov 2016 14:36:19 +0100

Add visit_tree ans is_initialized API calls.

Diffstat:
Msrc/sanim.h | 30++++++++++++++++++++----------
Msrc/sanim_node.c | 128+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
2 files changed, 113 insertions(+), 45 deletions(-)

diff --git a/src/sanim.h b/src/sanim.h @@ -89,10 +89,6 @@ enum tracking_policy { TRACKING_TYPES_COUNT }; -struct sanim_policy_sun { - char unused; -}; - struct sanim_policy_point { /* target can be in local space (ie in the same system than the pivot) * or in world space */ @@ -107,7 +103,6 @@ struct sanim_policy_out_dir { struct sanim_tracking { enum tracking_policy policy; union { - struct sanim_policy_sun sun; struct sanim_policy_point point; struct sanim_policy_out_dir out_dir; } data; @@ -119,30 +114,45 @@ BEGIN_DECLS ******************************************************************************/ SANIM_API res_T sanim_node_initialize - (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + (struct mem_allocator* allocator, struct sanim_node* node); SANIM_API res_T sanim_node_initialize_pivot - (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + (struct mem_allocator* allocator, const struct sanim_pivot* pivot, const struct sanim_tracking* tracking, struct sanim_node* node); /* simple copy, no recursion - * copy content of src into node that must be valid * copy rotations, translation and possible pivot information */ SANIM_API res_T sanim_node_copy_initialize - (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + (struct mem_allocator* allocator, const struct sanim_node* src, - struct sanim_node* node); + struct sanim_node* dst); + +SANIM_API res_T +sanim_node_is_initialized + (const struct sanim_node* node, + int* initialized); SANIM_API res_T sanim_node_solve_pivot (struct sanim_node* node, const double in_dir[3]); +/* Visit the (sub)tree starting at node + * Solve pivots if any + * Call visitor on every node of the tree with its updated transform + * Visit stops if a call to visitor return is not RES_OK */ +SANIM_API res_T +sanim_node_visit_tree + (struct sanim_node* node, + const double in_dir[3], + void* data, + res_T (*visitor)(const struct sanim_node* n, const double transform[12], void* data)); + SANIM_API res_T sanim_node_release (struct sanim_node* node); diff --git a/src/sanim_node.c b/src/sanim_node.c @@ -718,6 +718,55 @@ copy_and_normalise_pivot_data return RES_OK; } +static res_T +node_solve_pivot + (struct sanim_node* node, + const double in_dir[3]) +{ + ASSERT(node && node->data && in_dir && node->data->pivot_data); + ASSERT(d3_is_normalized(in_dir)); + + switch (node->data->pivot_data->pivot.type) { + case PIVOT_SINGLE_AXIS: + return pivot_solve_single_axis(node, in_dir); + break; + case PIVOT_TWO_AXIS: + return pivot_solve_two_axis(node, in_dir); + break; + default: FATAL("Unreachable code.\n"); break; + } +} + +static res_T +visit_tree + (struct sanim_node* node, + const double in_dir[3], + void* data, + res_T(*visitor) + (const struct sanim_node* n, const double transform[12], void* data)) +{ + double transform[12]; + size_t count, i; + struct sanim_node* const* children; + res_T res = RES_OK; + ASSERT(node && node->data && in_dir && visitor); + ASSERT(d3_is_normalized(in_dir)); + if (node->data->pivot_data) { + node_solve_pivot(node, in_dir); + node_get_transform(node, 1, transform); + res = visitor(node, transform, data); + if (res != RES_OK) return res; + } + count = darray_children_size_get(&node->data->children); + children = darray_children_data_get(&node->data->children); + for (i = 0; i < count; i++) { + struct sanim_node* child = children[i]; + res = visit_tree(child, in_dir, data, visitor); + if (res != RES_OK) return res; + } + return RES_OK; +} + /******************************************************************************* * Exported sanim_node functions ******************************************************************************/ @@ -755,20 +804,17 @@ sanim_node_initialize (struct mem_allocator* allocator, struct sanim_node* node) { - struct mem_allocator* alloc; res_T res = RES_OK; - if (!node) return RES_BAD_ARG; - alloc = allocator ? allocator : &mem_default_allocator; - - node->data = MEM_CALLOC(alloc, 1, sizeof(struct node_data)); + if (!allocator || !node) return RES_BAD_ARG; + node->data = MEM_CALLOC(allocator, 1, sizeof(struct node_data)); if (!node->data) { res = RES_MEM_ERR; goto error; } - darray_children_init(alloc, &node->data->children); - node->data->allocator = alloc; + darray_children_init(allocator, &node->data->children); + node->data->allocator = allocator; exit: return res; @@ -787,15 +833,13 @@ sanim_node_initialize_pivot const struct sanim_tracking* tracking, struct sanim_node* node) { - struct mem_allocator* alloc; res_T res = RES_OK; - if (!node || !pivot || !tracking) return RES_BAD_ARG; + if (!allocator || !node || !pivot || !tracking) return RES_BAD_ARG; res = sanim_node_initialize(allocator, node); if (res != RES_OK) goto error; - alloc = allocator ? allocator : &mem_default_allocator; - node->data->pivot_data = MEM_CALLOC(alloc, 1, sizeof(struct pivot_data)); + node->data->pivot_data = MEM_CALLOC(allocator, 1, sizeof(struct pivot_data)); if (!node->data->pivot_data) { res = RES_MEM_ERR; goto error; @@ -813,57 +857,71 @@ error: res_T sanim_node_copy_initialize - (struct mem_allocator* allocator, /* May be NULL <=> use default allocator */ + (struct mem_allocator* allocator, const struct sanim_node* src, - struct sanim_node* node) + struct sanim_node* dst) { res_T res = RES_OK; - if (!node || !src) return RES_BAD_ARG; - res = sanim_node_initialize(allocator, node); + if (!allocator || !src || !dst) return RES_BAD_ARG; + res = sanim_node_initialize(allocator, dst); if (res != RES_OK) goto error; if (src->data->pivot_data) { - node->data->pivot_data - = MEM_CALLOC(node->data->allocator, 1, sizeof(struct pivot_data)); - if (!node->data->pivot_data) { + dst->data->pivot_data = MEM_CALLOC(allocator, 1, sizeof(struct pivot_data)); + if (!dst->data->pivot_data) { res = RES_MEM_ERR; goto error; } - node->data->pivot_data->angleX = src->data->pivot_data->angleX; - node->data->pivot_data->angleZ = src->data->pivot_data->angleZ; - node->data->pivot_data->pivot = src->data->pivot_data->pivot; - node->data->pivot_data->tracking = src->data->pivot_data->tracking; + dst->data->pivot_data->angleX = src->data->pivot_data->angleX; + dst->data->pivot_data->angleZ = src->data->pivot_data->angleZ; + dst->data->pivot_data->pivot = src->data->pivot_data->pivot; + dst->data->pivot_data->tracking = src->data->pivot_data->tracking; } - d3_set(node->data->rotations, src->data->rotations); - d3_set(node->data->translation, src->data->translation); + d3_set(dst->data->rotations, src->data->rotations); + d3_set(dst->data->translation, src->data->translation); exit: return res; error: - sanim_node_release(node); + sanim_node_release(dst); goto exit; } res_T +sanim_node_is_initialized + (const struct sanim_node* node, + int* initialized) +{ + if (!node || !initialized) return RES_BAD_ARG; + *initialized = (node->data != NULL); + return RES_OK; +} + +res_T sanim_node_solve_pivot (struct sanim_node* node, const double in_dir[3]) { double dir[3]; - if (!node || !in_dir) return RES_BAD_ARG; + if (!node || !node->data || !in_dir) return RES_BAD_ARG; if (!node->data->pivot_data) return RES_BAD_ARG; if (!d3_normalize(dir, in_dir)) return RES_BAD_ARG; - switch (node->data->pivot_data->pivot.type) { - case PIVOT_SINGLE_AXIS: - return pivot_solve_single_axis(node, dir); - break; - case PIVOT_TWO_AXIS: - return pivot_solve_two_axis(node, dir); - break; - default: FATAL("Unreachable code.\n"); break; - } + return node_solve_pivot(node, dir); +} + +res_T +sanim_node_visit_tree + (struct sanim_node* node, + const double in_dir[3], + void* data, + res_T (*visitor)(const struct sanim_node* n, const double transform[12], void* data)) +{ + double dir[3]; + if (!node || !node->data || !in_dir || !visitor) return RES_BAD_ARG; + if (!d3_normalize(dir, in_dir)) return RES_BAD_ARG; + return visit_tree(node, dir, data, visitor); } res_T