00001 // Filename: eggJointNodePointer.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 "eggJointNodePointer.h" 00016 00017 #include "dcast.h" 00018 #include "eggObject.h" 00019 #include "eggGroup.h" 00020 #include "pointerTo.h" 00021 00022 00023 TypeHandle EggJointNodePointer::_type_handle; 00024 00025 //////////////////////////////////////////////////////////////////// 00026 // Function: EggJointNodePointer::Constructor 00027 // Access: Public 00028 // Description: 00029 //////////////////////////////////////////////////////////////////// 00030 EggJointNodePointer:: 00031 EggJointNodePointer(EggObject *object) { 00032 _joint = DCAST(EggGroup, object); 00033 00034 if (_joint != (EggGroup *)NULL && _joint->is_joint()) { 00035 // Quietly insist that the joint has a transform, for neatness. If 00036 // it does not, give it the identity transform. 00037 if (!_joint->has_transform()) { 00038 _joint->set_transform3d(LMatrix4d::ident_mat()); 00039 } 00040 } 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: EggJointNodePointer::get_num_frames 00045 // Access: Public, Virtual 00046 // Description: Returns the number of frames of animation for this 00047 // particular joint. 00048 // 00049 // In the case of a EggJointNodePointer, which just 00050 // stores a pointer to a <Joint> entry for a character 00051 // model (not an animation table), there is always 00052 // exactly one frame: the rest pose. 00053 //////////////////////////////////////////////////////////////////// 00054 int EggJointNodePointer:: 00055 get_num_frames() const { 00056 return 1; 00057 } 00058 00059 //////////////////////////////////////////////////////////////////// 00060 // Function: EggJointNodePointer::get_frame 00061 // Access: Public, Virtual 00062 // Description: Returns the transform matrix corresponding to this 00063 // joint position in the nth frame. 00064 // 00065 // In the case of a EggJointNodePointer, which just 00066 // stores a pointer to a <Joint> entry for a character 00067 // model (not an animation table), there is always 00068 // exactly one frame: the rest pose. 00069 //////////////////////////////////////////////////////////////////// 00070 LMatrix4d EggJointNodePointer:: 00071 get_frame(int n) const { 00072 nassertr(n == 0, LMatrix4d::ident_mat()); 00073 return _joint->get_transform3d(); 00074 } 00075 00076 //////////////////////////////////////////////////////////////////// 00077 // Function: EggJointNodePointer::set_frame 00078 // Access: Public, Virtual 00079 // Description: Sets the transform matrix corresponding to this 00080 // joint position in the nth frame. 00081 // 00082 // In the case of a EggJointNodePointer, which just 00083 // stores a pointer to a <Joint> entry for a character 00084 // model (not an animation table), there is always 00085 // exactly one frame: the rest pose. 00086 //////////////////////////////////////////////////////////////////// 00087 void EggJointNodePointer:: 00088 set_frame(int n, const LMatrix4d &mat) { 00089 nassertv(n == 0); 00090 _joint->set_transform3d(mat); 00091 } 00092 00093 //////////////////////////////////////////////////////////////////// 00094 // Function: EggJointNodePointer::do_finish_reparent 00095 // Access: Protected 00096 // Description: Performs the actual reparenting operation 00097 // by removing the node from its old parent and 00098 // associating it with its new parent, if any. 00099 //////////////////////////////////////////////////////////////////// 00100 void EggJointNodePointer:: 00101 do_finish_reparent(EggJointPointer *new_parent) { 00102 if (new_parent == (EggJointPointer *)NULL) { 00103 // No new parent; unparent the joint. 00104 EggGroupNode *egg_parent = _joint->get_parent(); 00105 if (egg_parent != (EggGroupNode *)NULL) { 00106 egg_parent->remove_child(_joint.p()); 00107 egg_parent->steal_children(*_joint); 00108 } 00109 00110 } else { 00111 // Reparent the joint to its new parent (implicitly unparenting it 00112 // from its previous parent). 00113 EggJointNodePointer *new_node = DCAST(EggJointNodePointer, new_parent); 00114 if (new_node->_joint != _joint->get_parent()) { 00115 new_node->_joint->add_child(_joint.p()); 00116 } 00117 } 00118 } 00119 00120 //////////////////////////////////////////////////////////////////// 00121 // Function: EggJointNodePointer::move_vertices_to 00122 // Access: Public, Virtual 00123 // Description: Moves the vertices assigned to this joint into the 00124 // other joint (which should be of the same type). 00125 //////////////////////////////////////////////////////////////////// 00126 void EggJointNodePointer:: 00127 move_vertices_to(EggJointPointer *new_joint) { 00128 if (new_joint == (EggJointPointer *)NULL) { 00129 _joint->unref_all_vertices(); 00130 00131 } else { 00132 EggJointNodePointer *new_node; 00133 DCAST_INTO_V(new_node, new_joint); 00134 00135 new_node->_joint->steal_vrefs(_joint); 00136 } 00137 } 00138 00139 //////////////////////////////////////////////////////////////////// 00140 // Function: EggJointNodePointer::do_rebuild 00141 // Access: Public, Virtual 00142 // Description: Rebuilds the entire table all at once, based on the 00143 // frames added by repeated calls to add_rebuild_frame() 00144 // since the last call to begin_rebuild(). 00145 // 00146 // Until do_rebuild() is called, the animation table is 00147 // not changed. 00148 // 00149 // The return value is true if all frames are 00150 // acceptable, or false if there is some problem. 00151 //////////////////////////////////////////////////////////////////// 00152 bool EggJointNodePointer:: 00153 do_rebuild(EggCharacterDb &db) { 00154 LMatrix4d mat; 00155 if (!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 0, mat)) { 00156 // No rebuild frame; this is OK. 00157 return true; 00158 } 00159 00160 _joint->set_transform3d(mat); 00161 00162 // We shouldn't have a frame 1. 00163 nassertr(!db.get_matrix(this, EggCharacterDb::TT_rebuild_frame, 1, mat), false); 00164 00165 return true; 00166 } 00167 00168 //////////////////////////////////////////////////////////////////// 00169 // Function: EggJointNodePointer::expose 00170 // Access: Public, Virtual 00171 // Description: Flags the joint with the indicated DCS flag so that 00172 // it will be loaded as a separate node in the player. 00173 //////////////////////////////////////////////////////////////////// 00174 void EggJointNodePointer:: 00175 expose(EggGroup::DCSType dcs_type) { 00176 if (_joint != (EggGroup *)NULL) { 00177 _joint->set_dcs_type(dcs_type); 00178 } 00179 } 00180 00181 //////////////////////////////////////////////////////////////////// 00182 // Function: EggJointNodePointer::apply_default_pose 00183 // Access: Public, Virtual 00184 // Description: Applies the pose from the indicated frame of the 00185 // indicated source joint as the initial pose for 00186 // this joint. 00187 //////////////////////////////////////////////////////////////////// 00188 void EggJointNodePointer:: 00189 apply_default_pose(EggJointPointer *source_joint, int frame) { 00190 if (_joint != (EggGroup *)NULL) { 00191 LMatrix4d pose; 00192 if (frame >= 0 && frame < source_joint->get_num_frames()) { 00193 pose = source_joint->get_frame(frame); 00194 } else { 00195 pose = get_frame(0); 00196 } 00197 _joint->clear_default_pose(); 00198 _joint->modify_default_pose().add_matrix4(pose); 00199 } 00200 } 00201 00202 //////////////////////////////////////////////////////////////////// 00203 // Function: EggJointNodePointer::has_vertices 00204 // Access: Public, Virtual 00205 // Description: Returns true if there are any vertices referenced by 00206 // the node this points to, false otherwise. For 00207 // certain kinds of back pointers (e.g. table animation 00208 // entries), this is always false. 00209 //////////////////////////////////////////////////////////////////// 00210 bool EggJointNodePointer:: 00211 has_vertices() const { 00212 if (_joint != (EggGroup *)NULL) { 00213 return (_joint->vref_size() != 0) || _joint->joint_has_primitives(); 00214 } 00215 00216 return false; 00217 } 00218 00219 //////////////////////////////////////////////////////////////////// 00220 // Function: EggJointNodePointer::make_new_joint 00221 // Access: Public, Virtual 00222 // Description: Creates a new child of the current joint in the 00223 // egg data, and returns a pointer to it. 00224 //////////////////////////////////////////////////////////////////// 00225 EggJointPointer *EggJointNodePointer:: 00226 make_new_joint(const string &name) { 00227 EggGroup *new_joint = new EggGroup(name); 00228 new_joint->set_group_type(EggGroup::GT_joint); 00229 _joint->add_child(new_joint); 00230 return new EggJointNodePointer(new_joint); 00231 } 00232 00233 //////////////////////////////////////////////////////////////////// 00234 // Function: EggJointNodePointer::set_name 00235 // Access: Public, Virtual 00236 // Description: Applies the indicated name change to the egg file. 00237 //////////////////////////////////////////////////////////////////// 00238 void EggJointNodePointer:: 00239 set_name(const string &name) { 00240 _joint->set_name(name); 00241 }