Panda3D
character.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 character.cxx
10  * @author drose
11  * @date 2002-03-06
12  */
13 
14 #include "character.h"
15 #include "characterJoint.h"
16 #include "config_char.h"
17 #include "nodePath.h"
18 #include "geomNode.h"
19 #include "datagram.h"
20 #include "datagramIterator.h"
21 #include "bamReader.h"
22 #include "bamWriter.h"
23 #include "pStatTimer.h"
24 #include "animControl.h"
25 #include "clockObject.h"
26 #include "pStatTimer.h"
27 #include "camera.h"
28 #include "cullTraverser.h"
29 #include "cullTraverserData.h"
30 
31 TypeHandle Character::_type_handle;
32 
33 PStatCollector Character::_animation_pcollector("*:Animation");
34 
35 /**
36  * Use make_copy() or copy_subgraph() to copy a Character.
37  */
38 Character::
39 Character(const Character &copy, bool copy_bundles) :
40  PartBundleNode(copy),
41  _lod_center(copy._lod_center),
42  _lod_far_distance(copy._lod_far_distance),
43  _lod_near_distance(copy._lod_near_distance),
44  _lod_delay_factor(copy._lod_delay_factor),
45  _do_lod_animation(copy._do_lod_animation),
46  _joints_pcollector(copy._joints_pcollector),
47  _skinning_pcollector(copy._skinning_pcollector)
48 {
49  set_cull_callback();
50 
51  if (copy_bundles) {
52  // Copy the bundle(s).
53  int num_bundles = copy.get_num_bundles();
54  for (int i = 0; i < num_bundles; ++i) {
55  PartBundle *orig_bundle = copy.get_bundle(i);
56  PT(PartBundle) new_bundle = DCAST(PartBundle, orig_bundle->copy_subgraph());
57  add_bundle(new_bundle);
58  }
59  } else {
60  // Share the bundles.
61  int num_bundles = copy.get_num_bundles();
62  for (int i = 0; i < num_bundles; ++i) {
63  PartBundle *orig_bundle = copy.get_bundle(i);
64  add_bundle(orig_bundle);
65  }
66  }
67  _last_auto_update = -1.0;
68  _view_frame = -1;
69  _view_distance2 = 0.0f;
70 }
71 
72 /**
73  *
74  */
75 Character::
76 Character(const std::string &name) :
77  PartBundleNode(name, new CharacterJointBundle(name)),
78  _joints_pcollector(PStatCollector(_animation_pcollector, name), "Joints"),
79  _skinning_pcollector(PStatCollector(_animation_pcollector, name), "Vertices")
80 {
81  set_cull_callback();
82  clear_lod_animation();
83  _last_auto_update = -1.0;
84  _view_frame = -1;
85  _view_distance2 = 0.0f;
86 }
87 
88 /**
89  *
90  */
91 Character::
92 ~Character() {
93  int num_bundles = get_num_bundles();
94  for (int i = 0; i < num_bundles; ++i) {
95  r_clear_joint_characters(get_bundle(i));
96  }
97 }
98 
99 /**
100  * The Character make_copy() function will make a new copy of the Character,
101  * with all of its joints copied, and with a new set of dynamic vertex arrays
102  * all ready to go, but it will not copy any of the original Character's
103  * geometry, so the new Character won't look like much. Use copy_subgraph()
104  * to make a full copy of the Character.
105  */
107 make_copy() const {
108  return new Character(*this, true);
109 }
110 
111 /**
112  * This is similar to make_copy(), but it makes a copy for the specific
113  * purpose of flatten. Typically, this will be a new PandaNode with a new
114  * pointer, but all of the internal data will always be shared with the
115  * original; whereas the new node returned by make_copy() might not share the
116  * internal data.
117  */
120  return new Character(*this, false);
121 }
122 
123 /**
124  * Collapses this node with the other node, if possible, and returns a pointer
125  * to the combined node, or NULL if the two nodes cannot safely be combined.
126  *
127  * The return value may be this, other, or a new node altogether.
128  *
129  * This function is called from GraphReducer::flatten(), and need not deal
130  * with children; its job is just to decide whether to collapse the two nodes
131  * and what the collapsed node should look like.
132  */
135  if (is_exact_type(get_class_type()) &&
136  other->is_exact_type(get_class_type())) {
137  // Two Characters can combine by moving PartBundles from one to the other.
138  Character *c_other = DCAST(Character, other);
139  steal_bundles(c_other);
140  return this;
141  }
142 
143  return PandaNode::combine_with(other);
144 }
145 
146 /**
147  * This function will be called during the cull traversal to perform any
148  * additional operations that should be performed at cull time. This may
149  * include additional manipulation of render state or additional
150  * visible/invisible decisions, or any other arbitrary operation.
151  *
152  * Note that this function will *not* be called unless set_cull_callback() is
153  * called in the constructor of the derived class. It is necessary to call
154  * set_cull_callback() to indicated that we require cull_callback() to be
155  * called.
156  *
157  * By the time this function is called, the node has already passed the
158  * bounding-volume test for the viewing frustum, and the node's transform and
159  * state have already been applied to the indicated CullTraverserData object.
160  *
161  * The return value is true if this node should be visible, or false if it
162  * should be culled.
163  */
164 bool Character::
166  // For now, we update the character during the cull traversal; this prevents
167  // us from needlessly updating characters that aren't in the view frustum.
168  // We may need a better way to do this optimization later, to handle
169  // characters that might animate themselves in front of the view frustum.
170 
171  if (_do_lod_animation) {
172  int this_frame = ClockObject::get_global_clock()->get_frame_count();
173 
174  CPT(TransformState) rel_transform = get_rel_transform(trav, data);
175  LPoint3 center = _lod_center * rel_transform->get_mat();
176  PN_stdfloat dist2 = center.dot(center);
177 
178  if (this_frame != _view_frame || dist2 < _view_distance2) {
179  _view_frame = this_frame;
180  _view_distance2 = dist2;
181 
182  // Now compute the lod delay.
183  PN_stdfloat dist = sqrt(dist2);
184  double delay = 0.0;
185  if (dist > _lod_near_distance) {
186  delay = _lod_delay_factor * (dist - _lod_near_distance) / (_lod_far_distance - _lod_near_distance);
187  nassertr(delay > 0.0, false);
188  }
189  set_lod_current_delay(delay);
190 
191  if (char_cat.is_spam()) {
192  char_cat.spam()
193  << "Distance to " << NodePath::any_path(this) << " in frame "
194  << this_frame << " is " << dist << ", computed delay is " << delay
195  << "\n";
196  }
197  }
198  }
199 
200  update();
201  return true;
202 }
203 
204 /**
205  * This is used to support NodePath::calc_tight_bounds(). It is not intended
206  * to be called directly, and it has nothing to do with the normal Panda
207  * bounding-volume computation.
208  *
209  * If the node contains any geometry, this updates min_point and max_point to
210  * enclose its bounding box. found_any is to be set true if the node has any
211  * geometry at all, or left alone if it has none. This method may be called
212  * over several nodes, so it may enter with min_point, max_point, and
213  * found_any already set.
214  *
215  * This function is recursive, and the return value is the transform after it
216  * has been modified by this node's transform.
217  */
218 CPT(TransformState) Character::
219 calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point, bool &found_any,
220  const TransformState *transform, Thread *current_thread) const {
221  // This method is overridden by Character solely to provide a hook to force
222  // the joints to update before computing the bounding volume.
223  ((Character *)this)->update_to_now();
224 
225  // Unfortunately, calling update_to_now() will invalidate the node's cached
226  // bounding volume, which causes a problem when this is called during the
227  // traversal, e.g. due to a ShowBoundsEffect. As a hacky fix to work
228  // around this, we will force-recompute all of the bounding volumes of our
229  // parent nodes immediately.
230  Parents parents = get_parents();
231  for (size_t i = 0; i < parents.get_num_parents(); ++i) {
232  PandaNode *parent = parents.get_parent(i);
233  parent->get_bounds();
234  }
235 
236  return PandaNode::calc_tight_bounds(min_point, max_point,
237  found_any, transform, current_thread);
238 }
239 
240 /**
241  * Merges old_bundle with new_bundle. old_bundle must be one of the
242  * PartBundles within this node. At the end of this call, the old_bundle
243  * pointer within this node will be replaced with the new_bundle pointer, and
244  * all geometry within this node will be updated to reference new_bundle.
245  *
246  * This method is deprecated. Use the newer version of this method, below.
247  */
248 void Character::
249 merge_bundles(PartBundle *old_bundle, PartBundle *new_bundle) {
250  if (old_bundle == new_bundle) {
251  // Trivially return.
252  return;
253  }
254 
255  // Find the PartBundleHandle of old_bundle.
256  PT(PartBundleHandle) old_bundle_handle;
257  Bundles::const_iterator bi;
258  for (bi = _bundles.begin(); bi != _bundles.end(); ++bi) {
259  if ((*bi)->get_bundle() == old_bundle) {
260  old_bundle_handle = (*bi);
261  break;
262  }
263  }
264  nassertv(!old_bundle_handle.is_null());
265 
266  PT(PartBundleHandle) new_bundle_handle = new PartBundleHandle(new_bundle);
267  merge_bundles(old_bundle_handle, new_bundle_handle);
268 }
269 
270 /**
271  * Merges old_bundle_handle->get_bundle() with new_bundle. old_bundle_handle
272  * must be one of the PartBundleHandle within this node. At the end of this
273  * call, the bundle pointer within the old_bundle_handle will be replaced with
274  * that within the new_bundle_handle pointer, and all geometry within this
275  * node will be updated to reference new_bundle.
276  *
277  * Normally, this is called when the two bundles have the same, or nearly the
278  * same, hierarchies. In this case, new_bundle will simply be assigned over
279  * the old_bundle position. However, if any joints are present in one bundle
280  * or the other, new_bundle will be modified to contain the union of all
281  * joints.
282  *
283  * The geometry below this node is also updated to reference new_bundle,
284  * instead of the original old_bundle.
285  *
286  * This method is intended to unify two different models that share a common
287  * skeleton, for instance, different LOD's of the same model.
288  */
289 void Character::
290 merge_bundles(PartBundleHandle *old_bundle_handle,
291  PartBundleHandle *new_bundle_handle) {
292  PartBundle *old_bundle = old_bundle_handle->get_bundle();
293  PartBundle *new_bundle = new_bundle_handle->get_bundle();
294  new_bundle->merge_anim_preloads(old_bundle);
295 
296  update_bundle(old_bundle_handle, new_bundle);
297 }
298 
299 /**
300  * Activates a special mode in which the character animates less frequently as
301  * it gets further from the camera. This is intended as a simple optimization
302  * to minimize the effort of computing animation for lots of characters that
303  * may not necessarily be very important to animate every frame.
304  *
305  * If the character is closer to the camera than near_distance, then it is
306  * animated its normal rate, every frame. If the character is exactly
307  * far_distance away, it is animated only every delay_factor seconds (which
308  * should be a number greater than 0). If the character is between
309  * near_distance and far_distance, its animation rate is linearly interpolated
310  * according to its distance between the two. The interpolation function
311  * continues beyond far_distance, so that the character is animated
312  * increasingly less frequently as it gets farther away.
313  *
314  * The distance calculations are made from center, which is a fixed point
315  * relative to the character node, to the camera's lod center or cull center
316  * node (or to the camera node itself).
317  *
318  * If multiple cameras are viewing the character in any given frame, the
319  * closest one counts.
320  */
321 void Character::
322 set_lod_animation(const LPoint3 &center,
323  PN_stdfloat far_distance, PN_stdfloat near_distance,
324  PN_stdfloat delay_factor) {
325  nassertv(far_distance >= near_distance);
326  nassertv(delay_factor >= 0.0f);
327  _lod_center = center;
328  _lod_far_distance = far_distance;
329  _lod_near_distance = near_distance;
330  _lod_delay_factor = delay_factor;
331  _do_lod_animation = (_lod_far_distance > _lod_near_distance && _lod_delay_factor > 0.0);
332  if (!_do_lod_animation) {
333  set_lod_current_delay(0.0);
334  }
335 }
336 
337 /**
338  * Undoes the effect of a recent call to set_lod_animation(). Henceforth, the
339  * character will animate every frame, regardless of its distance from the
340  * camera.
341  */
342 void Character::
344  _lod_center = LPoint3::zero();
345  _lod_far_distance = 0.0f;
346  _lod_near_distance = 0.0f;
347  _lod_delay_factor = 0.0f;
348  _do_lod_animation = false;
349  set_lod_current_delay(0.0);
350 }
351 
352 /**
353  * Returns a pointer to the joint with the given name, if there is such a
354  * joint, or NULL if there is no such joint. This will not return a pointer
355  * to a slider.
356  */
358 find_joint(const std::string &name) const {
359  int num_bundles = get_num_bundles();
360  for (int i = 0; i < num_bundles; ++i) {
361  PartGroup *part = get_bundle(i)->find_child(name);
362  if (part != nullptr && part->is_character_joint()) {
363  return DCAST(CharacterJoint, part);
364  }
365  }
366 
367  return nullptr;
368 }
369 
370 /**
371  * Returns a pointer to the slider with the given name, if there is such a
372  * slider, or NULL if there is no such slider. This will not return a pointer
373  * to a joint.
374  */
376 find_slider(const std::string &name) const {
377  int num_bundles = get_num_bundles();
378  for (int i = 0; i < num_bundles; ++i) {
379  PartGroup *part = get_bundle(i)->find_child(name);
380  if (part != nullptr &&
381  part->is_of_type(CharacterSlider::get_class_type())) {
382  return DCAST(CharacterSlider, part);
383  }
384  }
385 
386  return nullptr;
387 }
388 
389 /**
390  * Writes a list of the Character's joints and sliders, in their hierchical
391  * structure, to the indicated output stream.
392  */
393 void Character::
394 write_parts(std::ostream &out) const {
395  int num_bundles = get_num_bundles();
396  for (int i = 0; i < num_bundles; ++i) {
397  get_bundle(i)->write(out, 0);
398  }
399 }
400 
401 /**
402  * Writes a list of the Character's joints and sliders, along with each
403  * current position, in their hierchical structure, to the indicated output
404  * stream.
405  */
406 void Character::
407 write_part_values(std::ostream &out) const {
408  int num_bundles = get_num_bundles();
409  for (int i = 0; i < num_bundles; ++i) {
410  get_bundle(i)->write_with_value(out, 0);
411  }
412 }
413 
414 /**
415  * Advances the character's frame to the current time, and then calls
416  * update(). This can be used by show code to force an update of the
417  * character's position to the current frame, regardless of whether the
418  * character is currently onscreen and animating.
419  *
420  * This method is deprecated. Call update() instead.
421  */
422 void Character::
424  update();
425 }
426 
427 /**
428  * Recalculates the Character's joints and vertices for the current frame.
429  * Normally this is performed automatically during the render and need not be
430  * called explicitly.
431  */
432 void Character::
435  if (now != _last_auto_update) {
436  _last_auto_update = now;
437 
438  if (char_cat.is_spam()) {
439  char_cat.spam()
440  << "Animating " << NodePath::any_path(this)
441  << " at time " << now << "\n";
442  }
443 
444  PStatTimer timer(_joints_pcollector);
445  do_update();
446  }
447 }
448 
449 /**
450  * Recalculates the character even if we think it doesn't need it.
451  */
452 void Character::
454  // Statistics
455  PStatTimer timer(_joints_pcollector);
456 
457  // Update all the joints and sliders.
458  int num_bundles = get_num_bundles();
459  for (int i = 0; i < num_bundles; ++i) {
460  get_bundle(i)->force_update();
461  }
462 }
463 
464 /**
465  * This is called by r_copy_subgraph(); the copy has already been made of this
466  * particular node (and this is the copy); this function's job is to copy all
467  * of the children from the original.
468  *
469  * Note that it includes the parameter inst_map, which is a map type, and is
470  * not (and cannot be) exported from PANDA.DLL. Thus, any derivative of
471  * PandaNode that is not also a member of PANDA.DLL *cannot* access this map,
472  * and probably should not even override this function.
473  */
474 void Character::
475 r_copy_children(const PandaNode *from, PandaNode::InstanceMap &inst_map,
476  Thread *current_thread) {
477  // We assume there will be no instancing going on below the Character node.
478  // If there is, too bad; it will get flattened out.
479 
480  // We preempt the node's r_copy_children() operation with our own function
481  // that keeps track of the old vs. new nodes and also updates any Geoms we
482  // find with our new dynamic vertices.
483 
484  const Character *from_char;
485  DCAST_INTO_V(from_char, from);
486  NodeMap node_map;
487  JointMap joint_map;
488 
489  int num_bundles = get_num_bundles();
490  nassertv(from_char->get_num_bundles() == num_bundles);
491  int i;
492  for (i = 0; i < num_bundles; ++i) {
493  fill_joint_map(joint_map, get_bundle(i), from_char->get_bundle(i));
494  }
495 
496  GeomVertexMap gvmap;
497  GeomJointMap gjmap;
498  GeomSliderMap gsmap;
499  r_copy_char(this, from_char, from_char, node_map, joint_map,
500  gvmap, gjmap, gsmap);
501 
502  for (i = 0; i < num_bundles; ++i) {
503  copy_node_pointers(node_map, get_bundle(i), from_char->get_bundle(i));
504  }
505 }
506 
507 /**
508  * Replaces the contents of the indicated PartBundleHandle (presumably stored
509  * within this node) with new_bundle.
510  */
511 void Character::
512 update_bundle(PartBundleHandle *old_bundle_handle, PartBundle *new_bundle) {
513  if (old_bundle_handle->get_bundle() == new_bundle) {
514  // Trivially return.
515  return;
516  }
517 
518  // First, merge the bundles, to ensure we have the same set of joints in the
519  // new bundle.
520  JointMap joint_map;
521  r_merge_bundles(joint_map, old_bundle_handle->get_bundle(), new_bundle);
522 
523  PartBundleNode::update_bundle(old_bundle_handle, new_bundle);
524 
525  // Now convert the geometry to use the new bundle.
526  GeomVertexMap gvmap;
527  GeomJointMap gjmap;
528  GeomSliderMap gsmap;
529  r_update_geom(this, joint_map, gvmap, gjmap, gsmap);
530 }
531 
532 /**
533  * Returns the relative transform to convert from the LODNode space to the
534  * camera space.
535  */
536 CPT(TransformState) Character::
537 get_rel_transform(CullTraverser *trav, CullTraverserData &data) {
538  // Get a pointer to the camera node.
539  Camera *camera = trav->get_scene()->get_camera_node();
540 
541  // Get the camera space transform.
542  CPT(TransformState) rel_transform;
543 
544  NodePath lod_center = camera->get_lod_center();
545  if (!lod_center.is_empty()) {
546  rel_transform =
547  lod_center.get_net_transform()->invert_compose(data.get_net_transform(trav));
548  } else {
549  NodePath cull_center = camera->get_cull_center();
550  if (!cull_center.is_empty()) {
551  rel_transform =
552  cull_center.get_net_transform()->invert_compose(data.get_net_transform(trav));
553  } else {
554  rel_transform = data.get_modelview_transform(trav);
555  }
556  }
557 
558  return rel_transform;
559 }
560 
561 /**
562  * The actual implementation of update(). Assumes the appropriate
563  * PStatCollector has already been started.
564  */
565 void Character::
566 do_update() {
567  // Update all the joints and sliders.
568  if (even_animation) {
569  int num_bundles = get_num_bundles();
570  for (int i = 0; i < num_bundles; ++i) {
571  get_bundle(i)->force_update();
572  }
573  } else {
574  int num_bundles = get_num_bundles();
575  for (int i = 0; i < num_bundles; ++i) {
576  get_bundle(i)->update();
577  }
578  }
579 }
580 
581 /**
582  * Changes the amount of delay we should impose due to the LOD animation
583  * setting.
584  */
585 void Character::
586 set_lod_current_delay(double delay) {
587  int num_bundles = get_num_bundles();
588  for (int i = 0; i < num_bundles; ++i) {
589  get_bundle(i)->set_update_delay(delay);
590  }
591 }
592 
593 /**
594  * After the joint hierarchy has already been copied from the indicated
595  * hierarchy, this recursively walks through the joints and builds up a
596  * mapping from old to new.
597  */
598 void Character::
599 fill_joint_map(Character::JointMap &joint_map,
600  PartGroup *copy, PartGroup *orig) {
601  joint_map[orig] = copy;
602 
603  int i = 0, j = 0;
604  int copy_num_children = copy->get_num_children();
605  int orig_num_children = orig->get_num_children();
606 
607  while (i < copy_num_children && j < orig_num_children) {
608  PartGroup *pc = copy->get_child(i);
609  PartGroup *ac = orig->get_child(j);
610 
611  if (pc->get_name() < ac->get_name()) {
612  i++;
613  } else if (ac->get_name() < pc->get_name()) {
614  j++;
615  } else {
616  fill_joint_map(joint_map, pc, ac);
617  i++;
618  j++;
619  }
620  }
621 }
622 
623 /**
624  * Recursively checks the two bundles for a matching hierarchy, and adds nodes
625  * as necessary to "new_group" where they are not already present. Also fills
626  * joint_map in the same manner as fill_joint_map().
627  */
628 void Character::
629 r_merge_bundles(Character::JointMap &joint_map,
630  PartGroup *old_group, PartGroup *new_group) {
631  joint_map[old_group] = new_group;
632 
633  if (new_group->is_character_joint()) {
634  CharacterJoint *new_joint;
635  DCAST_INTO_V(new_joint, new_group);
636 
637  // Make sure the new_joint references this as its new character.
638  new_joint->_character = this;
639 
640  if (old_group != new_group &&
641  old_group->is_character_joint()) {
642  CharacterJoint *old_joint;
643  DCAST_INTO_V(old_joint, old_group);
644 
645  // Since the old_joint will be getting dropped, reset its character
646  // reference.
647  old_joint->_character = nullptr;
648 
649  // Copy any _net_transform and _local_transform operations to the new
650  // joint.
651  CharacterJoint::NodeList::iterator ni;
652  for (ni = old_joint->_net_transform_nodes.begin();
653  ni != old_joint->_net_transform_nodes.end();
654  ++ni) {
655  new_joint->_net_transform_nodes.insert(*ni);
656  }
657  for (ni = old_joint->_local_transform_nodes.begin();
658  ni != old_joint->_local_transform_nodes.end();
659  ++ni) {
660  new_joint->_local_transform_nodes.insert(*ni);
661  }
662  }
663  }
664 
665  if (old_group == new_group) {
666  return;
667  }
668 
669  int i = 0, j = 0;
670  int old_num_children = old_group->get_num_children();
671  int new_num_children = new_group->get_num_children();
672 
673  PartGroup::Children new_children(PartGroup::get_class_type());
674  new_children.reserve(std::max(old_num_children, new_num_children));
675 
676  while (i < old_num_children && j < new_num_children) {
677  PartGroup *pc = old_group->get_child(i);
678  PartGroup *ac = new_group->get_child(j);
679 
680  if (pc->get_name() < ac->get_name()) {
681  // Here is a group that exists in old_group, but not in new_group.
682  // Duplicate it.
683  PartGroup *new_pc = pc->make_copy();
684  new_children.push_back(new_pc);
685 
686  r_merge_bundles(joint_map, pc, new_pc);
687  i++;
688 
689  } else if (ac->get_name() < pc->get_name()) {
690  // Here is a group that exists in new_group, but not in old_group.
691  // Preserve it.
692  new_children.push_back(ac);
693 
694  r_merge_bundles(joint_map, ac, ac);
695  j++;
696 
697  } else {
698  // Here is a group that exists in both. Preserve it.
699  new_children.push_back(ac);
700 
701  r_merge_bundles(joint_map, pc, ac);
702  i++;
703  j++;
704  }
705  }
706 
707  while (i < old_num_children) {
708  PartGroup *pc = old_group->get_child(i);
709 
710  // Here is a group that exists in old_group, but not in new_group.
711  // Duplicate it.
712  PartGroup *new_pc = pc->make_copy();
713  new_children.push_back(new_pc);
714 
715  r_merge_bundles(joint_map, pc, new_pc);
716  i++;
717  }
718 
719  while (j < new_num_children) {
720  PartGroup *ac = new_group->get_child(j);
721 
722  // Here is a group that exists in new_group, but not in old_group.
723  // Preserve it.
724  new_children.push_back(ac);
725 
726  r_merge_bundles(joint_map, ac, ac);
727  j++;
728  }
729 
730  new_group->_children.swap(new_children);
731 }
732 
733 
734 /**
735  * Recursively walks the scene graph hierarchy below the Character node,
736  * duplicating it while noting the orig:copy node mappings, and also updates
737  * any GeomNodes found.
738  */
739 void Character::
740 r_copy_char(PandaNode *dest, const PandaNode *source,
741  const Character *from, Character::NodeMap &node_map,
742  const Character::JointMap &joint_map,
745 
746  if (source->is_geom_node()) {
747  const GeomNode *source_gnode;
748  GeomNode *dest_gnode;
749  DCAST_INTO_V(source_gnode, source);
750  DCAST_INTO_V(dest_gnode, dest);
751 
752  dest_gnode->remove_all_geoms();
753  int num_geoms = source_gnode->get_num_geoms();
754  for (int i = 0; i < num_geoms; i++) {
755  const Geom *geom = source_gnode->get_geom(i);
756  const RenderState *state = source_gnode->get_geom_state(i);
757  dest_gnode->add_geom(copy_geom(geom, joint_map, gvmap, gjmap, gsmap), state);
758  }
759  }
760 
761  int num_children = source->get_num_children();
762  for (int i = 0; i < num_children; i++) {
763  const PandaNode *source_child = source->get_child(i);
764  int source_sort = source->get_child_sort(i);
765 
766  PT(PandaNode) dest_child;
767  if (source_child->is_of_type(Character::get_class_type())) {
768  // We make a special case for nodes of type Character. If we encounter
769  // one of these, we have a Character under a Character, and the nested
770  // Character's copy should be called instead of ours.
771  dest_child = source_child->copy_subgraph();
772 
773  } else {
774  // Otherwise, we assume that make_copy() will make a suitable copy of
775  // the node. This does limit the sorts of things we can have parented
776  // to a Character and expect copy_subgraph() to work correctly. Too
777  // bad.
778  dest_child = source_child->make_copy();
779  r_copy_char(dest_child, source_child, from, node_map, joint_map,
780  gvmap, gjmap, gsmap);
781  }
782  dest->add_child(dest_child, source_sort);
783  node_map[source_child] = dest_child;
784  }
785 }
786 
787 /**
788  * Walks the hierarchy, updating any GeomNodes in-place to reference the new
789  * animation tables within this Character.
790  */
791 void Character::
792 r_update_geom(PandaNode *node, const Character::JointMap &joint_map,
795  Character::GeomSliderMap &gsmap) {
796  if (node->is_geom_node()) {
797  GeomNode *gnode;
798  DCAST_INTO_V(gnode, node);
799 
800  int num_geoms = gnode->get_num_geoms();
801  for (int i = 0; i < num_geoms; i++) {
802  CPT(Geom) geom = gnode->get_geom(i);
803  PT(Geom) new_geom = copy_geom(geom, joint_map, gvmap, gjmap, gsmap);
804  gnode->set_geom(i, new_geom);
805  }
806  }
807 
808  int num_children = node->get_num_children();
809  for (int i = 0; i < num_children; i++) {
810  PandaNode *child = node->get_child(i);
811 
812  r_update_geom(child, joint_map, gvmap, gjmap, gsmap);
813  }
814 }
815 
816 /**
817  * Makes a new copy of the Geom with the dynamic vertex arrays replaced to
818  * reference this Character instead of the other one. If no arrays have
819  * changed, simply returns the same Geom.
820  */
821 PT(Geom) Character::
822 copy_geom(const Geom *source, const Character::JointMap &joint_map,
824  Character::GeomSliderMap &gsmap) {
825  CPT(GeomVertexFormat) format = source->get_vertex_data()->get_format();
826  if (format->get_animation().get_animation_type() == Geom::AT_none) {
827  // Not animated, so never mind.
828  return (Geom *)source;
829  }
830 
831  PT(Geom) dest = source->make_copy();
832 
833  CPT(GeomVertexData) orig_vdata = source->get_vertex_data();
834  PT(GeomVertexData) new_vdata;
835  GeomVertexMap::iterator gvmi = gvmap.find(orig_vdata);
836  if (gvmi != gvmap.end()) {
837  new_vdata = (*gvmi).second;
838  } else {
839  new_vdata = new GeomVertexData(*orig_vdata);
840 
841  new_vdata->set_transform_table(redirect_transform_table(orig_vdata->get_transform_table(), joint_map, gjmap));
842  new_vdata->set_transform_blend_table(redirect_transform_blend_table(orig_vdata->get_transform_blend_table(), joint_map, gjmap));
843  new_vdata->set_slider_table(redirect_slider_table(orig_vdata->get_slider_table(), gsmap));
844 
845  gvmap.insert(GeomVertexMap::value_type(orig_vdata, new_vdata));
846  }
847 
848  dest->set_vertex_data(new_vdata);
849 
850  return dest;
851 }
852 
853 /**
854  * Creates _net_transform_nodes and _local_transform_nodes as appropriate in
855  * each of the Character's joints, as copied from the other Character.
856  */
857 void Character::
858 copy_node_pointers(const Character::NodeMap &node_map,
859  PartGroup *dest, const PartGroup *source) {
860  if (dest->is_character_joint()) {
861  nassertv(dest != source);
862  const CharacterJoint *source_joint;
863  CharacterJoint *dest_joint;
864  DCAST_INTO_V(source_joint, source);
865  DCAST_INTO_V(dest_joint, dest);
866 
867  CharacterJoint::NodeList::const_iterator ai;
868  for (ai = source_joint->_net_transform_nodes.begin();
869  ai != source_joint->_net_transform_nodes.end();
870  ++ai) {
871  PandaNode *source_node = (*ai);
872 
873  NodeMap::const_iterator mi;
874  mi = node_map.find(source_node);
875  if (mi != node_map.end()) {
876  PandaNode *dest_node = (*mi).second;
877 
878  // Here's an internal joint that the source Character was animating
879  // directly. We'll animate our corresponding joint the same way.
880  dest_joint->set_character(this);
881  dest_joint->add_net_transform(dest_node);
882  }
883  }
884 
885  for (ai = source_joint->_local_transform_nodes.begin();
886  ai != source_joint->_local_transform_nodes.end();
887  ++ai) {
888  PandaNode *source_node = (*ai);
889 
890  NodeMap::const_iterator mi;
891  mi = node_map.find(source_node);
892  if (mi != node_map.end()) {
893  PandaNode *dest_node = (*mi).second;
894 
895  // Here's an internal joint that the source Character was animating
896  // directly. We'll animate our corresponding joint the same way.
897  dest_joint->set_character(this);
898  dest_joint->add_local_transform(dest_node);
899  }
900  }
901  }
902 
903  // Now recurse over children.
904  int i = 0, j = 0;
905  int dest_num_children = dest->get_num_children();
906  int source_num_children = source->get_num_children();
907 
908  while (i < dest_num_children && j < source_num_children) {
909  PartGroup *pc = dest->get_child(i);
910  PartGroup *ac = source->get_child(j);
911 
912  if (pc->get_name() < ac->get_name()) {
913  i++;
914  } else if (ac->get_name() < pc->get_name()) {
915  j++;
916  } else {
917  copy_node_pointers(node_map, pc, ac);
918  i++;
919  j++;
920  }
921  }
922 }
923 
924 /**
925  * Creates a new TransformTable, similar to the indicated one, with the joint
926  * and slider pointers redirected into this object.
927  */
928 CPT(TransformTable) Character::
929 redirect_transform_table(const TransformTable *source,
930  const Character::JointMap &joint_map,
931  Character::GeomJointMap &gjmap) {
932  if (source == nullptr) {
933  return nullptr;
934  }
935 
936  PT(TransformTable) dest = new TransformTable(*source);
937 
938  int num_transforms = dest->get_num_transforms();
939  for (int i = 0; i < num_transforms; ++i) {
940  const VertexTransform *vt = dest->get_transform(i);
941  PT(JointVertexTransform) new_jvt = redirect_joint(vt, joint_map, gjmap);
942  if (new_jvt != nullptr) {
943  dest->set_transform(i, new_jvt);
944  }
945  }
946 
947  return TransformTable::register_table(dest);
948 }
949 
950 /**
951  * Creates a new TransformBlendTable, similar to the indicated one, with the
952  * joint and slider pointers redirected into this object.
953  */
955 redirect_transform_blend_table(const TransformBlendTable *source,
956  const Character::JointMap &joint_map,
957  Character::GeomJointMap &gjmap) {
958  if (source == nullptr) {
959  return nullptr;
960  }
961 
962  PT(TransformBlendTable) dest = new TransformBlendTable(*source);
963 
964  int num_blends = dest->get_num_blends();
965  for (int i = 0; i < num_blends; ++i) {
966  TransformBlend blend = dest->get_blend(i);
967  int num_transforms = blend.get_num_transforms();
968  for (int j = 0; j < num_transforms; ++j) {
969  const VertexTransform *vt = blend.get_transform(j);
970  PT(JointVertexTransform) new_jvt = redirect_joint(vt, joint_map, gjmap);
971  if (new_jvt != nullptr) {
972  blend.set_transform(j, new_jvt);
973  }
974  }
975  dest->set_blend(i, blend);
976  }
977 
978  return dest;
979 }
980 
981 /**
982  * Creates a new SliderTable, similar to the indicated one, with the joint and
983  * slider pointers redirected into this object.
984  */
985 CPT(SliderTable) Character::
986 redirect_slider_table(const SliderTable *source,
987  Character::GeomSliderMap &gsmap) {
988  if (source == nullptr) {
989  return nullptr;
990  }
991 
992  PT(SliderTable) dest = new SliderTable(*source);
993 
994  int num_sliders = dest->get_num_sliders();
995  for (int i = 0; i < num_sliders; ++i) {
996  const VertexSlider *vs = dest->get_slider(i);
997  PT(CharacterVertexSlider) new_cvs = redirect_slider(vs, gsmap);
998  if (new_cvs != nullptr) {
999  dest->set_slider(i, new_cvs);
1000  }
1001  }
1002 
1003  return SliderTable::register_table(dest);
1004 }
1005 
1006 /**
1007  * Creates a new JointVertexTransform that is similar to the indicated one,
1008  * but points into this character. If one was already created (in the
1009  * GeomJointMap), returns it instead.
1010  */
1012 redirect_joint(const VertexTransform *vt,
1013  const Character::JointMap &joint_map,
1014  Character::GeomJointMap &gjmap) {
1015  GeomJointMap::iterator ji;
1016  ji = gjmap.find(vt);
1017  if (ji != gjmap.end()) {
1018  return (*ji).second;
1019  }
1020 
1021  PT(JointVertexTransform) new_jvt;
1022 
1023  if (vt->is_of_type(JointVertexTransform::get_class_type())) {
1024  const JointVertexTransform *jvt = DCAST(JointVertexTransform, vt);
1025  const CharacterJoint *orig_joint = jvt->get_joint();
1026  JointMap::const_iterator jmi = joint_map.find(orig_joint);
1027  if (jmi == joint_map.end()) {
1028  char_cat.error()
1029  << "Could not find joint " << *orig_joint
1030  << " within the character hierarchy.\n";
1031 
1032  } else {
1033  CharacterJoint *joint = DCAST(CharacterJoint, (*jmi).second);
1034  new_jvt = new JointVertexTransform(joint);
1035  }
1036  }
1037 
1038  gjmap[vt] = new_jvt;
1039  return new_jvt;
1040 }
1041 
1042 /**
1043  * Creates a new CharacterVertexSlider that is similar to the indicated one,
1044  * but points into this character. If one was already created (in the
1045  * GeomSliderMap), returns it instead.
1046  */
1048 redirect_slider(const VertexSlider *vs, Character::GeomSliderMap &gsmap) {
1049  GeomSliderMap::iterator ji;
1050  ji = gsmap.find(vs);
1051  if (ji != gsmap.end()) {
1052  return (*ji).second;
1053  }
1054 
1055  PT(CharacterVertexSlider) new_cvs;
1056 
1057  if (vs->is_of_type(CharacterVertexSlider::get_class_type())) {
1058  const CharacterVertexSlider *cvs = DCAST(CharacterVertexSlider, vs);
1059  CharacterSlider *slider = find_slider(cvs->get_char_slider()->get_name());
1060  if (slider != nullptr) {
1061  new_cvs = new CharacterVertexSlider(slider);
1062  }
1063  }
1064 
1065  gsmap[vs] = new_cvs;
1066  return new_cvs;
1067 }
1068 
1069 /**
1070  * Recursively walks through the joint hierarchy and clears any _character
1071  * pointers on all the joints. Intended to be called just before Character
1072  * destruction.
1073  */
1074 void Character::
1075 r_clear_joint_characters(PartGroup *part) {
1076  if (part->is_character_joint()) {
1077  CharacterJoint *joint = DCAST(CharacterJoint, part);
1078 
1079  // It is possible for the joint to reference a different Character here--
1080  // after merge_bundles() has been called, a particular joint will be
1081  // listed within more than one Character node, but it can only point back
1082  // to one of them.
1083  if (joint->get_character() == this) {
1084  joint->set_character(nullptr);
1085  }
1086  }
1087 
1088  int num_children = part->get_num_children();
1089  for (int i = 0; i < num_children; ++i) {
1090  PartGroup *child = part->get_child(i);
1091  r_clear_joint_characters(child);
1092  }
1093 }
1094 
1095 /**
1096  * Tells the BamReader how to create objects of type Character.
1097  */
1098 void Character::
1100  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
1101 }
1102 
1103 /**
1104  * Writes the contents of this object to the datagram for shipping out to a
1105  * Bam file.
1106  */
1107 void Character::
1109  PartBundleNode::write_datagram(manager, dg);
1110 
1111  // Record 0 parts written--we no longer write an array of parts.
1112  dg.add_uint16(0);
1113 }
1114 
1115 /**
1116  * Receives an array of pointers, one for each time manager->read_pointer()
1117  * was called in fillin(). Returns the number of pointers processed.
1118  */
1119 int Character::
1121  // Pretend to read the _temp_num_parts parts that were found in the bam
1122  // file.
1123  return PartBundleNode::complete_pointers(p_list, manager) + _temp_num_parts;
1124 }
1125 
1126 /**
1127  * This function is called by the BamReader's factory when a new object of
1128  * type Character is encountered in the Bam file. It should create the
1129  * Character and extract its information from the file.
1130  */
1131 TypedWritable *Character::
1132 make_from_bam(const FactoryParams &params) {
1133  Character *node = new Character("");
1134  DatagramIterator scan;
1135  BamReader *manager;
1136 
1137  parse_params(params, scan, manager);
1138  node->fillin(scan, manager);
1139 
1140  return node;
1141 }
1142 
1143 /**
1144  * This internal function is called by make_from_bam to read in all of the
1145  * relevant data from the BamFile for the new Character.
1146  */
1147 void Character::
1148 fillin(DatagramIterator &scan, BamReader *manager) {
1149  PartBundleNode::fillin(scan, manager);
1150 
1151  // We no longer read an array of parts here, but for backward compatibility,
1152  // we must read in the number of parts that used to be there, and read past
1153  // each of the pointers.
1154  _temp_num_parts = scan.get_uint16();
1155  for (unsigned int i = 0; i < _temp_num_parts; i++) {
1156  manager->read_pointer(scan);
1157  }
1158 
1159 #ifdef DO_PSTATS
1160  // Reinitialize our collectors with our name, now that we know it.
1161  if (has_name()) {
1162  _joints_pcollector =
1163  PStatCollector(PStatCollector(_animation_pcollector, get_name()), "Joints");
1164  _skinning_pcollector =
1165  PStatCollector(PStatCollector(_animation_pcollector, get_name()), "Vertices");
1166  }
1167 #endif
1168 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
get_geom_state
Returns the RenderState associated with the nth geom of the node.
Definition: geomNode.h:75
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
void set_geom(int n, Geom *geom)
Replaces the nth Geom of the node with a new pointer.
Definition: geomNode.cxx:635
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
const CharacterJoint * get_joint() const
Returns the joint for which this object returns the transform.
const CharacterSlider * get_char_slider() const
Returns the CharacterSlider object for which this object returns the slider value.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:38
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
Indicates a coordinate-system transform on vertices.
CharacterJoint * find_joint(const std::string &name) const
Returns a pointer to the joint with the given name, if there is such a joint, or NULL if there is no ...
Definition: character.cxx:358
get_num_transforms
Returns the number of transforms stored in the blend object.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The collection of all the joints and sliders in the character.
virtual PandaNode * dupe_for_flatten() const
This is similar to make_copy(), but it makes a copy for the specific purpose of flatten.
Definition: character.cxx:119
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: character.cxx:1108
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
void update()
Recalculates the Character's joints and vertices for the current frame.
Definition: character.cxx:433
virtual PandaNode * combine_with(PandaNode *other)
Collapses this PandaNode with the other PandaNode, if possible, and returns a pointer to the combined...
Definition: pandaNode.cxx:325
An animated character, with skeleton-morph animation and either soft- skinned or hard-skinned vertice...
Definition: character.h:38
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
CharacterSlider * find_slider(const std::string &name) const
Returns a pointer to the slider with the given name, if there is such a slider, or NULL if there is n...
Definition: character.cxx:376
virtual PandaNode * combine_with(PandaNode *other)
Collapses this node with the other node, if possible, and returns a pointer to the combined node,...
Definition: character.cxx:134
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
set_transform
Replaces the nth transform stored in the blend object.
virtual bool cull_callback(CullTraverser *trav, CullTraverserData &data)
This function will be called during the cull traversal to perform any additional operations that shou...
Definition: character.cxx:165
This collects together the pieces of data that are accumulated for each node while walking the scene ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is a specialization on VertexSlider that returns the slider value associated with a particular C...
This is an abstract base class that retains some slider value, which is a linear value that typically...
Definition: vertexSlider.h:37
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool add_net_transform(PandaNode *node)
Adds the indicated node to the list of nodes that will be updated each frame with the joint's net tra...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
This is a morph slider within the character.
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
get_num_children
Returns the number of child nodes of the group.
Definition: partGroup.h:72
get_lod_center
Returns the point from which the LOD distances will be measured, if it was set by set_lod_center(),...
Definition: camera.h:75
get_transform
Returns the nth transform stored in the blend object.
This is a trivial class returned by PartBundleNode::get_bundle().
void update_to_now()
Advances the character's frame to the current time, and then calls update().
Definition: character.cxx:423
bool force_update()
Updates all the parts in the bundle to reflect the data for the current frame, whether we believe it ...
Definition: partBundle.cxx:509
get_parents
Returns an object that can be used to walk through the list of parents of the node,...
Definition: pandaNode.h:786
static NodePath any_path(PandaNode *node, Thread *current_thread=Thread::get_current_thread())
Returns a new NodePath that represents any arbitrary path from the root to the indicated node.
Definition: nodePath.I:62
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
Definition: character.cxx:1120
get_bundle
Returns the actual PartBundle embedded within the handle.
bool add_local_transform(PandaNode *node)
Adds the indicated node to the list of nodes that will be updated each frame with the joint's local t...
PartGroup * find_child(const std::string &name) const
Returns the first descendant found with the indicated name, or NULL if no such descendant exists.
Definition: partGroup.cxx:136
A lightweight class that represents a single element that may be timed and/or counted via stats.
virtual void write(std::ostream &out, int indent_level) const
Writes a brief description of the bundle and all of its descendants.
Definition: partBundle.cxx:222
Stores the total set of VertexSliders that the vertices in a particular GeomVertexData object might d...
Definition: sliderTable.h:37
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition: bamReader.I:275
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
get_num_children
Returns the number of child nodes this node has.
Definition: pandaNode.h:124
CPT(TransformState) Character
This is used to support NodePath::calc_tight_bounds().
Definition: character.cxx:218
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
Definition: clockObject.h:91
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
Definition: clockObject.h:94
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
Definition: geom.cxx:100
This is an abstract base class that holds a pointer to some transform, computed in some arbitrary way...
This is a node that contains a pointer to an PartBundle.
virtual void write_with_value(std::ostream &out, int indent_level) const
Writes a brief description of the group, showing its current value, and that of all of its descendant...
Definition: partGroup.cxx:268
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for geometry primitives.
Definition: geom.h:54
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void register_factory(TypeHandle handle, CreateFunc *func, void *user_data=nullptr)
Registers a new kind of thing the Factory will be able to create.
Definition: factory.I:73
void set_update_delay(double delay)
Specifies the minimum amount of time, in seconds, that should elapse between any two consecutive upda...
Definition: partBundle.I:208
Camera * get_camera_node() const
Returns the camera used to render the scene.
Definition: sceneSetup.I:115
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_child_sort(int n, Thread *current_thread=Thread::get_current_thread()) const
Returns the sort index of the nth child node of this node (that is, the number that was passed to add...
Definition: pandaNode.I:78
virtual void write_datagram(BamWriter *manager, Datagram &me)
Writes the contents of this object to the datagram for shipping out to a Bam file.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
Definition: pandaNode.cxx:487
virtual bool is_character_joint() const
Returns true if this part is a CharacterJoint, false otherwise.
Definition: partGroup.cxx:58
get_cull_center
Returns the point from which the culling operations will be performed, if it was set by set_cull_cent...
Definition: camera.h:67
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
void set_lod_animation(const LPoint3 &center, PN_stdfloat far_distance, PN_stdfloat near_distance, PN_stdfloat delay_factor)
Activates a special mode in which the character animates less frequently as it gets further from the ...
Definition: character.cxx:322
get_parent
Returns the nth parent node of this node.
Definition: pandaNode.h:118
This defines a single entry in a TransformBlendTable.
PT(Geom) Character
Makes a new copy of the Geom with the dynamic vertex arrays replaced to reference this Character inst...
Definition: character.cxx:821
This class defines the physical layout of the vertex data stored within a Geom.
This is a specialization on VertexTransform that returns the transform necessary to move vertices as ...
Stores the total set of VertexTransforms that the vertices in a particular GeomVertexData object migh...
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
get_num_geoms
Returns the number of geoms in the node.
Definition: geomNode.h:71
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A thread; that is, a lightweight process.
Definition: thread.h:46
This is the root of a MovingPart hierarchy.
Definition: partBundle.h:46
This represents one joint of the character's animation, containing an animating transform matrix.
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
SceneSetup * get_scene() const
Returns the SceneSetup object.
Definition: cullTraverser.I:35
bool update()
Updates all the parts in the bundle to reflect the data for the current frame (as set in each of the ...
Definition: partBundle.cxx:477
void clear_lod_animation()
Undoes the effect of a recent call to set_lod_animation().
Definition: character.cxx:343
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
void force_update()
Recalculates the character even if we think it doesn't need it.
Definition: character.cxx:453
This structure collects together the different combinations of transforms and blend amounts used by a...
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PartGroup * copy_subgraph() const
Allocates and returns a new copy of this node and of all of its children.
Definition: partGroup.cxx:75
A class to retrieve the individual data elements previously stored in a Datagram.
get_child
Returns the nth child of the group.
Definition: partGroup.h:72
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
Definition: namable.I:44
get_child
Returns the nth child node of this node.
Definition: pandaNode.h:124
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
virtual PartGroup * make_copy() const
Allocates and returns a new copy of the node.
Definition: partGroup.cxx:67
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
void merge_anim_preloads(const PartBundle *other)
Copies the contents of the other PartBundle's preload table into this one.
Definition: partBundle.cxx:91
void write_parts(std::ostream &out) const
Writes a list of the Character's joints and sliders, in their hierchical structure,...
Definition: character.cxx:394
virtual bool is_geom_node() const
A simple downcast check.
Definition: pandaNode.cxx:2068
void write_part_values(std::ostream &out) const
Writes a list of the Character's joints and sliders, along with each current position,...
Definition: character.cxx:407
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
static void register_with_read_factory()
Tells the BamReader how to create objects of type Character.
Definition: character.cxx:1099
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition: geomNode.cxx:584
virtual PandaNode * make_copy() const
The Character make_copy() function will make a new copy of the Character, with all of its joints copi...
Definition: character.cxx:107
void remove_all_geoms()
Removes all the geoms from the node at once.
Definition: geomNode.I:126
This is the base class for PartRoot and MovingPart.
Definition: partGroup.h:43