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  * @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  * @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 }
PartGroup::get_num_children
get_num_children
Returns the number of child nodes of the group.
Definition: partGroup.h:72
PandaNode::get_parent
get_parent
Returns the nth parent node of this node.
Definition: pandaNode.h:118
Geom
A container for geometry primitives.
Definition: geom.h:54
CharacterVertexSlider::get_char_slider
const CharacterSlider * get_char_slider() const
Returns the CharacterSlider object for which this object returns the slider value.
Definition: characterVertexSlider.I:19
CPT
CPT(TransformState) Character
This is used to support NodePath::calc_tight_bounds().
Definition: character.cxx:218
PandaNode::combine_with
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:319
Character::force_update
void force_update()
Recalculates the character even if we think it doesn't need it.
Definition: character.cxx:453
nodePath.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
SliderTable
Stores the total set of VertexSliders that the vertices in a particular GeomVertexData object might d...
Definition: sliderTable.h:37
PandaNode::is_geom_node
virtual bool is_geom_node() const
A simple downcast check.
Definition: pandaNode.cxx:2062
PartGroup
This is the base class for PartRoot and MovingPart.
Definition: partGroup.h:43
cullTraverser.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Geom::make_copy
virtual Geom * make_copy() const
Returns a newly-allocated Geom that is a shallow copy of this one.
Definition: geom.cxx:100
PartBundleNode
This is a node that contains a pointer to an PartBundle.
Definition: partBundleNode.h:35
DatagramIterator::get_uint16
uint16_t get_uint16()
Extracts an unsigned 16-bit integer.
Definition: datagramIterator.I:145
pvector< PT(PartGroup) >
Character::update_to_now
void update_to_now()
Advances the character's frame to the current time, and then calls update().
Definition: character.cxx:423
GeomVertexData
This defines the actual numeric vertex data stored in a Geom, in the structure defined by a particula...
Definition: geomVertexData.h:68
TransformBlend
This defines a single entry in a TransformBlendTable.
Definition: transformBlend.h:32
TransformBlend::get_num_transforms
get_num_transforms
Returns the number of transforms stored in the blend object.
Definition: transformBlend.h:63
Camera
A node that can be positioned around in the scene graph to represent a point of view for rendering a ...
Definition: camera.h:35
PartGroup::copy_subgraph
PartGroup * copy_subgraph() const
Allocates and returns a new copy of this node and of all of its children.
Definition: partGroup.cxx:75
JointVertexTransform::get_joint
const CharacterJoint * get_joint() const
Returns the joint for which this object returns the transform.
Definition: jointVertexTransform.I:18
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
pmap
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
CharacterJoint::add_net_transform
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...
Definition: characterJoint.cxx:196
TransformTable
Stores the total set of VertexTransforms that the vertices in a particular GeomVertexData object migh...
Definition: transformTable.h:38
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
Character::clear_lod_animation
void clear_lod_animation()
Undoes the effect of a recent call to set_lod_animation().
Definition: character.cxx:343
CharacterJoint::add_local_transform
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...
Definition: characterJoint.cxx:288
PartBundleHandle
This is a trivial class returned by PartBundleNode::get_bundle().
Definition: partBundleHandle.h:33
CullTraverser::get_scene
SceneSetup * get_scene() const
Returns the SceneSetup object.
Definition: cullTraverser.I:35
Camera::get_lod_center
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
GeomNode::set_geom
void set_geom(int n, Geom *geom)
Replaces the nth Geom of the node with a new pointer.
Definition: geomNode.cxx:635
Camera::get_cull_center
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
clockObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
ClockObject::get_global_clock
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
CullTraverser
This object performs a depth-first traversal of the scene graph, with optional view-frustum culling,...
Definition: cullTraverser.h:45
SceneSetup::get_camera_node
Camera * get_camera_node() const
Returns the camera used to render the scene.
Definition: sceneSetup.I:115
PandaNode::get_child_sort
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
BamReader::get_factory
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CharacterJoint
This represents one joint of the character's animation, containing an animating transform matrix.
Definition: characterJoint.h:32
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
PartGroup::is_character_joint
virtual bool is_character_joint() const
Returns true if this part is a CharacterJoint, false otherwise.
Definition: partGroup.cxx:58
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
GeomNode::get_num_geoms
get_num_geoms
Returns the number of geoms in the node.
Definition: geomNode.h:71
RenderState
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Definition: renderState.h:47
PT
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
PartBundle::set_update_delay
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
PStatTimer
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
Character::dupe_for_flatten
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
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
GeomNode
A node that holds Geom objects, renderable pieces of geometry.
Definition: geomNode.h:34
Datagram::add_uint16
void add_uint16(uint16_t value)
Adds an unsigned 16-bit integer to the datagram.
Definition: datagram.I:85
Character::write_parts
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
PartGroup::write_with_value
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
cullTraverserData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CharacterVertexSlider
This is a specialization on VertexSlider that returns the slider value associated with a particular C...
Definition: characterVertexSlider.h:26
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
CharacterSlider
This is a morph slider within the character.
Definition: characterSlider.h:28
Character::set_lod_animation
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
animControl.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
character.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PartBundle::write
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
TransformState
Indicates a coordinate-system transform on vertices.
Definition: transformState.h:54
PartBundle::update
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
Character::combine_with
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
Character::find_slider
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
PStatCollector
A lightweight class that represents a single element that may be timed and/or counted via stats.
Definition: pStatCollector.h:43
CullTraverserData
This collects together the pieces of data that are accumulated for each node while walking the scene ...
Definition: cullTraverserData.h:40
PandaNode::get_child
get_child
Returns the nth child node of this node.
Definition: pandaNode.h:124
Namable::has_name
bool has_name() const
Returns true if the Namable has a nonempty name set, false if the name is empty.
Definition: namable.I:44
Character::find_joint
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
VertexSlider
This is an abstract base class that retains some slider value, which is a linear value that typically...
Definition: vertexSlider.h:37
datagram.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Character::update
void update()
Recalculates the Character's joints and vertices for the current frame.
Definition: character.cxx:433
TransformBlend::get_transform
get_transform
Returns the nth transform stored in the blend object.
Definition: transformBlend.h:63
Character::complete_pointers
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
PandaNode::get_parents
get_parents
Returns an object that can be used to walk through the list of parents of the node,...
Definition: pandaNode.h:784
Character::make_copy
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
GeomVertexFormat
This class defines the physical layout of the vertex data stored within a Geom.
Definition: geomVertexFormat.h:55
Factory::register_factory
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
camera.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CharacterJointBundle
The collection of all the joints and sliders in the character.
Definition: characterJointBundle.h:28
ordered_vector::end
iterator_0 end()
Returns the iterator that marks the end of the ordered vector.
Definition: ordered_vector.I:50
PartBundleHandle::get_bundle
get_bundle
Returns the actual PartBundle embedded within the handle.
Definition: partBundleHandle.h:41
NodePath
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
ClockObject::get_frame_count
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
Definition: clockObject.h:94
config_char.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PartGroup::get_child
get_child
Returns the nth child of the group.
Definition: partGroup.h:72
ClockObject::get_frame_time
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
PandaNode::make_copy
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
Definition: pandaNode.cxx:481
PartGroup::find_child
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
BamReader::read_pointer
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
TransformBlend::set_transform
set_transform
Replaces the nth transform stored in the blend object.
Definition: transformBlend.h:70
GeomNode::get_geom_state
get_geom_state
Returns the RenderState associated with the nth geom of the node.
Definition: geomNode.h:75
Character::register_with_read_factory
static void register_with_read_factory()
Tells the BamReader how to create objects of type Character.
Definition: character.cxx:1099
PartBundle::merge_anim_preloads
void merge_anim_preloads(const PartBundle *other)
Copies the contents of the other PartBundle's preload table into this one.
Definition: partBundle.cxx:91
datagramIterator.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
geomNode.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PartBundle::force_update
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
JointVertexTransform
This is a specialization on VertexTransform that returns the transform necessary to move vertices as ...
Definition: jointVertexTransform.h:33
PartBundleNode::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &me)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: partBundleNode.cxx:146
characterJoint.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode::get_num_children
get_num_children
Returns the number of child nodes this node has.
Definition: pandaNode.h:124
bamWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PandaNode
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
GeomNode::add_geom
void add_geom(Geom *geom, const RenderState *state=RenderState::make_empty())
Adds a new Geom to the node.
Definition: geomNode.cxx:584
Character::write_datagram
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
TypedObject::is_exact_type
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
Definition: typedObject.I:38
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
TransformBlendTable
This structure collects together the different combinations of transforms and blend amounts used by a...
Definition: transformBlendTable.h:45
ordered_vector::begin
iterator_0 begin()
Returns the iterator that marks the first element in the ordered vector.
Definition: ordered_vector.I:41
GeomNode::remove_all_geoms
void remove_all_geoms()
Removes all the geoms from the node at once.
Definition: geomNode.I:126
parse_params
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
VertexTransform
This is an abstract base class that holds a pointer to some transform, computed in some arbitrary way...
Definition: vertexTransform.h:35
PartBundle
This is the root of a MovingPart hierarchy.
Definition: partBundle.h:46
Character::write_part_values
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
NodePath::any_path
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
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
Character::cull_callback
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
NodePath::is_empty
bool is_empty() const
Returns true if the NodePath contains no nodes.
Definition: nodePath.I:188
Character
An animated character, with skeleton-morph animation and either soft- skinned or hard-skinned vertice...
Definition: character.h:38
PartBundleNode::complete_pointers
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().
Definition: partBundleNode.cxx:161
PartGroup::make_copy
virtual PartGroup * make_copy() const
Allocates and returns a new copy of the node.
Definition: partGroup.cxx:67