Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/egg2pg/animBundleMaker.cxx

Go to the documentation of this file.
00001 // Filename: animBundleMaker.cxx
00002 // Created by:  drose (22Feb99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "animBundleMaker.h"
00020 #include "config_egg2pg.h"
00021 
00022 #include "eggTable.h"
00023 #include "eggAnimData.h"
00024 #include "eggSAnimData.h"
00025 #include "eggXfmAnimData.h"
00026 #include "eggXfmSAnim.h"
00027 #include "eggGroupNode.h"
00028 #include "animBundle.h"
00029 #include "animBundleNode.h"
00030 #include "animChannelMatrixXfmTable.h"
00031 #include "animChannelScalarTable.h"
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: AnimBundleMaker::Construtor
00035 //       Access: Public
00036 //  Description:
00037 ////////////////////////////////////////////////////////////////////
00038 AnimBundleMaker::
00039 AnimBundleMaker(EggTable *root) : _root(root) {
00040   _fps = 0.0f;
00041   _num_frames = 1;
00042 
00043   _ok_fps = true;
00044   _ok_num_frames = true;
00045 
00046   inspect_tree(root);
00047 
00048   if (!_ok_fps) {
00049     egg2pg_cat.warning()
00050       << "AnimBundle " << _root->get_name()
00051       << " specifies contradictory frame rates.\n";
00052   } else if (_fps == 0.0f) {
00053     egg2pg_cat.warning()
00054       << "AnimBundle " << _root->get_name()
00055       << " does not specify a frame rate.\n";
00056     _fps = 24.0f;
00057   }
00058 
00059   if (!_ok_num_frames) {
00060     egg2pg_cat.warning()
00061       << "AnimBundle " << _root->get_name()
00062       << " specifies contradictory number of frames.\n";
00063   }
00064 }
00065 
00066 
00067 ////////////////////////////////////////////////////////////////////
00068 //     Function: AnimBundleMaker::make_node
00069 //       Access: Public
00070 //  Description:
00071 ////////////////////////////////////////////////////////////////////
00072 AnimBundleNode *AnimBundleMaker::
00073 make_node() {
00074   return new AnimBundleNode("", make_bundle());
00075 }
00076 
00077 ////////////////////////////////////////////////////////////////////
00078 //     Function: AnimBundleMaker::make_bundle
00079 //       Access: Private
00080 //  Description:
00081 ////////////////////////////////////////////////////////////////////
00082 AnimBundle *AnimBundleMaker::
00083 make_bundle() {
00084   AnimBundle *bundle = new AnimBundle(_root->get_name(), _fps, _num_frames);
00085 
00086   EggTable::const_iterator ci;
00087   for (ci = _root->begin(); ci != _root->end(); ++ci) {
00088     if ((*ci)->is_of_type(EggTable::get_class_type())) {
00089       EggTable *child = DCAST(EggTable, *ci);
00090       build_hierarchy(child, bundle);
00091     }
00092   }
00093 
00094   bundle->sort_descendants();
00095 
00096   return bundle;
00097 }
00098 
00099 
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: AnimBundleMaker::inspect_tree
00102 //       Access: Private
00103 //  Description: Walks the egg tree, getting out the fps and the
00104 //               number of frames.
00105 ////////////////////////////////////////////////////////////////////
00106 void AnimBundleMaker::
00107 inspect_tree(EggNode *egg_node) {
00108   if (egg_node->is_of_type(EggAnimData::get_class_type())) {
00109     // Check frame rate.
00110     EggAnimData *egg_anim = DCAST(EggAnimData, egg_node);
00111     if (egg_anim->has_fps()) {
00112       if (_fps == 0.0f) {
00113         _fps = egg_anim->get_fps();
00114       } else if (_fps != egg_anim->get_fps()) {
00115         // Whoops!  This table differs in opinion from the other tables.
00116         _fps = min(_fps, (float)egg_anim->get_fps());
00117         _ok_fps = false;
00118       }
00119     }
00120   }
00121 
00122   if (egg_node->is_of_type(EggXfmSAnim::get_class_type())) {
00123     // Check frame rate.
00124     EggXfmSAnim *egg_anim = DCAST(EggXfmSAnim, egg_node);
00125     if (egg_anim->has_fps()) {
00126       if (_fps == 0.0f) {
00127         _fps = egg_anim->get_fps();
00128       } else if (_fps != egg_anim->get_fps()) {
00129         // Whoops!  This table differs in opinion from the other tables.
00130         _fps = min(_fps, (float)egg_anim->get_fps());
00131         _ok_fps = false;
00132       }
00133     }
00134   }
00135 
00136   if (egg_node->is_of_type(EggSAnimData::get_class_type())) {
00137     // Check number of frames.
00138     EggSAnimData *egg_anim = DCAST(EggSAnimData, egg_node);
00139     int num_frames = egg_anim->get_num_rows();
00140 
00141     if (num_frames > 1) {
00142       if (_num_frames == 1) {
00143         _num_frames = num_frames;
00144       } else if (_num_frames != num_frames) {
00145         // Whoops!  Another disagreement.
00146         _num_frames = min(_num_frames, num_frames);
00147         _ok_num_frames = false;
00148       }
00149     }
00150   }
00151 
00152   if (egg_node->is_of_type(EggXfmAnimData::get_class_type())) {
00153     // Check number of frames.
00154     EggXfmAnimData *egg_anim = DCAST(EggXfmAnimData, egg_node);
00155     int num_frames = egg_anim->get_num_rows();
00156 
00157     if (num_frames > 1) {
00158       if (_num_frames == 1) {
00159         _num_frames = num_frames;
00160       } else if (_num_frames != num_frames) {
00161         // Whoops!  Another disagreement.
00162         _num_frames = min(_num_frames, num_frames);
00163         _ok_num_frames = false;
00164       }
00165     }
00166   }
00167 
00168   if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
00169     // Now recurse.
00170     EggGroupNode *group = DCAST(EggGroupNode, egg_node);
00171     EggGroupNode::const_iterator ci;
00172     for (ci = group->begin(); ci != group->end(); ++ci) {
00173       inspect_tree(*ci);
00174     }
00175   }
00176 }
00177 
00178 
00179 ////////////////////////////////////////////////////////////////////
00180 //     Function: AnimBundleMaker::build_hierarchy
00181 //       Access: Private
00182 //  Description: Walks the egg tree again, creating the AnimChannels
00183 //               as appropriate.
00184 ////////////////////////////////////////////////////////////////////
00185 void AnimBundleMaker::
00186 build_hierarchy(EggTable *egg_table, AnimGroup *parent) {
00187   AnimGroup *this_node = NULL;
00188 
00189   // First, scan the children of egg_table for anim data tables.  If
00190   // any of them is named "xform", it's a special case--this one
00191   // stands for the egg_table node itself.  Don't ask me why.
00192 
00193   EggTable::const_iterator ci;
00194   for (ci = egg_table->begin(); ci != egg_table->end(); ++ci) {
00195     if ((*ci)->get_name() == "xform") {
00196       if (this_node == NULL) {
00197         this_node = create_xfm_channel((*ci), egg_table->get_name(), parent);
00198       } else {
00199         egg2pg_cat.warning()
00200           << "Duplicate xform table under node "
00201           << egg_table->get_name() << "\n";
00202       }
00203     }
00204   }
00205 
00206   // If none of them were named "xform", just create a plain old
00207   // AnimGroup.
00208   if (this_node == NULL) {
00209     this_node = new AnimGroup(parent, egg_table->get_name());
00210   }
00211 
00212   // Now walk the children again, creating any leftover tables, and
00213   // recursing.
00214   for (ci = egg_table->begin(); ci != egg_table->end(); ++ci) {
00215     if ((*ci)->get_name() == "xform") {
00216       // Skip this one.  We already got it.
00217     } else if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
00218       EggSAnimData *egg_anim = DCAST(EggSAnimData, *ci);
00219       create_s_channel(egg_anim, egg_anim->get_name(), this_node);
00220 
00221     } else if ((*ci)->is_of_type(EggTable::get_class_type())) {
00222       EggTable *child = DCAST(EggTable, *ci);
00223       build_hierarchy(child, this_node);
00224     }
00225   }
00226 }
00227 
00228 
00229 ////////////////////////////////////////////////////////////////////
00230 //     Function: AnimBundleMaker::create_s_channel
00231 //       Access: Private
00232 //  Description: Creates an AnimChannelScalarTable corresponding to
00233 //               the given EggSAnimData structure.
00234 ////////////////////////////////////////////////////////////////////
00235 AnimChannelScalarTable *AnimBundleMaker::
00236 create_s_channel(EggSAnimData *egg_anim, const string &name,
00237                  AnimGroup *parent) {
00238   AnimChannelScalarTable *table
00239     = new AnimChannelScalarTable(parent, name);
00240 
00241   // First we have to copy the table data from PTA_double to
00242   // PTA_float.
00243   PTA_float new_data=PTA_float::empty_array(egg_anim->get_num_rows());
00244   for (int i = 0; i < egg_anim->get_num_rows(); i++) {
00245     new_data[i] = (float)egg_anim->get_value(i);
00246   }
00247 
00248   // Now we can assign the table.
00249   table->set_table(new_data);
00250 
00251   return table;
00252 }
00253 
00254 
00255 ////////////////////////////////////////////////////////////////////
00256 //     Function: AnimBundleMaker::create_xfm_channel (EggNode)
00257 //       Access: Private
00258 //  Description: Creates an AnimChannelMatrixXfmTable corresponding to
00259 //               the given EggNode structure, if possible.
00260 ////////////////////////////////////////////////////////////////////
00261 AnimChannelMatrixXfmTable *AnimBundleMaker::
00262 create_xfm_channel(EggNode *egg_node, const string &name,
00263                    AnimGroup *parent) {
00264   if (egg_node->is_of_type(EggXfmAnimData::get_class_type())) {
00265     EggXfmAnimData *egg_anim = DCAST(EggXfmAnimData, egg_node);
00266     EggXfmSAnim new_anim(*egg_anim);
00267     return create_xfm_channel(&new_anim, name, parent);
00268 
00269   } else if (egg_node->is_of_type(EggXfmSAnim::get_class_type())) {
00270     EggXfmSAnim *egg_anim = DCAST(EggXfmSAnim, egg_node);
00271     return create_xfm_channel(egg_anim, name, parent);
00272   }
00273 
00274   egg2pg_cat.warning()
00275     << "Inappropriate node named xform under node "
00276     << name << "\n";
00277   return NULL;
00278 }
00279 
00280 
00281 ////////////////////////////////////////////////////////////////////
00282 //     Function: AnimBundleMaker::create_xfm_channel (EggXfmSAnim)
00283 //       Access: Private
00284 //  Description: Creates an AnimChannelMatrixXfmTable corresponding to
00285 //               the given EggXfmSAnim structure.
00286 ////////////////////////////////////////////////////////////////////
00287 AnimChannelMatrixXfmTable *AnimBundleMaker::
00288 create_xfm_channel(EggXfmSAnim *egg_anim, const string &name,
00289                    AnimGroup *parent) {
00290   // Ensure that the anim table is optimal and that it is standard
00291   // order.
00292   egg_anim->optimize_to_standard_order();
00293 
00294   AnimChannelMatrixXfmTable *table
00295     = new AnimChannelMatrixXfmTable(parent, name);
00296 
00297   // The EggXfmSAnim structure has a number of children which are
00298   // EggSAnimData tables.  Each of these represents a separate
00299   // component of the transform data, and will be added to the table.
00300 
00301   EggXfmSAnim::const_iterator ci;
00302   for (ci = egg_anim->begin(); ci != egg_anim->end(); ++ci) {
00303     if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
00304       EggSAnimData *child = DCAST(EggSAnimData, *ci);
00305 
00306       if (child->get_name().empty()) {
00307         egg2pg_cat.warning()
00308           << "Unnamed subtable of <Xfm$Anim_S$> " << name
00309           << "\n";
00310       } else {
00311         char table_id = child->get_name()[0];
00312 
00313         if (child->get_name().length() > 1 ||
00314             !table->is_valid_id(table_id)) {
00315           egg2pg_cat.warning()
00316             << "Unexpected table name " << child->get_name()
00317             << ", child of " << name << "\n";
00318 
00319         } else if (table->has_table(table_id)) {
00320           egg2pg_cat.warning()
00321             << "Duplicate table definition for " << table_id
00322             << " under " << name << "\n";
00323 
00324         } else {
00325 
00326           // Now we have to copy the table data from PTA_double to
00327           // PTA_float.
00328           PTA_float new_data=PTA_float::empty_array(child->get_num_rows());
00329           for (int i = 0; i < child->get_num_rows(); i++) {
00330             new_data[i] = (float)child->get_value(i);
00331           }
00332 
00333           // Now we can assign the table.
00334           table->set_table(table_id, new_data);
00335         }
00336       }
00337     }
00338   }
00339 
00340   return table;
00341 }

Generated on Fri May 2 00:38:07 2003 for Panda by doxygen1.3