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

panda/src/egg/eggXfmAnimData.cxx

Go to the documentation of this file.
00001 // Filename: eggXfmAnimData.cxx
00002 // Created by:  drose (19Feb99)
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 "eggXfmAnimData.h"
00020 #include "eggXfmSAnim.h"
00021 #include "eggSAnimData.h"
00022 #include "eggMiscFuncs.h"
00023 #include "config_egg.h"
00024 
00025 #include <indent.h>
00026 #include <luse.h>
00027 #include <lmatrix.h>
00028 #include <compose_matrix.h>
00029 
00030 TypeHandle EggXfmAnimData::_type_handle;
00031 
00032 
00033 ////////////////////////////////////////////////////////////////////
00034 //     Function: EggXfmAnimData::Conversion constructor
00035 //       Access: Public
00036 //  Description: Converts the newer-style XfmSAnim table to the
00037 //               older-style XfmAnim table.
00038 ////////////////////////////////////////////////////////////////////
00039 EggXfmAnimData::
00040 EggXfmAnimData(const EggXfmSAnim &convert_from)
00041   : EggAnimData(convert_from.get_name())
00042 {
00043   if (convert_from.has_order()) {
00044     set_order(convert_from.get_order());
00045   }
00046   if (convert_from.has_fps()) {
00047     set_fps(convert_from.get_fps());
00048   }
00049   _coordsys = convert_from.get_coordinate_system();
00050 
00051   // First, get the table names so we know how to build up our
00052   // contents string.  Also store up the SAnim tables themselves in a
00053   // temporary vector for convenience.
00054 
00055   pvector<EggSAnimData *> subtables;
00056 
00057   EggXfmSAnim::const_iterator ci;
00058   for (ci = convert_from.begin(); ci != convert_from.end(); ++ci) {
00059     if ((*ci)->is_of_type(EggSAnimData::get_class_type())) {
00060       EggSAnimData *sanim = DCAST(EggSAnimData, *ci);
00061       nassertv(sanim->get_name().length() == 1);
00062 
00063       if (sanim->get_num_rows() > 0) {
00064         subtables.push_back(sanim);
00065         _contents += sanim->get_name()[0];
00066       }
00067     }
00068   }
00069 
00070   // Now, go through and extract out all the data.
00071   int num_rows = convert_from.get_num_rows();
00072   for (int row = 0; row < num_rows; row++) {
00073     for (int col = 0; col < (int)subtables.size(); col++) {
00074       EggSAnimData *sanim = subtables[col];
00075       if (sanim->get_num_rows() == 1) {
00076         add_data(sanim->get_value(0));
00077       } else {
00078         nassertv(row < sanim->get_num_rows());
00079         add_data(sanim->get_value(row));
00080       }
00081     }
00082   }
00083 }
00084 
00085 
00086 ////////////////////////////////////////////////////////////////////
00087 //     Function: EggXfmAnimData::get_value
00088 //       Access: Public
00089 //  Description: Returns the value of the aggregate row of the table
00090 //               as a matrix.  This is a convenience function that
00091 //               treats the 2-d table as if it were a single table of
00092 //               matrices.
00093 ////////////////////////////////////////////////////////////////////
00094 void EggXfmAnimData::
00095 get_value(int row, LMatrix4d &mat) const {
00096   LVector3d scale(1.0, 1.0, 1.0);
00097   LVector3d hpr(0.0, 0.0, 0.0);
00098   LVector3d translate(0.0, 0.0, 0.0);
00099 
00100   for (int col = 0; col < get_num_cols(); col++) {
00101     double value = get_value(row, col);
00102 
00103     switch (_contents[col]) {
00104     case 'i':
00105       scale[0] = value;
00106       break;
00107 
00108     case 'j':
00109       scale[1] = value;
00110       break;
00111 
00112     case 'k':
00113       scale[2] = value;
00114       break;
00115 
00116     case 'h':
00117       hpr[0] = value;
00118       break;
00119 
00120     case 'p':
00121       hpr[1] = value;
00122       break;
00123 
00124     case 'r':
00125       hpr[2] = value;
00126       break;
00127 
00128     case 'x':
00129       translate[0] = value;
00130       break;
00131 
00132     case 'y':
00133       translate[1] = value;
00134       break;
00135 
00136     case 'z':
00137       translate[2] = value;
00138       break;
00139 
00140     default:
00141       // The contents string contained an invalid letter.
00142       nassertv(false);
00143     }
00144   }
00145 
00146   // So now we've got the nine components; build a matrix.
00147   EggXfmSAnim::compose_with_order(mat, scale, hpr, translate, get_order(),
00148                                   _coordsys);
00149 }
00150 
00151 ////////////////////////////////////////////////////////////////////
00152 //     Function: EggXfmAnimData::write
00153 //       Access: Public, Virtual
00154 //  Description: Writes the data to the indicated output stream in Egg
00155 //               format.
00156 ////////////////////////////////////////////////////////////////////
00157 void EggXfmAnimData::
00158 write(ostream &out, int indent_level) const {
00159   write_header(out, indent_level, "<Xfm$Anim>");
00160 
00161   if (has_fps()) {
00162     indent(out, indent_level + 2)
00163       << "<Scalar> fps { " << get_fps() << " }\n";
00164   }
00165 
00166   if (has_order()) {
00167     indent(out, indent_level + 2)
00168       << "<Char*> order { " << get_order() << " }\n";
00169   }
00170 
00171   if (has_contents()) {
00172     indent(out, indent_level + 2)
00173       << "<Char*> contents { " << get_contents() << " }\n";
00174   }
00175 
00176   indent(out, indent_level + 2) << "<V> {\n";
00177   write_long_list(out, indent_level + 4, _data.begin(), _data.end(),
00178         "", "", 72);
00179   indent(out, indent_level + 2) << "}\n";
00180   indent(out, indent_level) << "}\n";
00181 }
00182 
00183 ////////////////////////////////////////////////////////////////////
00184 //     Function: EggXfmAnimData::r_transform
00185 //       Access: Protected, Virtual
00186 //  Description: Applies the indicated transform to all the rows of
00187 //               the table.  This actually forces the generation of a
00188 //               totally new set of rows.
00189 ////////////////////////////////////////////////////////////////////
00190 void EggXfmAnimData::
00191 r_transform(const LMatrix4d &mat, const LMatrix4d &inv,
00192             CoordinateSystem to_cs) {
00193   // We need to build an inverse matrix that doesn't reflect the
00194   // translation component.
00195   LMatrix4d inv1 = inv;
00196   inv1.set_row(3, LVector3d(0.0, 0.0, 0.0));
00197 
00198   // Now we build a temporary copy of the table as an EggXfmSAnim.  We
00199   // do this because this kind of table is easier to build and
00200   // optimize.
00201 
00202   if (to_cs == CS_default) {
00203     to_cs = _coordsys;
00204   }
00205 
00206   EggXfmSAnim new_table(get_name(), to_cs);
00207   if (has_fps()) {
00208     new_table.set_fps(get_fps());
00209   }
00210 
00211   // We insist on the standard order now.
00212   new_table.set_order(get_standard_order());
00213 
00214   // Now build up the data into the new table.
00215   LMatrix4d orig_mat;
00216   for (int r = 0; r < get_num_rows(); r++) {
00217     get_value(r, orig_mat);
00218     bool result = new_table.add_data(inv1 * orig_mat * mat);
00219 
00220     if (!result) {
00221       egg_cat.error()
00222         << "Transform from " << _coordsys << " to " << to_cs
00223         << " failed!\n";
00224       LVector3d scale, hpr, trans;
00225       bool d = decompose_matrix(orig_mat, scale, hpr, trans, _coordsys);
00226       egg_cat.error(false)
00227         << "orig:\n" << orig_mat
00228         << "d = " << d
00229         << "\n  scale: " << scale
00230         << "\n  hpr: " << hpr
00231         << "\n  trans: " << trans << "\n";
00232 
00233       LMatrix4d new_mat = inv1 * orig_mat * mat;
00234       d = decompose_matrix(new_mat, scale, hpr, trans, to_cs);
00235       egg_cat.error(false)
00236         << "new:\n" << new_mat
00237         << "d = " << d
00238         << "\n  scale: " << scale
00239         << "\n  hpr: " << hpr
00240         << "\n  trans: " << trans << "\n";
00241     }
00242 
00243     // If this assertion fails, we attempted to transform by a skew
00244     // matrix or some such thing that cannot be represented in an anim
00245     // file.
00246     nassertv(result);
00247   }
00248 
00249   // Now clean out the redundant columns we created.
00250   new_table.optimize();
00251 
00252   // And copy that back into EggXfmAnimData table form.
00253   EggXfmAnimData copy_table(new_table);
00254   (*this) = copy_table;
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: EggXfmAnimData::r_mark_coordsys
00259 //       Access: Protected, Virtual
00260 //  Description: This is only called immediately after loading an egg
00261 //               file from disk, to propagate the value found in the
00262 //               CoordinateSystem entry (or the default Y-up
00263 //               coordinate system) to all nodes that care about what
00264 //               the coordinate system is.
00265 ////////////////////////////////////////////////////////////////////
00266 void EggXfmAnimData::
00267 r_mark_coordsys(CoordinateSystem cs) {
00268   _coordsys = cs;
00269 }

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