Panda3D
eggMatrixTablePointer.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file eggMatrixTablePointer.cxx
10  * @author drose
11  * @date 2001-02-26
12  */
13 
14 #include "eggMatrixTablePointer.h"
15 
16 #include "dcast.h"
17 #include "eggCharacterDb.h"
18 #include "eggSAnimData.h"
19 #include "eggXfmAnimData.h"
20 #include "eggXfmSAnim.h"
21 
22 using std::string;
23 
24 TypeHandle EggMatrixTablePointer::_type_handle;
25 
26 /**
27  *
28  */
29 EggMatrixTablePointer::
30 EggMatrixTablePointer(EggObject *object) {
31  _table = DCAST(EggTable, object);
32 
33  if (_table != nullptr) {
34  // Now search for the child named "xform". This contains the actual table
35  // data.
36  EggGroupNode::iterator ci;
37  bool found = false;
38  for (ci = _table->begin(); ci != _table->end() && !found; ++ci) {
39  EggNode *child = (*ci);
40  if (child->get_name() == "xform") {
41  if (child->is_of_type(EggXfmSAnim::get_class_type())) {
42  _xform = DCAST(EggXfmSAnim, child);
43  _xform->normalize();
44  found = true;
45 
46  } else if (child->is_of_type(EggXfmAnimData::get_class_type())) {
47  // Quietly replace old-style XfmAnim tables with new-style XfmSAnim
48  // tables.
49  PT(EggXfmAnimData) anim = DCAST(EggXfmAnimData, child);
50  _xform = new EggXfmSAnim(*anim);
51  _table->replace(ci, _xform.p());
52  found = true;
53  }
54  }
55  }
56  }
57 }
58 
59 /**
60  * Returns the stated frame rate of this particular joint, or 0.0 if it
61  * doesn't state.
62  */
64 get_frame_rate() const {
65  if (_xform == nullptr || !_xform->has_fps()) {
66  return 0.0;
67  } else {
68  return _xform->get_fps();
69  }
70 }
71 
72 /**
73  * Returns the number of frames of animation for this particular joint.
74  */
76 get_num_frames() const {
77  if (_xform == nullptr) {
78  return 0;
79  } else {
80  return _xform->get_num_rows();
81  }
82 }
83 
84 /**
85  * Extends the table to the indicated number of frames.
86  */
88 extend_to(int num_frames) {
89  nassertv(_xform != nullptr);
90  _xform->normalize();
91  int num_rows = _xform->get_num_rows();
92  LMatrix4d last_mat;
93  if (num_rows == 0) {
94  last_mat = LMatrix4d::ident_mat();
95  } else {
96  _xform->get_value(num_rows - 1, last_mat);
97  }
98 
99  while (num_rows < num_frames) {
100  _xform->add_data(last_mat);
101  num_rows++;
102  }
103 }
104 
105 /**
106  * Returns the transform matrix corresponding to this joint position in the
107  * nth frame.
108  */
110 get_frame(int n) const {
111  if (get_num_frames() == 1) {
112  // If we have exactly one frame, then we have as many frames as we want;
113  // just repeat the first frame.
114  n = 0;
115 
116  } else if (get_num_frames() == 0) {
117  // If we have no frames, we really have the identity matrix.
118  return LMatrix4d::ident_mat();
119  }
120 
121  nassertr(n >= 0 && n < get_num_frames(), LMatrix4d::ident_mat());
122  LMatrix4d mat;
123  _xform->get_value(n, mat);
124  return mat;
125 }
126 
127 /**
128  * Sets the transform matrix corresponding to this joint position in the nth
129  * frame.
130  */
132 set_frame(int n, const LMatrix4d &mat) {
133  nassertv(n >= 0 && n < get_num_frames());
134  _xform->set_value(n, mat);
135 }
136 
137 /**
138  * Appends a new frame onto the end of the data, if possible; returns true if
139  * not possible, or false otherwise (e.g. for a static joint).
140  */
142 add_frame(const LMatrix4d &mat) {
143  if (_xform == nullptr) {
144  return false;
145  }
146 
147  return _xform->add_data(mat);
148 }
149 
150 /**
151  * Performs the actual reparenting operation by removing the node from its old
152  * parent and associating it with its new parent, if any.
153  */
155 do_finish_reparent(EggJointPointer *new_parent) {
156  if (new_parent == nullptr) {
157  // No new parent; unparent the joint.
158  EggGroupNode *egg_parent = _table->get_parent();
159  if (egg_parent != nullptr) {
160  egg_parent->remove_child(_table.p());
161  }
162 
163  } else {
164  // Reparent the joint to its new parent (implicitly unparenting it from
165  // its previous parent).
166  EggMatrixTablePointer *new_node = DCAST(EggMatrixTablePointer, new_parent);
167  if (new_node->_table != _table->get_parent()) {
168  new_node->_table->add_child(_table.p());
169  }
170  }
171 }
172 
173 /**
174  * Rebuilds the entire table all at once, based on the frames added by
175  * repeated calls to add_rebuild_frame() since the last call to
176  * begin_rebuild().
177  *
178  * Until do_rebuild() is called, the animation table is not changed.
179  *
180  * The return value is true if all frames are acceptable, or false if there is
181  * some problem.
182  */
185  LMatrix4d mat;
186  if (!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 0, mat)) {
187  // No rebuild frame; this is OK.
188  return true;
189  }
190 
191  if (_xform == nullptr) {
192  return false;
193  }
194 
195  bool all_ok = true;
196 
197  _xform->clear_data();
198  if (!_xform->add_data(mat)) {
199  all_ok = false;
200  }
201 
202  // Assume all frames will be contiguous.
203  int n = 1;
204  while (db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, n, mat)) {
205  if (!_xform->add_data(mat)) {
206  all_ok = false;
207  }
208  ++n;
209  }
210 
211  return all_ok;
212 }
213 
214 /**
215  * Resets the table before writing to disk so that redundant rows (e.g. i { 1
216  * 1 1 1 1 1 1 1 }) are collapsed out.
217  */
219 optimize() {
220  if (_xform != nullptr) {
221  _xform->optimize();
222  }
223 }
224 
225 /**
226  * Zeroes out the named components of the transform in the animation frames.
227  */
229 zero_channels(const string &components) {
230  if (_xform == nullptr) {
231  return;
232  }
233 
234  // This is particularly easy: we only have to remove children from the
235  // _xform object whose name is listed in the components.
236  string::const_iterator si;
237  for (si = components.begin(); si != components.end(); ++si) {
238  string table_name(1, *si);
239  EggNode *child = _xform->find_child(table_name);
240  if (child != nullptr) {
241  _xform->remove_child(child);
242  }
243  }
244 }
245 
246 /**
247  * Rounds the named components of the transform to the nearest multiple of
248  * quantum.
249  */
251 quantize_channels(const string &components, double quantum) {
252  if (_xform == nullptr) {
253  return;
254  }
255 
256  // This is similar to the above: we quantize children of the _xform object
257  // whose name is listed in the components.
258  string::const_iterator si;
259  for (si = components.begin(); si != components.end(); ++si) {
260  string table_name(1, *si);
261  EggNode *child = _xform->find_child(table_name);
262  if (child != nullptr &&
263  child->is_of_type(EggSAnimData::get_class_type())) {
264  EggSAnimData *anim = DCAST(EggSAnimData, child);
265  anim->quantize(quantum);
266  }
267  }
268 }
269 
270 /**
271  * Creates a new child of the current joint in the egg data, and returns a
272  * pointer to it.
273  */
275 make_new_joint(const string &name) {
276  EggTable *new_table = new EggTable(name);
277  _table->add_child(new_table);
278  CoordinateSystem cs = CS_default;
279  if (_xform != nullptr) {
280  cs = _xform->get_coordinate_system();
281  }
282  EggXfmSAnim *new_xform = new EggXfmSAnim("xform", cs);
283  new_table->add_child(new_xform);
284  new_xform->add_data(LMatrix4d::ident_mat());
285 
286  return new EggMatrixTablePointer(new_table);
287 }
288 
289 /**
290  * Applies the indicated name change to the egg file.
291  */
293 set_name(const string &name) {
294  _table->set_name(name);
295 }
EggMatrixTablePointer::set_frame
virtual void set_frame(int n, const LMatrix4d &mat)
Sets the transform matrix corresponding to this joint position in the nth frame.
Definition: eggMatrixTablePointer.cxx:132
EggMatrixTablePointer::quantize_channels
virtual void quantize_channels(const std::string &components, double quantum)
Rounds the named components of the transform to the nearest multiple of quantum.
Definition: eggMatrixTablePointer.cxx:251
eggXfmSAnim.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eggCharacterDb.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
dcast.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggMatrixTablePointer::zero_channels
virtual void zero_channels(const std::string &components)
Zeroes out the named components of the transform in the animation frames.
Definition: eggMatrixTablePointer.cxx:229
eggSAnimData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggTable
This corresponds to a.
Definition: eggTable.h:27
EggAnimData::quantize
void quantize(double quantum)
Rounds each element of the table to the nearest multiple of quantum.
Definition: eggAnimData.cxx:22
EggGroupNode
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
EggXfmAnimData
Corresponding to an <Xfm$Anim> entry, this stores a two-dimensional table with up to nine columns,...
Definition: eggXfmAnimData.h:29
EggMatrixTablePointer::extend_to
virtual void extend_to(int num_frames)
Extends the table to the indicated number of frames.
Definition: eggMatrixTablePointer.cxx:88
EggCharacterDb::get_matrix
bool get_matrix(const EggJointPointer *joint, TableType type, int frame, LMatrix4d &mat) const
Looks up the data for the indicated joint, type, and frame, and fills it in result (and returns true)...
Definition: eggCharacterDb.cxx:68
eggMatrixTablePointer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
EggJointPointer
This is a base class for EggJointNodePointer and EggMatrixTablePointer.
Definition: eggJointPointer.h:31
EggMatrixTablePointer::set_name
virtual void set_name(const std::string &name)
Applies the indicated name change to the egg file.
Definition: eggMatrixTablePointer.cxx:293
EggXfmSAnim
This corresponds to an <Xfm$Anim_S$> entry, which is a collection of up to nine <S$Anim> entries that...
Definition: eggXfmSAnim.h:28
EggMatrixTablePointer::optimize
virtual void optimize()
Resets the table before writing to disk so that redundant rows (e.g.
Definition: eggMatrixTablePointer.cxx:219
EggMatrixTablePointer::get_frame
virtual LMatrix4d get_frame(int n) const
Returns the transform matrix corresponding to this joint position in the nth frame.
Definition: eggMatrixTablePointer.cxx:110
EggMatrixTablePointer::add_frame
virtual bool add_frame(const LMatrix4d &mat)
Appends a new frame onto the end of the data, if possible; returns true if not possible,...
Definition: eggMatrixTablePointer.cxx:142
EggMatrixTablePointer::do_rebuild
virtual bool do_rebuild(EggCharacterDb &db)
Rebuilds the entire table all at once, based on the frames added by repeated calls to add_rebuild_fra...
Definition: eggMatrixTablePointer.cxx:184
EggMatrixTablePointer::get_frame_rate
virtual double get_frame_rate() const
Returns the stated frame rate of this particular joint, or 0.0 if it doesn't state.
Definition: eggMatrixTablePointer.cxx:64
EggMatrixTablePointer::do_finish_reparent
virtual void do_finish_reparent(EggJointPointer *new_parent)
Performs the actual reparenting operation by removing the node from its old parent and associating it...
Definition: eggMatrixTablePointer.cxx:155
EggMatrixTablePointer::make_new_joint
virtual EggJointPointer * make_new_joint(const std::string &name)
Creates a new child of the current joint in the egg data, and returns a pointer to it.
Definition: eggMatrixTablePointer.cxx:275
EggMatrixTablePointer
This stores a pointer back to an EggXfmSAnim table (i.e.
Definition: eggMatrixTablePointer.h:30
EggMatrixTablePointer::get_num_frames
virtual int get_num_frames() const
Returns the number of frames of animation for this particular joint.
Definition: eggMatrixTablePointer.cxx:76
EggObject
The highest-level base class in the egg directory.
Definition: eggObject.h:29
EggNode
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:35
EggGroupNode::add_child
EggNode * add_child(EggNode *node)
Adds the indicated child to the group and returns it.
Definition: eggGroupNode.cxx:243
EggXfmSAnim::add_data
bool add_data(const LMatrix4d &mat)
Adds a new matrix to the table, by adding a new row to each of the subtables.
Definition: eggXfmSAnim.cxx:476
eggXfmAnimData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggSAnimData
Corresponding to an <S$Anim> entry, this stores a single column of numbers, for instance for a morph ...
Definition: eggSAnimData.h:25
TypedObject::is_of_type
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
EggCharacterDb
This class is used during joint optimization or restructuring to store the table of interim joint com...
Definition: eggCharacterDb.h:41