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@0: #include nuclear@0: #include nuclear@0: #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@0: struct anm_node { nuclear@0: char *name; nuclear@0: nuclear@0: struct anm_track tracks[ANM_NUM_TRACKS]; 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@0: /* matrix calculated by anm_eval functions (no locking, meant as a pre-pass) */ nuclear@0: mat4_t matrix; nuclear@0: 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@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: void anm_set_interpolator(struct anm_node *node, enum anm_interpolator in); nuclear@0: void anm_set_extrapolator(struct anm_node *node, enum anm_extrapolator ex); 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@0: void anm_clear(struct anm_node *node); nuclear@0: 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@0: void anm_set_pivot(struct anm_node *node, vec3_t pivot); nuclear@0: vec3_t anm_get_pivot(struct anm_node *node); nuclear@0: nuclear@0: /* those return the start and end times of the whole tree */ nuclear@0: anm_time_t anm_get_start_time(struct anm_node *node); nuclear@0: anm_time_t anm_get_end_time(struct anm_node *node); nuclear@0: nuclear@0: /* these calculate the matrix and inverse matrix of this node alone */ nuclear@0: void anm_get_node_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm); nuclear@0: void anm_get_node_inv_matrix(struct anm_node *node, mat4_t mat, anm_time_t tm); nuclear@0: nuclear@0: /* ---- top-down matrix calculation interface ---- */ nuclear@0: nuclear@0: /* calculate and set the matrix of this node */ nuclear@0: void anm_eval_node(struct anm_node *node, anm_time_t tm); nuclear@0: /* calculate and set the matrix of this node and all its children recursively */ nuclear@0: void anm_eval(struct anm_node *node, anm_time_t tm); nuclear@0: nuclear@0: nuclear@0: /* ---- bottom-up lazy matrix calculation interface ---- */ nuclear@0: nuclear@0: /* These calculate the matrix and inverse matrix of this node taking hierarchy nuclear@0: * into account. The results are cached in thread-specific storage and returned nuclear@0: * if there's no change in time or tracks from the last query... nuclear@0: */ 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_ */