# HG changeset patch # User John Tsiombikas # Date 1388289719 -7200 # Node ID 9ef9de80649c0a1136c4e28ea04e64f3d04266ec # Parent 498ca7ac70473df24d5f12ba06e65810da30e781 implemented animation track XML saving diff -r 498ca7ac7047 -r 9ef9de80649c src/goat3d_writexml.cc --- a/src/goat3d_writexml.cc Sat Dec 28 06:47:39 2013 +0200 +++ b/src/goat3d_writexml.cc Sun Dec 29 06:01:59 2013 +0200 @@ -180,48 +180,35 @@ static bool write_node_anim(goat3d_io *io, const XFormNode *node, int level) { + /* NOTE: the order of names must correspond to the order of + * XFormNode::POSITION_TRACK/ROTATION_TRACK/SCALING_TRACK enum + */ static const char *attr_names[] = { "position", "rotation", "scaling" }; - struct anm_node *anode = node->get_libanim_node(); - struct anm_animation *anim = anm_get_active_animation(anode, 0); - if(!anode || !anim) { - return false; - } - - struct anm_track *trk[4]; - - for(int i=0; i<3; i++) { // 3 attributes - switch(i) { - case 0: // position - trk[0] = anim->tracks + ANM_TRACK_POS_X; - trk[1] = anim->tracks + ANM_TRACK_POS_Y; - trk[2] = anim->tracks + ANM_TRACK_POS_Z; - trk[3] = 0; - break; - - case 1: // rotation - trk[0] = anim->tracks + ANM_TRACK_ROT_X; - trk[1] = anim->tracks + ANM_TRACK_ROT_Y; - trk[2] = anim->tracks + ANM_TRACK_ROT_Z; - trk[3] = anim->tracks + ANM_TRACK_ROT_W; - break; - - case 2: // scaling - trk[0] = anim->tracks + ANM_TRACK_SCL_X; - trk[1] = anim->tracks + ANM_TRACK_SCL_Y; - trk[2] = anim->tracks + ANM_TRACK_SCL_Z; - trk[3] = 0; - } - - if(trk[0]->count <= 0) { - continue; // skip tracks without any keyframes - } + // for each of: position/rotation/scaling + for(int i=0; i<3; i++) { + int num_keys = node->get_key_count(i); + if(!num_keys) continue; xmlout(io, level + 1, "\n"); xmlout(io, level + 2, "\n", node->get_name()); - xmlout(io, level + 2, "\n", attr_names[i]); + xmlout(io, level + 2, "\n\n", attr_names[i]); - // TODO cont: move all the keyframe retreival to XFormNode and use that... + // for each key in that track + for(int j=0; jget_key_time(i, j); + + float value[4]; + int num_elems = node->get_key_value(i, j, value); + + if(num_elems == 3) { + xmlout(io, level + 2, "\n", + tm, value[0], value[1], value[2]); + } else { + xmlout(io, level + 2, "\n", + tm, value[0], value[1], value[2], value[3]); + } + } xmlout(io, level + 1, "\n"); } diff -r 498ca7ac7047 -r 9ef9de80649c src/xform_node.cc --- a/src/xform_node.cc Sat Dec 28 06:47:39 2013 +0200 +++ b/src/xform_node.cc Sun Dec 29 06:01:59 2013 +0200 @@ -184,7 +184,84 @@ return anm_get_active_animation_name(anm); } +static const int track_type_base[] = {ANM_TRACK_POS_X, ANM_TRACK_ROT_X, ANM_TRACK_SCL_X}; +static const int track_type_nelem[] = {3, 4, 3}; +int XFormNode::get_key_count(int trackid) const +{ + struct anm_animation *anim = anm_get_active_animation(anm, 0); + return anim->tracks[track_type_base[trackid]].count; +} + +int XFormNode::get_position_key_count() const +{ + return get_key_count(POSITION_TRACK); +} + +int XFormNode::get_rotation_key_count() const +{ + return get_key_count(ROTATION_TRACK); +} + +int XFormNode::get_scaling_key_count() const +{ + return get_key_count(SCALING_TRACK); +} + +long XFormNode::get_key_time(int trackid, int idx) const +{ + struct anm_animation *anim = anm_get_active_animation(anm, 0); + struct anm_keyframe *key = anm_get_keyframe(anim->tracks + track_type_base[trackid], idx); + return ANM_TM2MSEC(key->time); +} + +long XFormNode::get_position_key_time(int idx) const +{ + return get_key_time(POSITION_TRACK, idx); +} + +long XFormNode::get_rotation_key_time(int idx) const +{ + return get_key_time(ROTATION_TRACK, idx); +} + +long XFormNode::get_scaling_key_time(int idx) const +{ + return get_key_time(SCALING_TRACK, idx); +} + +int XFormNode::get_key_value(int trackid, int idx, float *val) const +{ + struct anm_animation *anim = anm_get_active_animation(anm, 0); + + int nelem = track_type_nelem[trackid]; + for(int i=0; itracks + track_type_base[trackid] + i, idx); + val[i] = key->val; + } + return nelem; +} + +Vector3 XFormNode::get_position_key_value(int idx) const +{ + float val[3]; + get_key_value(POSITION_TRACK, idx, val); + return Vector3(val[0], val[1], val[2]); +} + +Quaternion XFormNode::get_rotation_key_value(int idx) const +{ + float val[4]; + get_key_value(ROTATION_TRACK, idx, val); + return Quaternion(val[3], val[0], val[1], val[2]); +} + +Vector3 XFormNode::get_scaling_key_value(int idx) const +{ + float val[3]; + get_key_value(SCALING_TRACK, idx, val); + return Vector3(val[0], val[1], val[2]); +} void XFormNode::set_position(const Vector3 &pos, long tmsec) { diff -r 498ca7ac7047 -r 9ef9de80649c src/xform_node.h --- a/src/xform_node.h Sat Dec 28 06:47:39 2013 +0200 +++ b/src/xform_node.h Sun Dec 29 06:01:59 2013 +0200 @@ -33,6 +33,8 @@ XFormNode &operator =(const XFormNode &node) { return *this; } public: + enum { POSITION_TRACK, ROTATION_TRACK, SCALING_TRACK }; + XFormNode(); virtual ~XFormNode(); @@ -76,6 +78,27 @@ virtual void set_animation_name(const char *name); virtual const char *get_animation_name() const; + // raw keyframe retrieval without interpolation + // NOTE: trackid parameters correspond to the values of the unnamed enumeration at the top + + virtual int get_key_count(int trackid) const; + virtual int get_position_key_count() const; + virtual int get_rotation_key_count() const; + virtual int get_scaling_key_count() const; + + virtual long get_key_time(int trackid, int idx) const; + virtual long get_position_key_time(int idx) const; + virtual long get_rotation_key_time(int idx) const; + virtual long get_scaling_key_time(int idx) const; + + /* writes the key value through the val pointer, and returns the number + * of elements in that value (3 for pos/scale, 4 for rotation). + */ + virtual int get_key_value(int trackid, int idx, float *val) const; + virtual Vector3 get_position_key_value(int idx) const; + virtual Quaternion get_rotation_key_value(int idx) const; + virtual Vector3 get_scaling_key_value(int idx) const; + virtual void set_position(const Vector3 &pos, long tmsec = 0); virtual Vector3 get_node_position(long tmsec = 0) const;