nuclear@1: #include nuclear@1: #include nuclear@1: #include "xform_node.h" nuclear@47: #include "anim/anim.h" nuclear@47: #include "anim/track.h" nuclear@47: nuclear@47: using namespace g3dimpl; nuclear@1: nuclear@1: static inline anm_interpolator track_interpolator(Interp in); nuclear@1: static inline anm_extrapolator track_extrapolator(Extrap ex); nuclear@1: nuclear@1: XFormNode::XFormNode() nuclear@1: { nuclear@1: anm = new anm_node; nuclear@1: anm_init_node(anm); nuclear@47: parent = 0; nuclear@30: nuclear@47: // TODO read them from anm to get the correct initial values nuclear@47: interp = INTERP_LINEAR; nuclear@47: extrap = EXTRAP_EXTEND; nuclear@1: } nuclear@1: nuclear@1: XFormNode::~XFormNode() nuclear@1: { nuclear@1: anm_destroy_node(anm); nuclear@1: delete anm; nuclear@1: } nuclear@1: nuclear@47: struct anm_node *XFormNode::get_libanim_node() const nuclear@47: { nuclear@47: return anm; nuclear@47: } nuclear@47: nuclear@1: void XFormNode::set_name(const char *name) nuclear@1: { nuclear@1: anm_set_node_name(anm, name); nuclear@1: } nuclear@1: nuclear@1: const char *XFormNode::get_name() const nuclear@1: { nuclear@1: return anm_get_node_name(anm); nuclear@1: } nuclear@1: nuclear@1: void XFormNode::set_interpolator(Interp in) nuclear@1: { nuclear@1: anm_set_interpolator(anm, track_interpolator(in)); nuclear@1: interp = in; nuclear@1: } nuclear@1: nuclear@1: Interp XFormNode::get_interpolator() const nuclear@1: { nuclear@1: return interp; nuclear@1: } nuclear@1: nuclear@1: void XFormNode::set_extrapolator(Extrap ex) nuclear@1: { nuclear@1: anm_set_extrapolator(anm, track_extrapolator(ex)); nuclear@1: extrap = ex; nuclear@1: } nuclear@1: nuclear@1: Extrap XFormNode::get_extrapolator() const nuclear@1: { nuclear@1: return extrap; nuclear@1: } nuclear@1: nuclear@47: XFormNode *XFormNode::get_parent() nuclear@47: { nuclear@47: return parent; nuclear@47: } nuclear@47: nuclear@47: const XFormNode *XFormNode::get_parent() const nuclear@47: { nuclear@47: return parent; nuclear@47: } nuclear@47: nuclear@1: void XFormNode::add_child(XFormNode *child) nuclear@1: { nuclear@1: children.push_back(child); nuclear@1: anm_link_node(anm, child->anm); nuclear@30: child->parent = this; nuclear@1: } nuclear@1: nuclear@1: void XFormNode::remove_child(XFormNode *child) nuclear@1: { nuclear@1: std::vector::iterator it; nuclear@1: it = std::find(children.begin(), children.end(), child); nuclear@1: if(it != children.end()) { nuclear@1: children.erase(it); nuclear@1: anm_unlink_node(anm, child->anm); nuclear@47: nuclear@47: if(child->parent == this) { nuclear@47: child->parent = 0; nuclear@47: } nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: int XFormNode::get_children_count() const nuclear@1: { nuclear@1: return (int)children.size(); nuclear@1: } nuclear@1: nuclear@1: XFormNode *XFormNode::get_child(int idx) nuclear@1: { nuclear@1: if(idx >= 0 && idx < get_children_count()) { nuclear@1: return children[idx]; nuclear@1: } nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@1: const XFormNode *XFormNode::get_child(int idx) const nuclear@1: { nuclear@1: if(idx >= 0 && idx < get_children_count()) { nuclear@1: return children[idx]; nuclear@1: } nuclear@1: return 0; nuclear@1: } nuclear@1: nuclear@47: nuclear@47: void XFormNode::use_animation(int idx) nuclear@30: { nuclear@47: if(idx >= 0) { nuclear@47: anm_use_animation(anm, idx); nuclear@47: } nuclear@30: } nuclear@30: nuclear@47: void XFormNode::use_animation(const char *name) nuclear@47: { nuclear@47: anm_use_animation(anm, anm_find_animation(anm, name)); nuclear@47: } nuclear@47: nuclear@47: void XFormNode::use_animation(int aidx, int bidx, float t) nuclear@47: { nuclear@47: anm_use_animations(anm, aidx, bidx, t); nuclear@47: } nuclear@47: nuclear@47: void XFormNode::use_animation(const char *aname, const char *bname, float t) nuclear@47: { nuclear@47: int aidx = anm_find_animation(anm, aname); nuclear@47: int bidx = anm_find_animation(anm, bname); nuclear@47: nuclear@47: if(aidx == -1) { nuclear@47: use_animation(bidx); nuclear@47: } nuclear@47: if(bidx == -1) { nuclear@47: use_animation(aidx); nuclear@47: } nuclear@47: anm_use_animations(anm, aidx, bidx, t); nuclear@47: } nuclear@47: nuclear@47: int XFormNode::get_active_animation_index(int which) const nuclear@47: { nuclear@47: return anm_get_active_animation_index(anm, which); nuclear@47: } nuclear@47: nuclear@47: float XFormNode::get_active_animation_mix() const nuclear@47: { nuclear@47: return anm_get_active_animation_mix(anm); nuclear@47: } nuclear@47: nuclear@47: int XFormNode::get_animation_count() const nuclear@47: { nuclear@47: return anm_get_animation_count(anm); nuclear@47: } nuclear@47: nuclear@47: void XFormNode::add_animation(const char *name) nuclear@47: { nuclear@47: int idx = get_animation_count(); nuclear@47: nuclear@47: anm_add_animation(anm); nuclear@47: use_animation(idx); nuclear@47: nuclear@47: if(name) { nuclear@47: set_animation_name(name); nuclear@47: } nuclear@47: } nuclear@47: nuclear@47: void XFormNode::set_animation_name(const char *name) nuclear@47: { nuclear@47: anm_set_active_animation_name(anm, name); nuclear@47: } nuclear@47: nuclear@47: const char *XFormNode::get_animation_name() const nuclear@47: { nuclear@47: return anm_get_active_animation_name(anm); nuclear@47: } nuclear@47: nuclear@48: static const int track_type_base[] = {ANM_TRACK_POS_X, ANM_TRACK_ROT_X, ANM_TRACK_SCL_X}; nuclear@48: static const int track_type_nelem[] = {3, 4, 3}; nuclear@47: nuclear@48: int XFormNode::get_key_count(int trackid) const nuclear@48: { nuclear@48: struct anm_animation *anim = anm_get_active_animation(anm, 0); nuclear@48: return anim->tracks[track_type_base[trackid]].count; nuclear@48: } nuclear@48: nuclear@48: int XFormNode::get_position_key_count() const nuclear@48: { nuclear@48: return get_key_count(POSITION_TRACK); nuclear@48: } nuclear@48: nuclear@48: int XFormNode::get_rotation_key_count() const nuclear@48: { nuclear@48: return get_key_count(ROTATION_TRACK); nuclear@48: } nuclear@48: nuclear@48: int XFormNode::get_scaling_key_count() const nuclear@48: { nuclear@48: return get_key_count(SCALING_TRACK); nuclear@48: } nuclear@48: nuclear@48: long XFormNode::get_key_time(int trackid, int idx) const nuclear@48: { nuclear@48: struct anm_animation *anim = anm_get_active_animation(anm, 0); nuclear@48: struct anm_keyframe *key = anm_get_keyframe(anim->tracks + track_type_base[trackid], idx); nuclear@48: return ANM_TM2MSEC(key->time); nuclear@48: } nuclear@48: nuclear@48: long XFormNode::get_position_key_time(int idx) const nuclear@48: { nuclear@48: return get_key_time(POSITION_TRACK, idx); nuclear@48: } nuclear@48: nuclear@48: long XFormNode::get_rotation_key_time(int idx) const nuclear@48: { nuclear@48: return get_key_time(ROTATION_TRACK, idx); nuclear@48: } nuclear@48: nuclear@48: long XFormNode::get_scaling_key_time(int idx) const nuclear@48: { nuclear@48: return get_key_time(SCALING_TRACK, idx); nuclear@48: } nuclear@48: nuclear@48: int XFormNode::get_key_value(int trackid, int idx, float *val) const nuclear@48: { nuclear@48: struct anm_animation *anim = anm_get_active_animation(anm, 0); nuclear@48: nuclear@48: int nelem = track_type_nelem[trackid]; nuclear@48: for(int i=0; itracks + track_type_base[trackid] + i, idx); nuclear@48: val[i] = key->val; nuclear@48: } nuclear@48: return nelem; nuclear@48: } nuclear@48: nuclear@48: Vector3 XFormNode::get_position_key_value(int idx) const nuclear@48: { nuclear@48: float val[3]; nuclear@48: get_key_value(POSITION_TRACK, idx, val); nuclear@48: return Vector3(val[0], val[1], val[2]); nuclear@48: } nuclear@48: nuclear@48: Quaternion XFormNode::get_rotation_key_value(int idx) const nuclear@48: { nuclear@48: float val[4]; nuclear@48: get_key_value(ROTATION_TRACK, idx, val); nuclear@48: return Quaternion(val[3], val[0], val[1], val[2]); nuclear@48: } nuclear@48: nuclear@48: Vector3 XFormNode::get_scaling_key_value(int idx) const nuclear@48: { nuclear@48: float val[3]; nuclear@48: get_key_value(SCALING_TRACK, idx, val); nuclear@48: return Vector3(val[0], val[1], val[2]); nuclear@48: } nuclear@47: nuclear@1: void XFormNode::set_position(const Vector3 &pos, long tmsec) nuclear@1: { nuclear@1: anm_set_position(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec)); nuclear@1: } nuclear@1: nuclear@1: Vector3 XFormNode::get_node_position(long tmsec) const nuclear@1: { nuclear@1: vec3_t p = anm_get_node_position(anm, ANM_MSEC2TM(tmsec)); nuclear@1: return Vector3(p.x, p.y, p.z); nuclear@1: } nuclear@1: nuclear@1: void XFormNode::set_rotation(const Quaternion &quat, long tmsec) nuclear@1: { nuclear@1: anm_set_rotation(anm, quat_cons(quat.s, quat.v.x, quat.v.y, quat.v.z), ANM_MSEC2TM(tmsec)); nuclear@1: } nuclear@1: nuclear@1: Quaternion XFormNode::get_node_rotation(long tmsec) const nuclear@1: { nuclear@1: quat_t q = anm_get_node_rotation(anm, ANM_MSEC2TM(tmsec)); nuclear@1: return Quaternion(q.w, q.x, q.y, q.z); nuclear@1: } nuclear@1: nuclear@1: void XFormNode::set_scaling(const Vector3 &pos, long tmsec) nuclear@1: { nuclear@1: anm_set_scaling(anm, v3_cons(pos.x, pos.y, pos.z), ANM_MSEC2TM(tmsec)); nuclear@1: } nuclear@1: nuclear@1: Vector3 XFormNode::get_node_scaling(long tmsec) const nuclear@1: { nuclear@1: vec3_t s = anm_get_node_scaling(anm, ANM_MSEC2TM(tmsec)); nuclear@1: return Vector3(s.x, s.y, s.z); nuclear@1: } nuclear@1: nuclear@1: // these take hierarchy into account nuclear@1: Vector3 XFormNode::get_position(long tmsec) const nuclear@1: { nuclear@1: vec3_t v = anm_get_position(anm, ANM_MSEC2TM(tmsec)); nuclear@1: return Vector3(v.x, v.y, v.z); nuclear@1: } nuclear@1: nuclear@1: Quaternion XFormNode::get_rotation(long tmsec) const nuclear@1: { nuclear@1: quat_t q = anm_get_rotation(anm, tmsec); nuclear@1: return Quaternion(q.w, q.x, q.y, q.z); nuclear@1: } nuclear@1: nuclear@1: Vector3 XFormNode::get_scaling(long tmsec) const nuclear@1: { nuclear@1: vec3_t v = anm_get_scaling(anm, ANM_MSEC2TM(tmsec)); nuclear@1: return Vector3(v.x, v.y, v.z); nuclear@1: } nuclear@1: nuclear@1: void XFormNode::set_pivot(const Vector3 &pivot) nuclear@1: { nuclear@1: anm_set_pivot(anm, v3_cons(pivot.x, pivot.y, pivot.z)); nuclear@1: } nuclear@1: nuclear@1: Vector3 XFormNode::get_pivot() const nuclear@1: { nuclear@1: vec3_t p = anm_get_pivot(anm); nuclear@1: return Vector3(p.x, p.y, p.z); nuclear@1: } nuclear@1: nuclear@1: void XFormNode::set_local_matrix(const Matrix4x4 &mat) nuclear@1: { nuclear@1: local_matrix = mat; nuclear@1: } nuclear@1: nuclear@1: const Matrix4x4 &XFormNode::get_local_matrix() const nuclear@1: { nuclear@1: return local_matrix; nuclear@1: } nuclear@1: nuclear@1: void XFormNode::set_bone_matrix(const Matrix4x4 &bmat) nuclear@1: { nuclear@1: bone_matrix = bmat; nuclear@1: } nuclear@1: nuclear@1: const Matrix4x4 &XFormNode::get_bone_matrix() const nuclear@1: { nuclear@1: return bone_matrix; nuclear@1: } nuclear@1: nuclear@1: #define FOO nuclear@1: nuclear@1: void XFormNode::get_node_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const nuclear@1: { nuclear@1: anm_time_t tm = ANM_MSEC2TM(tmsec); nuclear@1: nuclear@1: if(mat) { nuclear@1: anm_get_node_matrix(anm, (scalar_t(*)[4])mat, tm); nuclear@1: #ifdef FOO nuclear@1: *mat = local_matrix * *mat; nuclear@1: #else nuclear@1: *mat = *mat * local_matrix; nuclear@1: #endif nuclear@1: } nuclear@1: if(inv_mat) { nuclear@1: anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: void XFormNode::get_xform(long tmsec, Matrix4x4 *mat, Matrix4x4 *inv_mat) const nuclear@1: { nuclear@1: anm_time_t tm = ANM_MSEC2TM(tmsec); nuclear@1: nuclear@1: if(mat) { nuclear@1: anm_get_matrix(anm, (scalar_t(*)[4])mat, tm); nuclear@1: #ifdef FOO nuclear@1: *mat = local_matrix * *mat; nuclear@1: #else nuclear@1: *mat = *mat * local_matrix; nuclear@1: #endif nuclear@1: } nuclear@1: if(inv_mat) { nuclear@1: anm_get_inv_matrix(anm, (scalar_t(*)[4])inv_mat, tm); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: nuclear@1: // ---- Track ---- nuclear@1: nuclear@1: Track::Track() nuclear@1: { nuclear@1: trk = new anm_track; nuclear@1: anm_init_track(trk); nuclear@1: } nuclear@1: nuclear@1: Track::~Track() nuclear@1: { nuclear@1: anm_destroy_track(trk); nuclear@1: delete trk; nuclear@1: } nuclear@1: nuclear@1: Track::Track(const Track &rhs) nuclear@1: { nuclear@1: trk = new anm_track; nuclear@1: anm_init_track(trk); nuclear@1: anm_copy_track(trk, rhs.trk); nuclear@1: interp = rhs.interp; nuclear@1: extrap = rhs.extrap; nuclear@1: } nuclear@1: nuclear@1: Track &Track::operator =(const Track &rhs) nuclear@1: { nuclear@1: if(&rhs == this) { nuclear@1: return *this; nuclear@1: } nuclear@1: nuclear@1: anm_copy_track(trk, rhs.trk); nuclear@1: interp = rhs.interp; nuclear@1: extrap = rhs.extrap; nuclear@1: return *this; nuclear@1: } nuclear@1: nuclear@1: nuclear@1: void Track::set_interpolator(Interp in) nuclear@1: { nuclear@1: anm_set_track_interpolator(trk, track_interpolator(in)); nuclear@1: interp = in; nuclear@1: } nuclear@1: nuclear@1: Interp Track::get_interpolator() const nuclear@1: { nuclear@1: return interp; nuclear@1: } nuclear@1: nuclear@1: void Track::set_extrapolator(Extrap ex) nuclear@1: { nuclear@1: anm_set_track_extrapolator(trk, track_extrapolator(ex)); nuclear@1: extrap = ex; nuclear@1: } nuclear@1: nuclear@1: Extrap Track::get_extrapolator() const nuclear@1: { nuclear@1: return extrap; nuclear@1: } nuclear@1: nuclear@1: void Track::set_default(double def) nuclear@1: { nuclear@1: anm_set_track_default(trk, def); nuclear@1: } nuclear@1: nuclear@1: void Track::set_value(float val, long tmsec) nuclear@1: { nuclear@1: anm_set_value(trk, ANM_MSEC2TM(tmsec), val); nuclear@1: } nuclear@1: nuclear@1: float Track::get_value(long tmsec) const nuclear@1: { nuclear@1: return anm_get_value(trk, ANM_MSEC2TM(tmsec)); nuclear@1: } nuclear@1: nuclear@1: float Track::operator ()(long tmsec) const nuclear@1: { nuclear@1: return anm_get_value(trk, ANM_MSEC2TM(tmsec)); nuclear@1: } nuclear@1: nuclear@1: nuclear@1: // ---- Track3 ---- nuclear@1: nuclear@1: void Track3::set_interpolator(Interp in) nuclear@1: { nuclear@1: for(int i=0; i<3; i++) { nuclear@1: track[i].set_interpolator(in); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: Interp Track3::get_interpolator() const nuclear@1: { nuclear@1: return track[0].get_interpolator(); nuclear@1: } nuclear@1: nuclear@1: void Track3::set_extrapolator(Extrap ex) nuclear@1: { nuclear@1: for(int i=0; i<3; i++) { nuclear@1: track[i].set_extrapolator(ex); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: Extrap Track3::get_extrapolator() const nuclear@1: { nuclear@1: return track[0].get_extrapolator(); nuclear@1: } nuclear@1: nuclear@1: void Track3::set_default(const Vector3 &def) nuclear@1: { nuclear@1: for(int i=0; i<3; i++) { nuclear@1: track[i].set_default(def[i]); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: void Track3::set_value(const Vector3 &val, long tmsec) nuclear@1: { nuclear@1: for(int i=0; i<3; i++) { nuclear@1: track[i].set_value(val[i], tmsec); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: Vector3 Track3::get_value(long tmsec) const nuclear@1: { nuclear@1: return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec)); nuclear@1: } nuclear@1: nuclear@1: Vector3 Track3::operator ()(long tmsec) const nuclear@1: { nuclear@1: return Vector3(track[0](tmsec), track[1](tmsec), track[2](tmsec)); nuclear@1: } nuclear@1: nuclear@1: nuclear@1: static inline anm_interpolator track_interpolator(Interp in) nuclear@1: { nuclear@1: switch(in) { nuclear@1: case INTERP_STEP: nuclear@1: return ANM_INTERP_STEP; nuclear@1: case INTERP_LINEAR: nuclear@1: return ANM_INTERP_LINEAR; nuclear@1: case INTERP_CUBIC: nuclear@1: return ANM_INTERP_CUBIC; nuclear@1: } nuclear@1: nuclear@1: assert(0); nuclear@1: return ANM_INTERP_STEP; nuclear@1: } nuclear@1: nuclear@1: static inline anm_extrapolator track_extrapolator(Extrap ex) nuclear@1: { nuclear@1: switch(ex) { nuclear@1: case EXTRAP_EXTEND: nuclear@1: return ANM_EXTRAP_EXTEND; nuclear@1: case EXTRAP_CLAMP: nuclear@1: return ANM_EXTRAP_CLAMP; nuclear@1: case EXTRAP_REPEAT: nuclear@1: return ANM_EXTRAP_REPEAT; nuclear@1: } nuclear@1: nuclear@1: assert(0); nuclear@1: return ANM_EXTRAP_EXTEND; nuclear@1: } nuclear@1: