Panda3D
eggJointNodePointer.cxx
1 // Filename: eggJointNodePointer.cxx
2 // Created by: drose (26Feb01)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "eggJointNodePointer.h"
16 
17 #include "dcast.h"
18 #include "eggObject.h"
19 #include "eggGroup.h"
20 #include "pointerTo.h"
21 
22 
23 TypeHandle EggJointNodePointer::_type_handle;
24 
25 ////////////////////////////////////////////////////////////////////
26 // Function: EggJointNodePointer::Constructor
27 // Access: Public
28 // Description:
29 ////////////////////////////////////////////////////////////////////
30 EggJointNodePointer::
31 EggJointNodePointer(EggObject *object) {
32  _joint = DCAST(EggGroup, object);
33 
34  if (_joint != (EggGroup *)NULL && _joint->is_joint()) {
35  // Quietly insist that the joint has a transform, for neatness. If
36  // it does not, give it the identity transform.
37  if (!_joint->has_transform()) {
38  _joint->set_transform3d(LMatrix4d::ident_mat());
39  }
40  }
41 }
42 
43 ////////////////////////////////////////////////////////////////////
44 // Function: EggJointNodePointer::get_num_frames
45 // Access: Public, Virtual
46 // Description: Returns the number of frames of animation for this
47 // particular joint.
48 //
49 // In the case of a EggJointNodePointer, which just
50 // stores a pointer to a <Joint> entry for a character
51 // model (not an animation table), there is always
52 // exactly one frame: the rest pose.
53 ////////////////////////////////////////////////////////////////////
55 get_num_frames() const {
56  return 1;
57 }
58 
59 ////////////////////////////////////////////////////////////////////
60 // Function: EggJointNodePointer::get_frame
61 // Access: Public, Virtual
62 // Description: Returns the transform matrix corresponding to this
63 // joint position in the nth frame.
64 //
65 // In the case of a EggJointNodePointer, which just
66 // stores a pointer to a <Joint> entry for a character
67 // model (not an animation table), there is always
68 // exactly one frame: the rest pose.
69 ////////////////////////////////////////////////////////////////////
71 get_frame(int n) const {
72  nassertr(n == 0, LMatrix4d::ident_mat());
73  return _joint->get_transform3d();
74 }
75 
76 ////////////////////////////////////////////////////////////////////
77 // Function: EggJointNodePointer::set_frame
78 // Access: Public, Virtual
79 // Description: Sets the transform matrix corresponding to this
80 // joint position in the nth frame.
81 //
82 // In the case of a EggJointNodePointer, which just
83 // stores a pointer to a <Joint> entry for a character
84 // model (not an animation table), there is always
85 // exactly one frame: the rest pose.
86 ////////////////////////////////////////////////////////////////////
88 set_frame(int n, const LMatrix4d &mat) {
89  nassertv(n == 0);
90  _joint->set_transform3d(mat);
91 }
92 
93 ////////////////////////////////////////////////////////////////////
94 // Function: EggJointNodePointer::do_finish_reparent
95 // Access: Protected
96 // Description: Performs the actual reparenting operation
97 // by removing the node from its old parent and
98 // associating it with its new parent, if any.
99 ////////////////////////////////////////////////////////////////////
102  if (new_parent == (EggJointPointer *)NULL) {
103  // No new parent; unparent the joint.
104  EggGroupNode *egg_parent = _joint->get_parent();
105  if (egg_parent != (EggGroupNode *)NULL) {
106  egg_parent->remove_child(_joint.p());
107  egg_parent->steal_children(*_joint);
108  }
109 
110  } else {
111  // Reparent the joint to its new parent (implicitly unparenting it
112  // from its previous parent).
113  EggJointNodePointer *new_node = DCAST(EggJointNodePointer, new_parent);
114  if (new_node->_joint != _joint->get_parent()) {
115  new_node->_joint->add_child(_joint.p());
116  }
117  }
118 }
119 
120 ////////////////////////////////////////////////////////////////////
121 // Function: EggJointNodePointer::move_vertices_to
122 // Access: Public, Virtual
123 // Description: Moves the vertices assigned to this joint into the
124 // other joint (which should be of the same type).
125 ////////////////////////////////////////////////////////////////////
128  if (new_joint == (EggJointPointer *)NULL) {
129  _joint->unref_all_vertices();
130 
131  } else {
132  EggJointNodePointer *new_node;
133  DCAST_INTO_V(new_node, new_joint);
134 
135  new_node->_joint->steal_vrefs(_joint);
136  }
137 }
138 
139 ////////////////////////////////////////////////////////////////////
140 // Function: EggJointNodePointer::do_rebuild
141 // Access: Public, Virtual
142 // Description: Rebuilds the entire table all at once, based on the
143 // frames added by repeated calls to add_rebuild_frame()
144 // since the last call to begin_rebuild().
145 //
146 // Until do_rebuild() is called, the animation table is
147 // not changed.
148 //
149 // The return value is true if all frames are
150 // acceptable, or false if there is some problem.
151 ////////////////////////////////////////////////////////////////////
154  LMatrix4d mat;
155  if (!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 0, mat)) {
156  // No rebuild frame; this is OK.
157  return true;
158  }
159 
160  _joint->set_transform3d(mat);
161 
162  // We shouldn't have a frame 1.
163  nassertr(!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 1, mat), false);
164 
165  return true;
166 }
167 
168 ////////////////////////////////////////////////////////////////////
169 // Function: EggJointNodePointer::expose
170 // Access: Public, Virtual
171 // Description: Flags the joint with the indicated DCS flag so that
172 // it will be loaded as a separate node in the player.
173 ////////////////////////////////////////////////////////////////////
175 expose(EggGroup::DCSType dcs_type) {
176  if (_joint != (EggGroup *)NULL) {
177  _joint->set_dcs_type(dcs_type);
178  }
179 }
180 
181 ////////////////////////////////////////////////////////////////////
182 // Function: EggJointNodePointer::apply_default_pose
183 // Access: Public, Virtual
184 // Description: Applies the pose from the indicated frame of the
185 // indicated source joint as the initial pose for
186 // this joint.
187 ////////////////////////////////////////////////////////////////////
189 apply_default_pose(EggJointPointer *source_joint, int frame) {
190  if (_joint != (EggGroup *)NULL) {
191  LMatrix4d pose;
192  if (frame >= 0 && frame < source_joint->get_num_frames()) {
193  pose = source_joint->get_frame(frame);
194  } else {
195  pose = get_frame(0);
196  }
197  _joint->clear_default_pose();
198  _joint->modify_default_pose().add_matrix4(pose);
199  }
200 }
201 
202 ////////////////////////////////////////////////////////////////////
203 // Function: EggJointNodePointer::has_vertices
204 // Access: Public, Virtual
205 // Description: Returns true if there are any vertices referenced by
206 // the node this points to, false otherwise. For
207 // certain kinds of back pointers (e.g. table animation
208 // entries), this is always false.
209 ////////////////////////////////////////////////////////////////////
211 has_vertices() const {
212  if (_joint != (EggGroup *)NULL) {
213  return (_joint->vref_size() != 0) || _joint->joint_has_primitives();
214  }
215 
216  return false;
217 }
218 
219 ////////////////////////////////////////////////////////////////////
220 // Function: EggJointNodePointer::make_new_joint
221 // Access: Public, Virtual
222 // Description: Creates a new child of the current joint in the
223 // egg data, and returns a pointer to it.
224 ////////////////////////////////////////////////////////////////////
226 make_new_joint(const string &name) {
227  EggGroup *new_joint = new EggGroup(name);
228  new_joint->set_group_type(EggGroup::GT_joint);
229  _joint->add_child(new_joint);
230  return new EggJointNodePointer(new_joint);
231 }
232 
233 ////////////////////////////////////////////////////////////////////
234 // Function: EggJointNodePointer::set_name
235 // Access: Public, Virtual
236 // Description: Applies the indicated name change to the egg file.
237 ////////////////////////////////////////////////////////////////////
239 set_name(const string &name) {
240  _joint->set_name(name);
241 }
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:4716
virtual LMatrix4d get_frame(int n) const
Returns the transform matrix corresponding to this joint position in the nth frame.
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:51
virtual void apply_default_pose(EggJointPointer *source_joint, int frame)
Applies the pose from the indicated frame of the indicated source joint as the initial pose for this ...
virtual void move_vertices_to(EggJointPointer *new_joint)
Moves the vertices assigned to this joint into the other joint (which should be of the same type)...
virtual bool has_vertices() const
Returns true if there are any vertices referenced by the node this points to, false otherwise...
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...
virtual void do_finish_reparent(EggJointPointer *new_parent)
Performs the actual reparenting operation by removing the node from its old parent and associating it...
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:36
This stores a pointer back to a <Joint> node.
This class is used during joint optimization or restructuring to store the table of interim joint com...
virtual int get_num_frames() const
Returns the number of frames of animation for this particular joint.
static const LMatrix4d & ident_mat()
Returns an identity matrix.
Definition: lmatrix.h:5168
void steal_children(EggGroupNode &other)
Moves all the children from the other node to this one.
virtual void expose(EggGroup::DCSType dcs_type)
Flags the joint with the indicated DCS flag so that it will be loaded as a separate node in the playe...
This is a base class for EggJointNodePointer and EggMatrixTablePointer.
virtual void set_name(const string &name)
Applies the indicated name change to the egg file.
virtual EggJointPointer * make_new_joint(const string &name)
Creates a new child of the current joint in the egg data, and returns a pointer to it...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
The highest-level base class in the egg directory.
Definition: eggObject.h:31
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)...
virtual void set_frame(int n, const LMatrix4d &mat)
Sets the transform matrix corresponding to this joint position in the nth frame.