diff --git a/pandatool/src/xfileegg/Sources.pp b/pandatool/src/xfileegg/Sources.pp index 69e7e746a5..e56b1495ea 100644 --- a/pandatool/src/xfileegg/Sources.pp +++ b/pandatool/src/xfileegg/Sources.pp @@ -20,7 +20,7 @@ #define COMBINED_SOURCES $[TARGET]_composite1.cxx #define SOURCES \ - xFileAnimationSet.h \ + xFileAnimationSet.h xFileAnimationSet.I \ xFileFace.h xFileMaker.h xFileMaterial.h \ xFileMesh.h xFileNormal.h xFileTemplates.h \ xFileToEggConverter.h xFileVertex.h diff --git a/pandatool/src/xfileegg/xFileAnimationSet.I b/pandatool/src/xfileegg/xFileAnimationSet.I new file mode 100644 index 0000000000..f19208044b --- /dev/null +++ b/pandatool/src/xfileegg/xFileAnimationSet.I @@ -0,0 +1,59 @@ +// Filename: xFileAnimationSet.I +// Created by: drose (04Oct04) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: XFileAnimationSet::FrameEntry::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE XFileAnimationSet::FrameEntry:: +FrameEntry() : + _scale(1.0, 1.0, 1.0), + _rot(LQuaterniond::ident_quat()), + _trans(LVector3d::zero()), + _mat(LMatrix4d::ident_mat()) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileAnimationSet::FrameEntry::get_mat +// Access: Public +// Description: Returns the frame's data as a matrix, composing the +// matrix first if necessary, as indicated by the +// FrameData's _flags member. +//////////////////////////////////////////////////////////////////// +INLINE const LMatrix4d &XFileAnimationSet::FrameEntry:: +get_mat(int flags) const { + if ((flags & FDF_mat) == 0) { + ((FrameEntry *)this)->_mat = LMatrix4d::scale_mat(_scale) * _rot; + ((FrameEntry *)this)->_mat.set_row(3, _trans); + } + return _mat; +} + +//////////////////////////////////////////////////////////////////// +// Function: XFileAnimationSet::FrameData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE XFileAnimationSet::FrameData:: +FrameData() : + _flags(0) +{ +} diff --git a/pandatool/src/xfileegg/xFileAnimationSet.cxx b/pandatool/src/xfileegg/xFileAnimationSet.cxx index 3af072574d..8dd1a93111 100644 --- a/pandatool/src/xfileegg/xFileAnimationSet.cxx +++ b/pandatool/src/xfileegg/xFileAnimationSet.cxx @@ -65,7 +65,8 @@ create_hierarchy(XFileToEggConverter *converter) { bundle->add_child(skeleton); // Fill in the rest of the hierarchy with empty tables. - mirror_table(converter->get_dart_node(), skeleton); + mirror_table(converter->_frame_rate, + converter->get_dart_node(), skeleton); // Now populate those empty tables with the frame data. JointData::const_iterator ji; @@ -79,9 +80,9 @@ create_hierarchy(XFileToEggConverter *converter) { << "Frame " << joint_name << ", named by animation data, not defined.\n"; } else { // If we have animation data, apply it. - FrameData::const_iterator fi; - for (fi = table.begin(); fi != table.end(); ++fi) { - anim_table->add_data(*fi); + FrameEntries::const_iterator fi; + for (fi = table._entries.begin(); fi != table._entries.end(); ++fi) { + anim_table->add_data((*fi).get_mat(table._flags)); } anim_table->optimize(); } @@ -139,7 +140,7 @@ create_frame_data(const string &joint_name) { // record. //////////////////////////////////////////////////////////////////// void XFileAnimationSet:: -mirror_table(EggGroup *model_node, EggTable *anim_node) { +mirror_table(double frame_rate, EggGroup *model_node, EggTable *anim_node) { EggGroupNode::iterator gi; for (gi = model_node->begin(); gi != model_node->end(); ++gi) { EggNode *child = (*gi); @@ -151,16 +152,17 @@ mirror_table(EggGroup *model_node, EggTable *anim_node) { anim_node->add_child(new_table); EggXfmSAnim *xform = new EggXfmSAnim("xform"); new_table->add_child(xform); + xform->set_fps(frame_rate); TablePair &table_pair = _tables[group->get_name()]; table_pair._table = xform; table_pair._joint = group; // Now recurse. - mirror_table(group, new_table); + mirror_table(frame_rate, group, new_table); } else { // If we come to an ordinary , skip past it. - mirror_table(group, anim_node); + mirror_table(frame_rate, group, anim_node); } } } diff --git a/pandatool/src/xfileegg/xFileAnimationSet.h b/pandatool/src/xfileegg/xFileAnimationSet.h index caf58d4615..34bf00cfb5 100644 --- a/pandatool/src/xfileegg/xFileAnimationSet.h +++ b/pandatool/src/xfileegg/xFileAnimationSet.h @@ -46,11 +46,38 @@ public: bool create_hierarchy(XFileToEggConverter *converter); EggXfmSAnim *get_table(const string &joint_name) const; - typedef pvector FrameData; + enum FrameDataFlags { + FDF_scale = 0x01, + FDF_rot = 0x02, + FDF_trans = 0x04, + FDF_mat = 0x08, + }; + + class FrameEntry { + public: + INLINE FrameEntry(); + INLINE const LMatrix4d &get_mat(int flags) const; + + LVecBase3d _scale; + LQuaterniond _rot; + LVector3d _trans; + LMatrix4d _mat; + }; + + typedef pvector FrameEntries; + + class FrameData { + public: + INLINE FrameData(); + FrameEntries _entries; + int _flags; + }; + FrameData &create_frame_data(const string &joint_name); private: - void mirror_table(EggGroup *model_node, EggTable *anim_node); + void mirror_table(double frame_rate, + EggGroup *model_node, EggTable *anim_node); typedef pmap JointData; JointData _joint_data; @@ -65,5 +92,7 @@ private: Tables _tables; }; +#include "xFileAnimationSet.I" + #endif diff --git a/pandatool/src/xfileegg/xFileMaker.h b/pandatool/src/xfileegg/xFileMaker.h index 7fe073fb2f..4f1e2fde35 100644 --- a/pandatool/src/xfileegg/xFileMaker.h +++ b/pandatool/src/xfileegg/xFileMaker.h @@ -27,7 +27,7 @@ #define WIN32_LEAN_AND_MEAN #include -#include +#include #include #include #undef WIN32_LEAN_AND_MEAN diff --git a/pandatool/src/xfileegg/xFileTemplates.h b/pandatool/src/xfileegg/xFileTemplates.h index 3cd3795ebb..2c91d9b2a8 100644 --- a/pandatool/src/xfileegg/xFileTemplates.h +++ b/pandatool/src/xfileegg/xFileTemplates.h @@ -23,7 +23,7 @@ #define WIN32_LEAN_AND_MEAN #include -#include +#include #include #include #undef WIN32_LEAN_AND_MEAN diff --git a/pandatool/src/xfileegg/xFileToEggConverter.cxx b/pandatool/src/xfileegg/xFileToEggConverter.cxx index 5895d30756..ee0937768b 100644 --- a/pandatool/src/xfileegg/xFileToEggConverter.cxx +++ b/pandatool/src/xfileegg/xFileToEggConverter.cxx @@ -60,6 +60,7 @@ MY_DEFINE_GUID(DXFILEOBJ_SkinWeights, XFileToEggConverter:: XFileToEggConverter() { _make_char = false; + _frame_rate = 30.0; _dx_file = NULL; _dx_file_enum = NULL; _dart_node = NULL; @@ -903,10 +904,13 @@ convert_animation_key(LPDIRECTXFILEDATA obj, const string &joint_name, int key_type = di.get_uint32(); int nkeys = di.get_uint32(); - int last_time = 0; - for (int i = 0; i < nkeys; i++) { - int time = di.get_uint32(); + // We ignore the time value. It seems to be of questionable value + // anyway, being of all sorts of crazy scales; and Panda doesn't + // support timestamped keyframes anyway. Assume the x file was + // generated with one frame per frame of animation, and translate + // accordingly. + /*int time =*/ di.get_uint32(); int nvalues = di.get_uint32(); pvector values; @@ -916,12 +920,9 @@ convert_animation_key(LPDIRECTXFILEDATA obj, const string &joint_name, values.push_back(value); } - while (last_time <= time) { - if (!set_animation_frame(joint_name, table, last_time, key_type, - &values[0], nvalues)) { - return false; - } - last_time++; + if (!set_animation_frame(joint_name, table, i, key_type, + &values[0], nvalues)) { + return false; } } @@ -937,44 +938,40 @@ bool XFileToEggConverter:: set_animation_frame(const string &joint_name, XFileToEggConverter::FrameData &table, int frame, int key_type, const float *values, int nvalues) { - LMatrix4d mat; - - // Pad out the table by duplicating the last row as necessary. - if ((int)table.size() <= frame) { - if (table.empty()) { - // Get the initial transform from the joint's rest transform. - EggGroup *joint = find_joint(joint_name); - if (joint != (EggGroup *)NULL) { - mat = joint->get_transform(); - } else { - mat = LMatrix4d::ident_mat(); - } - } else { - // Get the initial transform from the last frame of animation. - mat = table.back(); - } - table.push_back(mat); - while ((int)table.size() <= frame) { - table.push_back(mat); - } - - } else { - mat = table.back(); + if ((int)table._entries.size() <= frame) { + nassertr((int)table._entries.size() == frame, false); + table._entries.push_back(XFileAnimationSet::FrameEntry()); } + XFileAnimationSet::FrameEntry &frame_entry = table._entries[frame]; + // Now modify the last row in the table. switch (key_type) { - /* case 0: - // Key type 0: rotation + // Key type 0: rotation. + // This appears to be a quaternion. Hope we get the coordinate + // system right. + if (nvalues != 4) { + xfile_cat.error() + << "Incorrect number of values in animation table: " + << nvalues << " for rotation data.\n"; + return false; + } + frame_entry._rot.set(values[0], -values[1], values[2], -values[3]); + // frame_entry._rot.set_from_matrix(LMatrix3d::rotate_mat(-90, LVecBase3d(1, 0, 0)) * frame_entry._rot * LMatrix3d::rotate_mat(90, LVecBase3d(1, 0, 0))); + table._flags |= XFileAnimationSet::FDF_rot; break; - */ - /* case 1: - // Key type 1: scale + if (nvalues != 3) { + xfile_cat.error() + << "Incorrect number of values in animation table: " + << nvalues << " for scale data.\n"; + return false; + } + frame_entry._scale.set(values[0], values[1], values[2]); + table._flags |= XFileAnimationSet::FDF_scale; break; - */ case 2: // Key type 2: position @@ -984,7 +981,8 @@ set_animation_frame(const string &joint_name, << nvalues << " for position data.\n"; return false; } - mat.set_row(3, LVecBase3d(values[0], values[1], values[2])); + frame_entry._trans.set(values[0], values[1], values[2]); + table._flags |= XFileAnimationSet::FDF_trans; break; /* @@ -1001,10 +999,11 @@ set_animation_frame(const string &joint_name, << nvalues << " for matrix data.\n"; return false; } - mat.set(values[0], values[1], values[2], values[3], - values[4], values[5], values[6], values[7], - values[8], values[9], values[10], values[11], - values[12], values[13], values[14], values[15]); + frame_entry._mat.set(values[0], values[1], values[2], values[3], + values[4], values[5], values[6], values[7], + values[8], values[9], values[10], values[11], + values[12], values[13], values[14], values[15]); + table._flags |= XFileAnimationSet::FDF_mat; break; default: @@ -1012,8 +1011,6 @@ set_animation_frame(const string &joint_name, << "Unsupported key type " << key_type << " in animation table.\n"; return false; } - - table.back() = mat; return true; } diff --git a/pandatool/src/xfileegg/xFileToEggConverter.h b/pandatool/src/xfileegg/xFileToEggConverter.h index 31c127092f..b84f3a1f14 100644 --- a/pandatool/src/xfileegg/xFileToEggConverter.h +++ b/pandatool/src/xfileegg/xFileToEggConverter.h @@ -30,7 +30,7 @@ #define WIN32_LEAN_AND_MEAN #include -#include +#include #include #include #undef WIN32_LEAN_AND_MEAN @@ -72,6 +72,7 @@ public: public: bool _make_char; string _char_name; + double _frame_rate; private: typedef XFileAnimationSet::FrameData FrameData;