nuclear@0: #ifndef LIBANIM_H_ nuclear@0: #define LIBANIM_H_ nuclear@0: nuclear@0: #include "config.h" nuclear@0: nuclear@0: #include nuclear@0: nuclear@1: #include nuclear@1: #include nuclear@1: #include nuclear@0: #include "track.h" nuclear@0: nuclear@0: enum { nuclear@0: ANM_TRACK_POS_X, nuclear@0: ANM_TRACK_POS_Y, nuclear@0: ANM_TRACK_POS_Z, nuclear@0: nuclear@0: ANM_TRACK_ROT_X, nuclear@0: ANM_TRACK_ROT_Y, nuclear@0: ANM_TRACK_ROT_Z, nuclear@0: ANM_TRACK_ROT_W, nuclear@0: nuclear@0: ANM_TRACK_SCL_X, nuclear@0: ANM_TRACK_SCL_Y, nuclear@0: ANM_TRACK_SCL_Z, nuclear@0: nuclear@0: ANM_NUM_TRACKS nuclear@0: }; nuclear@0: nuclear@21: struct anm_animation { nuclear@21: char *name; nuclear@21: struct anm_track tracks[ANM_NUM_TRACKS]; nuclear@21: }; nuclear@21: nuclear@0: struct anm_node { nuclear@0: char *name; nuclear@0: nuclear@21: int cur_anim[2]; nuclear@24: anm_time_t cur_anim_offset[2]; nuclear@21: float cur_mix; nuclear@21: nuclear@24: /* high-level animation blending transition duration */ nuclear@24: anm_time_t blend_dur; nuclear@24: nuclear@21: struct anm_animation *animations; nuclear@0: vec3_t pivot; nuclear@0: nuclear@0: /* matrix cache */ nuclear@0: struct mat_cache { nuclear@0: mat4_t matrix, inv_matrix; nuclear@0: anm_time_t time, inv_time; nuclear@0: struct mat_cache *next; nuclear@0: } *cache_list; nuclear@0: pthread_key_t cache_key; nuclear@0: pthread_mutex_t cache_list_lock; nuclear@0: nuclear@20: /* matrix calculated by anm_eval functions (no locking, meant as a pre-pass) */ nuclear@20: mat4_t matrix; nuclear@20: nuclear@0: struct anm_node *parent; nuclear@0: struct anm_node *child; nuclear@0: struct anm_node *next; nuclear@0: }; nuclear@0: nuclear@0: #ifdef __cplusplus nuclear@0: extern "C" { nuclear@0: #endif nuclear@0: nuclear@21: int anm_init_animation(struct anm_animation *anim); nuclear@21: void anm_destroy_animation(struct anm_animation *anim); nuclear@21: nuclear@22: void anm_set_animation_name(struct anm_animation *anim, const char *name); nuclear@22: nuclear@22: nuclear@24: /* ---- node/hierarchy management ---- */ nuclear@24: nuclear@0: /* node constructor and destructor */ nuclear@0: int anm_init_node(struct anm_node *node); nuclear@0: void anm_destroy_node(struct anm_node *node); nuclear@0: nuclear@0: /* recursively destroy an animation node tree */ nuclear@0: void anm_destroy_node_tree(struct anm_node *tree); nuclear@0: nuclear@0: /* helper functions to allocate/construct and destroy/free with nuclear@0: * a single call. They call anm_init_node and anm_destroy_node nuclear@0: * internally. nuclear@0: */ nuclear@0: struct anm_node *anm_create_node(void); nuclear@0: void anm_free_node(struct anm_node *node); nuclear@0: nuclear@0: /* recursively destroy and free the nodes of a node tree */ nuclear@0: void anm_free_node_tree(struct anm_node *tree); nuclear@0: nuclear@0: int anm_set_node_name(struct anm_node *node, const char *name); nuclear@0: const char *anm_get_node_name(struct anm_node *node); nuclear@0: nuclear@0: /* link and unlink nodes with parent/child relations */ nuclear@0: void anm_link_node(struct anm_node *parent, struct anm_node *child); nuclear@0: int anm_unlink_node(struct anm_node *parent, struct anm_node *child); nuclear@0: nuclear@21: void anm_set_pivot(struct anm_node *node, vec3_t pivot); nuclear@21: vec3_t anm_get_pivot(struct anm_node *node); nuclear@21: nuclear@24: /* ---- multiple animations and animation blending ---- */ nuclear@24: nuclear@21: /* set active animation(s) */ nuclear@21: int anm_use_node_animation(struct anm_node *node, int aidx); nuclear@21: int anm_use_node_animations(struct anm_node *node, int aidx, int bidx, float t); nuclear@21: /* recursive variants */ nuclear@21: int anm_use_animation(struct anm_node *node, int aidx); nuclear@21: int anm_use_animations(struct anm_node *node, int aidx, int bidx, float t); nuclear@21: nuclear@24: /* set/get current animation offset(s) */ nuclear@24: void anm_set_node_animation_offset(struct anm_node *node, anm_time_t offs, int which); nuclear@24: anm_time_t anm_get_animation_offset(const struct anm_node *node, int which); nuclear@24: /* recursive variant */ nuclear@24: void anm_set_animation_offset(struct anm_node *node, anm_time_t offs, int which); nuclear@24: nuclear@21: /* returns the requested current animation index, which can be 0 or 1 */ nuclear@24: int anm_get_active_animation_index(const struct anm_node *node, int which); nuclear@21: /* returns the requested current animation, which can be 0 or 1 */ nuclear@24: struct anm_animation *anm_get_active_animation(const struct anm_node *node, int which); nuclear@24: float anm_get_active_animation_mix(const struct anm_node *node); nuclear@21: nuclear@24: int anm_get_animation_count(const struct anm_node *node); nuclear@21: nuclear@21: /* add/remove an animation to the specified node */ nuclear@21: int anm_add_node_animation(struct anm_node *node); nuclear@21: int anm_remove_node_animation(struct anm_node *node, int idx); nuclear@21: nuclear@21: /* add/remove an animation to the specified node and all it's descendants */ nuclear@21: int anm_add_animation(struct anm_node *node); nuclear@21: int anm_remove_animation(struct anm_node *node, int idx); nuclear@21: nuclear@21: struct anm_animation *anm_get_animation(struct anm_node *node, int idx); nuclear@21: struct anm_animation *anm_get_animation_by_name(struct anm_node *node, const char *name); nuclear@21: nuclear@21: int anm_find_animation(struct anm_node *node, const char *name); nuclear@21: nuclear@21: /* set the interpolator for the (first) currently active animation */ nuclear@21: void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in); nuclear@21: /* set the extrapolator for the (first) currently active animation */ nuclear@21: void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex); nuclear@21: nuclear@23: /* set the name of the currently active animation of this node only */ nuclear@23: void anm_set_node_active_animation_name(struct anm_node *node, const char *name); nuclear@23: /* recursively set the name of the currently active animation for this node nuclear@23: * and all it's descendants */ nuclear@23: void anm_set_active_animation_name(struct anm_node *node, const char *name); nuclear@23: /* get the name of the currently active animation of this node */ nuclear@23: const char *anm_get_active_animation_name(struct anm_node *node); nuclear@23: nuclear@24: nuclear@24: /* ---- high level animation blending interface ---- */ nuclear@24: /* XXX this convenience interface assumes monotonically increasing time values nuclear@24: * in all subsequent calls to anm_get_* and anm_eval_* functions. nuclear@24: * nuclear@24: * anmidx: index of the animation to transition to nuclear@24: * start: when to start the transition nuclear@24: * dur: transition duration nuclear@24: * nuclear@24: * sets up a transition from the current animation (cur_anim[0]) to another animation. nuclear@24: * at time start + dur, the transition will be completed, cur_anim[0] will be the new nuclear@24: * animation and cur_anim_offset[0] will be equal to start. nuclear@24: */ nuclear@24: void anm_transition(struct anm_node *node, int anmidx, anm_time_t start, anm_time_t dur); nuclear@24: /* non-recursive variant, acts on a single node (you probably DON'T want to use this) */ nuclear@24: void anm_node_transition(struct anm_node *node, int anmidx, anm_time_t start, anm_time_t dur); nuclear@24: nuclear@24: nuclear@24: /* ---- keyframes / PRS interpolation ---- */ nuclear@24: nuclear@0: void anm_set_position(struct anm_node *node, vec3_t pos, anm_time_t tm); nuclear@0: vec3_t anm_get_node_position(struct anm_node *node, anm_time_t tm); nuclear@0: nuclear@0: void anm_set_rotation(struct anm_node *node, quat_t rot, anm_time_t tm); nuclear@0: quat_t anm_get_node_rotation(struct anm_node *node, anm_time_t tm); nuclear@0: nuclear@0: void anm_set_scaling(struct anm_node *node, vec3_t scl, anm_time_t tm); nuclear@0: vec3_t anm_get_node_scaling(struct anm_node *node, anm_time_t tm); nuclear@0: nuclear@0: /* these three return the full p/r/s taking hierarchy into account */ nuclear@0: vec3_t anm_get_position(struct anm_node *node, anm_time_t tm); nuclear@0: quat_t anm_get_rotation(struct anm_node *node, anm_time_t tm); nuclear@0: vec3_t anm_get_scaling(struct anm_node *node, anm_time_t tm); nuclear@0: nuclear@20: /* those return the start and end times of the whole tree */ nuclear@20: anm_time_t anm_get_start_time(struct anm_node *node); nuclear@20: anm_time_t anm_get_end_time(struct anm_node *node); nuclear@20: nuclear@24: nuclear@24: /* ---- transformation matrices ---- */ nuclear@24: nuclear@5: /* these calculate the matrix and inverse matrix of this node alone */ nuclear@5: void anm_get_node_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm); nuclear@5: void anm_get_node_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm); nuclear@5: nuclear@20: /* ---- top-down matrix calculation interface ---- */ nuclear@20: nuclear@20: /* calculate and set the matrix of this node */ nuclear@20: void anm_eval_node(struct anm_node *node, anm_time_t tm); nuclear@20: /* calculate and set the matrix of this node and all its children recursively */ nuclear@20: void anm_eval(struct anm_node *node, anm_time_t tm); nuclear@20: nuclear@20: nuclear@20: /* ---- bottom-up lazy matrix calculation interface ---- */ nuclear@20: nuclear@5: /* These calculate the matrix and inverse matrix of this node taking hierarchy nuclear@5: * into account. The results are cached in thread-specific storage and returned nuclear@5: * if there's no change in time or tracks from the last query... nuclear@5: */ nuclear@0: void anm_get_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm); nuclear@0: void anm_get_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm); nuclear@0: nuclear@0: #ifdef __cplusplus nuclear@0: } nuclear@0: #endif nuclear@0: nuclear@0: #endif /* LIBANIM_H_ */