Panda3D

xFileAnimationSet.cxx

00001 // Filename: xFileAnimationSet.cxx
00002 // Created by:  drose (02Oct04)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "xFileAnimationSet.h"
00016 #include "xFileToEggConverter.h"
00017 #include "config_xfile.h"
00018 #include "eggGroup.h"
00019 #include "eggTable.h"
00020 #include "eggData.h"
00021 #include "eggXfmSAnim.h"
00022 #include "dcast.h"
00023 
00024 ////////////////////////////////////////////////////////////////////
00025 //     Function: XFileAnimationSet::Constructor
00026 //       Access: Public
00027 //  Description:
00028 ////////////////////////////////////////////////////////////////////
00029 XFileAnimationSet::
00030 XFileAnimationSet() {
00031   _frame_rate = 0.0;
00032 }
00033 
00034 ////////////////////////////////////////////////////////////////////
00035 //     Function: XFileAnimationSet::Destructor
00036 //       Access: Public
00037 //  Description:
00038 ////////////////////////////////////////////////////////////////////
00039 XFileAnimationSet::
00040 ~XFileAnimationSet() {
00041 }
00042 
00043 ////////////////////////////////////////////////////////////////////
00044 //     Function: XFileAnimationSet::create_hierarchy
00045 //       Access: Public
00046 //  Description: Sets up the hierarchy of EggTables corresponding to
00047 //               this AnimationSet.
00048 ////////////////////////////////////////////////////////////////////
00049 bool XFileAnimationSet::
00050 create_hierarchy(XFileToEggConverter *converter) {
00051   // Egg animation tables start off with one Table entry, enclosing a
00052   // Bundle entry.
00053   EggTable *table = new EggTable(get_name());
00054   converter->get_egg_data()->add_child(table);
00055   EggTable *bundle = new EggTable(converter->_char_name);
00056   table->add_child(bundle);
00057   bundle->set_table_type(EggTable::TT_bundle);
00058 
00059   // Then the Bundle contains a "<skeleton>" entry, which begins the
00060   // animation table hierarchy.
00061   EggTable *skeleton = new EggTable("<skeleton>");
00062   bundle->add_child(skeleton);
00063 
00064   // Fill in the rest of the hierarchy with empty tables.
00065   mirror_table(converter, converter->get_dart_node(), skeleton);
00066 
00067   // Now populate those empty tables with the frame data.
00068   JointData::const_iterator ji;
00069   for (ji = _joint_data.begin(); ji != _joint_data.end(); ++ji) {
00070     const string &joint_name = (*ji).first;
00071     const FrameData &table = (*ji).second;
00072 
00073     EggXfmSAnim *anim_table = get_table(joint_name);
00074     if (anim_table == (EggXfmSAnim *)NULL) {
00075       xfile_cat.warning()
00076         << "Frame " << joint_name << ", named by animation data, not defined.\n";
00077     } else {
00078       // If we have animation data, apply it.
00079       FrameEntries::const_iterator fi;
00080       for (fi = table._entries.begin(); fi != table._entries.end(); ++fi) {
00081         anim_table->add_data((*fi).get_mat(table._flags));
00082       }
00083       anim_table->optimize();
00084     }
00085   }
00086 
00087   // Put some data in the empty tables also.
00088   Tables::iterator ti;
00089   for (ti = _tables.begin(); ti != _tables.end(); ++ti) {
00090     EggXfmSAnim *anim_table = (*ti).second._table;
00091     EggGroup *joint = (*ti).second._joint;
00092     if (anim_table->empty() && joint != (EggGroup *)NULL) {
00093       // If there's no animation data, assign the rest transform.
00094       anim_table->add_data(joint->get_transform3d());
00095     }
00096     anim_table->optimize();
00097     if (_frame_rate != 0.0) {
00098       anim_table->set_fps(_frame_rate);
00099     }
00100   }
00101 
00102   return true;
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: XFileAnimationSet::get_table
00107 //       Access: Public
00108 //  Description: Returns the table associated with the indicated joint
00109 //               name.
00110 ////////////////////////////////////////////////////////////////////
00111 EggXfmSAnim *XFileAnimationSet::
00112 get_table(const string &joint_name) const {
00113   Tables::const_iterator ti;
00114   ti = _tables.find(joint_name);
00115   if (ti != _tables.end()) {
00116     return (*ti).second._table;
00117   }
00118   return NULL;
00119 }
00120 
00121 ////////////////////////////////////////////////////////////////////
00122 //     Function: XFileAnimationSet::create_frame_data
00123 //       Access: Public
00124 //  Description: Returns a reference to a new FrameData table
00125 //               corresponding to the indicated joint.
00126 ////////////////////////////////////////////////////////////////////
00127 XFileAnimationSet::FrameData &XFileAnimationSet::
00128 create_frame_data(const string &joint_name) {
00129   return _joint_data[joint_name];
00130 }
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //     Function: XFileAnimationSet::mirror_table
00134 //       Access: Private
00135 //  Description: Builds up a new set of EggTable nodes, as a
00136 //               mirror of the existing set of EggGroup (joint)
00137 //               nodes, and saves each new table in the _tables
00138 //               record.
00139 ////////////////////////////////////////////////////////////////////
00140 void XFileAnimationSet::
00141 mirror_table(XFileToEggConverter *converter, 
00142              EggGroup *model_node, EggTable *anim_node) {
00143   EggGroupNode::iterator gi;
00144   for (gi = model_node->begin(); gi != model_node->end(); ++gi) {
00145     EggNode *child = (*gi);
00146     if (child->is_of_type(EggGroup::get_class_type())) {
00147       EggGroup *group = DCAST(EggGroup, child);
00148       if (group->get_group_type() == EggGroup::GT_joint) {
00149         // When we come to a <Joint>, create a new Table for it.
00150         EggTable *new_table = new EggTable(group->get_name());
00151         anim_node->add_child(new_table);
00152         CoordinateSystem cs = 
00153           converter->get_egg_data()->get_coordinate_system();
00154         EggXfmSAnim *xform = new EggXfmSAnim("xform", cs);
00155         new_table->add_child(xform);
00156         xform->set_fps(converter->_frame_rate);
00157         TablePair &table_pair = _tables[group->get_name()];
00158         table_pair._table = xform;
00159         table_pair._joint = group;
00160 
00161         // Now recurse.
00162         mirror_table(converter, group, new_table);
00163 
00164       } else {
00165         // If we come to an ordinary <Group>, skip past it.
00166         mirror_table(converter, group, anim_node);
00167       }
00168     }
00169   }
00170 }
 All Classes Functions Variables Enumerations