Panda3D
|
00001 // Filename: eggMatrixTablePointer.cxx 00002 // Created by: drose (26Feb01) 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 "eggMatrixTablePointer.h" 00016 #include "dcast.h" 00017 #include "eggSAnimData.h" 00018 #include "eggXfmAnimData.h" 00019 #include "eggXfmSAnim.h" 00020 00021 TypeHandle EggMatrixTablePointer::_type_handle; 00022 00023 //////////////////////////////////////////////////////////////////// 00024 // Function: EggMatrixTablePointer::Constructor 00025 // Access: Public 00026 // Description: 00027 //////////////////////////////////////////////////////////////////// 00028 EggMatrixTablePointer:: 00029 EggMatrixTablePointer(EggObject *object) { 00030 _table = DCAST(EggTable, object); 00031 00032 if (_table != (EggTable *)NULL) { 00033 // Now search for the child named "xform". This contains the 00034 // actual table data. 00035 EggGroupNode::iterator ci; 00036 bool found = false; 00037 for (ci = _table->begin(); ci != _table->end() && !found; ++ci) { 00038 EggNode *child = (*ci); 00039 if (child->get_name() == "xform") { 00040 if (child->is_of_type(EggXfmSAnim::get_class_type())) { 00041 _xform = DCAST(EggXfmSAnim, child); 00042 _xform->normalize(); 00043 found = true; 00044 00045 } else if (child->is_of_type(EggXfmAnimData::get_class_type())) { 00046 // Quietly replace old-style XfmAnim tables with new-style 00047 // XfmSAnim tables. 00048 PT(EggXfmAnimData) anim = DCAST(EggXfmAnimData, child); 00049 _xform = new EggXfmSAnim(*anim); 00050 _table->replace(ci, _xform.p()); 00051 found = true; 00052 } 00053 } 00054 } 00055 } 00056 } 00057 00058 //////////////////////////////////////////////////////////////////// 00059 // Function: EggMatrixTablePointer::get_frame_rate 00060 // Access: Public, Virtual 00061 // Description: Returns the stated frame rate of this particular 00062 // joint, or 0.0 if it doesn't state. 00063 //////////////////////////////////////////////////////////////////// 00064 double EggMatrixTablePointer:: 00065 get_frame_rate() const { 00066 if (_xform == (EggXfmSAnim *)NULL || !_xform->has_fps()) { 00067 return 0.0; 00068 } else { 00069 return _xform->get_fps(); 00070 } 00071 } 00072 00073 //////////////////////////////////////////////////////////////////// 00074 // Function: EggMatrixTablePointer::get_num_frames 00075 // Access: Public, Virtual 00076 // Description: Returns the number of frames of animation for this 00077 // particular joint. 00078 //////////////////////////////////////////////////////////////////// 00079 int EggMatrixTablePointer:: 00080 get_num_frames() const { 00081 if (_xform == (EggXfmSAnim *)NULL) { 00082 return 0; 00083 } else { 00084 return _xform->get_num_rows(); 00085 } 00086 } 00087 00088 //////////////////////////////////////////////////////////////////// 00089 // Function: EggMatrixTablePointer::extend_to 00090 // Access: Public, Virtual 00091 // Description: Extends the table to the indicated number of frames. 00092 //////////////////////////////////////////////////////////////////// 00093 void EggMatrixTablePointer:: 00094 extend_to(int num_frames) { 00095 nassertv(_xform != (EggXfmSAnim *)NULL); 00096 _xform->normalize(); 00097 int num_rows = _xform->get_num_rows(); 00098 LMatrix4d last_mat; 00099 if (num_rows == 0) { 00100 last_mat = LMatrix4d::ident_mat(); 00101 } else { 00102 _xform->get_value(num_rows - 1, last_mat); 00103 } 00104 00105 while (num_rows < num_frames) { 00106 _xform->add_data(last_mat); 00107 num_rows++; 00108 } 00109 } 00110 00111 //////////////////////////////////////////////////////////////////// 00112 // Function: EggMatrixTablePointer::get_frame 00113 // Access: Public, Virtual 00114 // Description: Returns the transform matrix corresponding to this 00115 // joint position in the nth frame. 00116 //////////////////////////////////////////////////////////////////// 00117 LMatrix4d EggMatrixTablePointer:: 00118 get_frame(int n) const { 00119 if (get_num_frames() == 1) { 00120 // If we have exactly one frame, then we have as many frames as we 00121 // want; just repeat the first frame. 00122 n = 0; 00123 00124 } else if (get_num_frames() == 0) { 00125 // If we have no frames, we really have the identity matrix. 00126 return LMatrix4d::ident_mat(); 00127 } 00128 00129 nassertr(n >= 0 && n < get_num_frames(), LMatrix4d::ident_mat()); 00130 LMatrix4d mat; 00131 _xform->get_value(n, mat); 00132 return mat; 00133 } 00134 00135 //////////////////////////////////////////////////////////////////// 00136 // Function: EggMatrixTablePointer::set_frame 00137 // Access: Public, Virtual 00138 // Description: Sets the transform matrix corresponding to this 00139 // joint position in the nth frame. 00140 //////////////////////////////////////////////////////////////////// 00141 void EggMatrixTablePointer:: 00142 set_frame(int n, const LMatrix4d &mat) { 00143 nassertv(n >= 0 && n < get_num_frames()); 00144 _xform->set_value(n, mat); 00145 } 00146 00147 //////////////////////////////////////////////////////////////////// 00148 // Function: EggMatrixTablePointer::add_frame 00149 // Access: Public, Virtual 00150 // Description: Appends a new frame onto the end of the data, if 00151 // possible; returns true if not possible, or false 00152 // otherwise (e.g. for a static joint). 00153 //////////////////////////////////////////////////////////////////// 00154 bool EggMatrixTablePointer:: 00155 add_frame(const LMatrix4d &mat) { 00156 if (_xform == (EggXfmSAnim *)NULL) { 00157 return false; 00158 } 00159 00160 return _xform->add_data(mat); 00161 } 00162 00163 //////////////////////////////////////////////////////////////////// 00164 // Function: EggMatrixTablePointer::do_finish_reparent 00165 // Access: Protected 00166 // Description: Performs the actual reparenting operation 00167 // by removing the node from its old parent and 00168 // associating it with its new parent, if any. 00169 //////////////////////////////////////////////////////////////////// 00170 void EggMatrixTablePointer:: 00171 do_finish_reparent(EggJointPointer *new_parent) { 00172 if (new_parent == (EggJointPointer *)NULL) { 00173 // No new parent; unparent the joint. 00174 EggGroupNode *egg_parent = _table->get_parent(); 00175 if (egg_parent != (EggGroupNode *)NULL) { 00176 egg_parent->remove_child(_table.p()); 00177 } 00178 00179 } else { 00180 // Reparent the joint to its new parent (implicitly unparenting it 00181 // from its previous parent). 00182 EggMatrixTablePointer *new_node = DCAST(EggMatrixTablePointer, new_parent); 00183 if (new_node->_table != _table->get_parent()) { 00184 new_node->_table->add_child(_table.p()); 00185 } 00186 } 00187 } 00188 00189 //////////////////////////////////////////////////////////////////// 00190 // Function: EggMatrixTablePointer::do_rebuild 00191 // Access: Public, Virtual 00192 // Description: Rebuilds the entire table all at once, based on the 00193 // frames added by repeated calls to add_rebuild_frame() 00194 // since the last call to begin_rebuild(). 00195 // 00196 // Until do_rebuild() is called, the animation table is 00197 // not changed. 00198 // 00199 // The return value is true if all frames are 00200 // acceptable, or false if there is some problem. 00201 //////////////////////////////////////////////////////////////////// 00202 bool EggMatrixTablePointer:: 00203 do_rebuild(EggCharacterDb &db) { 00204 LMatrix4d mat; 00205 if (!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 0, mat)) { 00206 // No rebuild frame; this is OK. 00207 return true; 00208 } 00209 00210 if (_xform == (EggXfmSAnim *)NULL) { 00211 return false; 00212 } 00213 00214 bool all_ok = true; 00215 00216 _xform->clear_data(); 00217 if (!_xform->add_data(mat)) { 00218 all_ok = false; 00219 } 00220 00221 // Assume all frames will be contiguous. 00222 int n = 1; 00223 while (db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, n, mat)) { 00224 if (!_xform->add_data(mat)) { 00225 all_ok = false; 00226 } 00227 ++n; 00228 } 00229 00230 return all_ok; 00231 } 00232 00233 //////////////////////////////////////////////////////////////////// 00234 // Function: EggMatrixTablePointer::optimize 00235 // Access: Public, Virtual 00236 // Description: Resets the table before writing to disk so that 00237 // redundant rows (e.g. i { 1 1 1 1 1 1 1 1 }) are 00238 // collapsed out. 00239 //////////////////////////////////////////////////////////////////// 00240 void EggMatrixTablePointer:: 00241 optimize() { 00242 if (_xform != (EggXfmSAnim *)NULL) { 00243 _xform->optimize(); 00244 } 00245 } 00246 00247 //////////////////////////////////////////////////////////////////// 00248 // Function: EggMatrixTablePointer::zero_channels 00249 // Access: Public, Virtual 00250 // Description: Zeroes out the named components of the transform in 00251 // the animation frames. 00252 //////////////////////////////////////////////////////////////////// 00253 void EggMatrixTablePointer:: 00254 zero_channels(const string &components) { 00255 if (_xform == (EggXfmSAnim *)NULL) { 00256 return; 00257 } 00258 00259 // This is particularly easy: we only have to remove children from 00260 // the _xform object whose name is listed in the components. 00261 string::const_iterator si; 00262 for (si = components.begin(); si != components.end(); ++si) { 00263 string table_name(1, *si); 00264 EggNode *child = _xform->find_child(table_name); 00265 if (child != (EggNode *)NULL) { 00266 _xform->remove_child(child); 00267 } 00268 } 00269 } 00270 00271 //////////////////////////////////////////////////////////////////// 00272 // Function: EggMatrixTablePointer::quantize_channels 00273 // Access: Public, Virtual 00274 // Description: Rounds the named components of the transform to the 00275 // nearest multiple of quantum. 00276 //////////////////////////////////////////////////////////////////// 00277 void EggMatrixTablePointer:: 00278 quantize_channels(const string &components, double quantum) { 00279 if (_xform == (EggXfmSAnim *)NULL) { 00280 return; 00281 } 00282 00283 // This is similar to the above: we quantize children of the _xform 00284 // object whose name is listed in the components. 00285 string::const_iterator si; 00286 for (si = components.begin(); si != components.end(); ++si) { 00287 string table_name(1, *si); 00288 EggNode *child = _xform->find_child(table_name); 00289 if (child != (EggNode *)NULL && 00290 child->is_of_type(EggSAnimData::get_class_type())) { 00291 EggSAnimData *anim = DCAST(EggSAnimData, child); 00292 anim->quantize(quantum); 00293 } 00294 } 00295 } 00296 00297 //////////////////////////////////////////////////////////////////// 00298 // Function: EggMatrixTablePointer::make_new_joint 00299 // Access: Public, Virtual 00300 // Description: Creates a new child of the current joint in the 00301 // egg data, and returns a pointer to it. 00302 //////////////////////////////////////////////////////////////////// 00303 EggJointPointer *EggMatrixTablePointer:: 00304 make_new_joint(const string &name) { 00305 EggTable *new_table = new EggTable(name); 00306 _table->add_child(new_table); 00307 CoordinateSystem cs = CS_default; 00308 if (_xform != (EggXfmSAnim *)NULL) { 00309 cs = _xform->get_coordinate_system(); 00310 } 00311 EggXfmSAnim *new_xform = new EggXfmSAnim("xform", cs); 00312 new_table->add_child(new_xform); 00313 new_xform->add_data(LMatrix4d::ident_mat()); 00314 00315 return new EggMatrixTablePointer(new_table); 00316 } 00317 00318 //////////////////////////////////////////////////////////////////// 00319 // Function: EggMatrixTablePointer::set_name 00320 // Access: Public, Virtual 00321 // Description: Applies the indicated name change to the egg file. 00322 //////////////////////////////////////////////////////////////////// 00323 void EggMatrixTablePointer:: 00324 set_name(const string &name) { 00325 _table->set_name(name); 00326 }