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