Panda3D
bulletRigidBodyNode.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 bulletRigidBodyNode.cxx
10  * @author enn0x
11  * @date 2010-11-19
12  */
13 
14 #include "bulletRigidBodyNode.h"
15 
16 #include "config_bullet.h"
17 
18 #include "bulletShape.h"
19 #include "bulletWorld.h"
20 
21 TypeHandle BulletRigidBodyNode::_type_handle;
22 
23 /**
24  *
25  */
26 BulletRigidBodyNode::
27 BulletRigidBodyNode(const char *name) : BulletBodyNode(name) {
28  // Mass properties
29  btScalar mass(0.0);
30  btVector3 inertia(0, 0, 0);
31 
32  // construction info
33  btRigidBody::btRigidBodyConstructionInfo ci(mass, &_motion, _shape, inertia);
34 
35  // Additional damping
36  if (bullet_additional_damping) {
37  ci.m_additionalDamping = true;
38  ci.m_additionalDampingFactor = bullet_additional_damping_linear_factor;
39  ci.m_additionalLinearDampingThresholdSqr = bullet_additional_damping_linear_threshold;
40  ci.m_additionalAngularDampingFactor = bullet_additional_damping_angular_factor;
41  ci.m_additionalAngularDampingThresholdSqr = bullet_additional_damping_angular_threshold;
42  }
43 
44  // Rigid body
45  _rigid = new btRigidBody(ci);
46  _rigid->setUserPointer(this);
47 }
48 
49 /**
50  * Do not call the copy constructor directly; instead, use make_copy() or
51  * copy_subgraph() to make a copy of a node.
52  */
53 BulletRigidBodyNode::
54 BulletRigidBodyNode(const BulletRigidBodyNode &copy) :
55  BulletBodyNode(copy)
56 {
57  LightMutexHolder holder(BulletWorld::get_global_lock());
58 
59  _motion = copy._motion;
60  _rigid = new btRigidBody(*copy._rigid);
61  _rigid->setUserPointer(this);
62  _rigid->setCollisionShape(_shape);
63  _rigid->setMotionState(&_motion);
64 }
65 
66 /**
67  * Returns a newly-allocated PandaNode that is a shallow copy of this one. It
68  * will be a different pointer, but its internal data may or may not be shared
69  * with that of the original PandaNode. No children will be copied.
70  */
72 make_copy() const {
73 
74  return new BulletRigidBodyNode(*this);
75 }
76 
77 /**
78  *
79  */
80 void BulletRigidBodyNode::
81 output(std::ostream &out) const {
82  LightMutexHolder holder(BulletWorld::get_global_lock());
83 
84  BulletBodyNode::do_output(out);
85 
86  out << " mass=" << do_get_mass();
87 }
88 
89 /**
90  *
91  */
92 btCollisionObject *BulletRigidBodyNode::
93 get_object() const {
94 
95  return _rigid;
96 }
97 
98 /**
99  * Hook which should be called whenever the total shape of a body changed.
100  * Used for example to update the mass properties (inertia) of a rigid body.
101  * The default implementation does nothing.
102  */
103 void BulletRigidBodyNode::
104 do_shape_changed() {
105 
106  do_set_mass(do_get_mass());
107  do_transform_changed();
108 }
109 
110 /**
111  * Sets the mass of a rigid body. This also modifies the inertia, which is
112  * automatically computed from the shape of the body. Setting a value of zero
113  * for mass will make the body static. A value of zero can be considered an
114  * infinite mass.
115  * Assumes the lock(bullet global lock) is held by the caller
116  */
117 void BulletRigidBodyNode::
118 do_set_mass(PN_stdfloat mass) {
119 
120  btScalar bt_mass = mass;
121  btVector3 bt_inertia(0.0, 0.0, 0.0);
122 
123  if (bt_mass > 0.0 && !_shapes.empty()) {
124  _rigid->getCollisionShape()->calculateLocalInertia(bt_mass, bt_inertia);
125  }
126 
127  _rigid->setMassProps(bt_mass, bt_inertia);
128  _rigid->updateInertiaTensor();
129 }
130 
131 /**
132  * Sets the mass of a rigid body. This also modifies the inertia, which is
133  * automatically computed from the shape of the body. Setting a value of zero
134  * for mass will make the body static. A value of zero can be considered an
135  * infinite mass.
136  */
138 set_mass(PN_stdfloat mass) {
139  LightMutexHolder holder(BulletWorld::get_global_lock());
140 
141  do_set_mass(mass);
142 }
143 
144 /**
145  * Returns the total mass of a rigid body. A value of zero means that the
146  * body is staic, i.e. has an infinite mass.
147  * Assumes the lock(bullet global lock) is held by the caller
148  */
149 PN_stdfloat BulletRigidBodyNode::
150 do_get_mass() const {
151 
152  btScalar inv_mass = _rigid->getInvMass();
153  btScalar mass = (inv_mass == btScalar(0.0)) ? btScalar(0.0) : btScalar(1.0) / inv_mass;
154 
155  return mass;
156 }
157 
158 /**
159  * Returns the total mass of a rigid body. A value of zero means that the
160  * body is staic, i.e. has an infinite mass.
161  */
162 PN_stdfloat BulletRigidBodyNode::
163 get_mass() const {
164  LightMutexHolder holder(BulletWorld::get_global_lock());
165 
166  return do_get_mass();
167 }
168 
169 
170 /**
171  * Returns the inverse mass of a rigid body.
172  */
173 PN_stdfloat BulletRigidBodyNode::
174 get_inv_mass() const {
175  LightMutexHolder holder(BulletWorld::get_global_lock());
176 
177  return (PN_stdfloat)_rigid->getInvMass();
178 }
179 
180 /**
181  * Sets the inertia of a rigid body. Inertia is given as a three-component
182  * vector. A component value of zero means infinite inertia along this
183  * direction. Setting the intertia will override the value which is
184  * automatically calculated from the rigid bodies shape. However, it is
185  * possible that automatic calculation of intertia is trigger after calling
186  * this method, and thus overwriting the explicitly set value again. This
187  * happens when: (a) the mass is set after the inertia. (b) a shape is added
188  * or removed from the body. (c) the scale of the body changed.
189  */
191 set_inertia(const LVecBase3 &inertia) {
192  LightMutexHolder holder(BulletWorld::get_global_lock());
193 
194  btVector3 inv_inertia(
195  inertia.get_x() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_x()),
196  inertia.get_y() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_y()),
197  inertia.get_z() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_z())
198  );
199 
200  _rigid->setInvInertiaDiagLocal(inv_inertia);
201  _rigid->updateInertiaTensor();
202 }
203 
204 /**
205  * Returns the inertia of the rigid body. Inertia is given as a three
206  * component vector. A component value of zero means infinite inertia along
207  * this direction.
208  */
209 LVector3 BulletRigidBodyNode::
210 get_inertia() const {
211  LightMutexHolder holder(BulletWorld::get_global_lock());
212 
213  btVector3 inv_inertia = _rigid->getInvInertiaDiagLocal();
214  LVector3 inertia(
215  inv_inertia.x() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.x(),
216  inv_inertia.y() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.y(),
217  inv_inertia.z() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.z()
218  );
219 
220  return inertia;
221 }
222 
223 /**
224  *
225  */
226 LVector3 BulletRigidBodyNode::
227 get_inv_inertia_diag_local() const {
228  LightMutexHolder holder(BulletWorld::get_global_lock());
229 
230  return btVector3_to_LVector3(_rigid->getInvInertiaDiagLocal());
231 }
232 
233 /**
234  *
235  */
236 LMatrix3 BulletRigidBodyNode::
237 get_inv_inertia_tensor_world() const {
238  LightMutexHolder holder(BulletWorld::get_global_lock());
239 
240  return btMatrix3x3_to_LMatrix3(_rigid->getInvInertiaTensorWorld());
241 }
242 
243 /**
244  *
245  */
246 void BulletRigidBodyNode::
247 apply_force(const LVector3 &force, const LPoint3 &pos) {
248  LightMutexHolder holder(BulletWorld::get_global_lock());
249 
250  nassertv_always(!force.is_nan());
251  nassertv_always(!pos.is_nan());
252 
253  _rigid->applyForce(LVecBase3_to_btVector3(force),
254  LVecBase3_to_btVector3(pos));
255 }
256 
257 /**
258  *
259  */
260 void BulletRigidBodyNode::
261 apply_central_force(const LVector3 &force) {
262  LightMutexHolder holder(BulletWorld::get_global_lock());
263 
264  nassertv_always(!force.is_nan());
265 
266  _rigid->applyCentralForce(LVecBase3_to_btVector3(force));
267 }
268 
269 /**
270  *
271  */
272 void BulletRigidBodyNode::
273 apply_torque(const LVector3 &torque) {
274  LightMutexHolder holder(BulletWorld::get_global_lock());
275 
276  nassertv_always(!torque.is_nan());
277 
278  _rigid->applyTorque(LVecBase3_to_btVector3(torque));
279 }
280 
281 /**
282  *
283  */
284 void BulletRigidBodyNode::
285 apply_torque_impulse(const LVector3 &torque) {
286  LightMutexHolder holder(BulletWorld::get_global_lock());
287 
288  nassertv_always(!torque.is_nan());
289 
290  _rigid->applyTorqueImpulse(LVecBase3_to_btVector3(torque));
291 }
292 
293 /**
294  *
295  */
296 void BulletRigidBodyNode::
297 apply_impulse(const LVector3 &impulse, const LPoint3 &pos) {
298  LightMutexHolder holder(BulletWorld::get_global_lock());
299 
300  nassertv_always(!impulse.is_nan());
301  nassertv_always(!pos.is_nan());
302 
303  _rigid->applyImpulse(LVecBase3_to_btVector3(impulse),
304  LVecBase3_to_btVector3(pos));
305 }
306 
307 /**
308  *
309  */
310 void BulletRigidBodyNode::
311 apply_central_impulse(const LVector3 &impulse) {
312  LightMutexHolder holder(BulletWorld::get_global_lock());
313 
314  nassertv_always(!impulse.is_nan());
315 
316  _rigid->applyCentralImpulse(LVecBase3_to_btVector3(impulse));
317 }
318 
319 /**
320  * Assumes the lock(bullet global lock) is held by the caller
321  */
322 void BulletRigidBodyNode::
323 do_transform_changed() {
324 
325  if (_motion.sync_disabled()) return;
326 
327  NodePath np = NodePath::any_path((PandaNode *)this);
328  CPT(TransformState) ts = np.get_net_transform();
329 
330  // For kinematic bodies Bullet will query the transform via
331  // Motionstate::getWorldTransform. Therefor we need to store the new
332  // transform within the motion state. For dynamic bodies we need to store
333  // the net scale within the motion state, since Bullet might update the
334  // transform via MotionState::setWorldTransform.
335  _motion.set_net_transform(ts);
336 
337  // For dynamic or static bodies we directly apply the new transform.
338  if (!(get_object()->isKinematicObject())) {
339  btTransform trans = TransformState_to_btTrans(ts);
340  _rigid->setCenterOfMassTransform(trans);
341  }
342 
343  // Rescale all shapes, but only if the new transform state has a scale, and
344  // this scale differes from the current scale.
345  if (ts->has_scale()) {
346  btVector3 new_scale = LVecBase3_to_btVector3(ts->get_scale());
347  btVector3 current_scale = _shape->getLocalScaling();
348  btVector3 current_scale_inv(1.0/current_scale.x(), 1.0/current_scale.y(), 1.0/current_scale.z());
349 
350  if (new_scale != current_scale) {
351  _shape->setLocalScaling(current_scale_inv);
352  _shape->setLocalScaling(new_scale);
353  }
354  }
355 
356  // Activate the body if it has been sleeping
357  if (!_rigid->isActive()) {
358  _rigid->activate(true);
359  }
360 }
361 
362 /**
363  *
364  */
365 void BulletRigidBodyNode::
366 parents_changed() {
367 
368  if (_motion.sync_disabled()) return;
369 
370  if (get_num_parents() > 0) {
371  LightMutexHolder holder(BulletWorld::get_global_lock());
372  do_transform_changed();
373  }
374 }
375 
376 /**
377  *
378  */
379 void BulletRigidBodyNode::
380 transform_changed() {
381 
382  if (_motion.sync_disabled()) return;
383 
384  LightMutexHolder holder(BulletWorld::get_global_lock());
385 
386  do_transform_changed();
387 }
388 
389 /**
390  * Assumes the lock(bullet global lock) is held by the caller
391  */
394 
395  if (get_object()->isKinematicObject()) {
396  do_transform_changed();
397  }
398 }
399 
400 /**
401  * Assumes the lock(bullet global lock) is held by the caller
402  */
405 
406  _motion.sync_b2p((PandaNode *)this);
407 }
408 
409 /**
410  *
411  */
412 LVector3 BulletRigidBodyNode::
413 get_linear_velocity() const {
414  LightMutexHolder holder(BulletWorld::get_global_lock());
415 
416  return btVector3_to_LVector3(_rigid->getLinearVelocity());
417 }
418 
419 /**
420  *
421  */
422 LVector3 BulletRigidBodyNode::
423 get_angular_velocity() const {
424  LightMutexHolder holder(BulletWorld::get_global_lock());
425 
426  return btVector3_to_LVector3(_rigid->getAngularVelocity());
427 }
428 
429 /**
430  *
431  */
432 void BulletRigidBodyNode::
433 set_linear_velocity(const LVector3 &velocity) {
434  LightMutexHolder holder(BulletWorld::get_global_lock());
435 
436  nassertv_always(!velocity.is_nan());
437 
438  _rigid->setLinearVelocity(LVecBase3_to_btVector3(velocity));
439 }
440 
441 /**
442  *
443  */
444 void BulletRigidBodyNode::
445 set_angular_velocity(const LVector3 &velocity) {
446  LightMutexHolder holder(BulletWorld::get_global_lock());
447 
448  nassertv_always(!velocity.is_nan());
449 
450  _rigid->setAngularVelocity(LVecBase3_to_btVector3(velocity));
451 }
452 
453 /**
454  *
455  */
456 void BulletRigidBodyNode::
457 set_linear_damping(PN_stdfloat value) {
458  LightMutexHolder holder(BulletWorld::get_global_lock());
459 
460  _rigid->setDamping(value, _rigid->getAngularDamping());
461 }
462 
463 /**
464  *
465  */
466 void BulletRigidBodyNode::
467 set_angular_damping(PN_stdfloat value) {
468  LightMutexHolder holder(BulletWorld::get_global_lock());
469 
470  _rigid->setDamping(_rigid->getLinearDamping(), value);
471 }
472 
473 /**
474  *
475  */
476 PN_stdfloat BulletRigidBodyNode::
477 get_linear_damping() const {
478  LightMutexHolder holder(BulletWorld::get_global_lock());
479 
480  return (PN_stdfloat)_rigid->getLinearDamping();
481 }
482 
483 /**
484  *
485  */
486 PN_stdfloat BulletRigidBodyNode::
487 get_angular_damping() const {
488  LightMutexHolder holder(BulletWorld::get_global_lock());
489 
490  return (PN_stdfloat)_rigid->getAngularDamping();
491 }
492 
493 /**
494  *
495  */
496 void BulletRigidBodyNode::
497 clear_forces() {
498  LightMutexHolder holder(BulletWorld::get_global_lock());
499 
500  _rigid->clearForces();
501 }
502 
503 /**
504  *
505  */
506 PN_stdfloat BulletRigidBodyNode::
507 get_linear_sleep_threshold() const {
508  LightMutexHolder holder(BulletWorld::get_global_lock());
509 
510  return _rigid->getLinearSleepingThreshold();
511 }
512 
513 /**
514  *
515  */
516 PN_stdfloat BulletRigidBodyNode::
517 get_angular_sleep_threshold() const {
518  LightMutexHolder holder(BulletWorld::get_global_lock());
519 
520  return _rigid->getAngularSleepingThreshold();
521 }
522 
523 /**
524  *
525  */
526 void BulletRigidBodyNode::
527 set_linear_sleep_threshold(PN_stdfloat threshold) {
528  LightMutexHolder holder(BulletWorld::get_global_lock());
529 
530  _rigid->setSleepingThresholds(threshold, _rigid->getAngularSleepingThreshold());
531 }
532 
533 /**
534  *
535  */
536 void BulletRigidBodyNode::
537 set_angular_sleep_threshold(PN_stdfloat threshold) {
538  LightMutexHolder holder(BulletWorld::get_global_lock());
539 
540  _rigid->setSleepingThresholds(_rigid->getLinearSleepingThreshold(), threshold);
541 }
542 
543 /**
544  *
545  */
546 void BulletRigidBodyNode::
547 set_gravity(const LVector3 &gravity) {
548  LightMutexHolder holder(BulletWorld::get_global_lock());
549 
550  nassertv_always(!gravity.is_nan());
551 
552  _rigid->setGravity(LVecBase3_to_btVector3(gravity));
553 }
554 
555 /**
556  *
557  */
558 LVector3 BulletRigidBodyNode::
559 get_gravity() const {
560  LightMutexHolder holder(BulletWorld::get_global_lock());
561 
562  return btVector3_to_LVector3(_rigid->getGravity());
563 }
564 
565 /**
566  *
567  */
568 LVector3 BulletRigidBodyNode::
569 get_linear_factor() const {
570  LightMutexHolder holder(BulletWorld::get_global_lock());
571 
572  return btVector3_to_LVector3(_rigid->getLinearFactor());
573 }
574 
575 /**
576  *
577  */
578 LVector3 BulletRigidBodyNode::
579 get_angular_factor() const {
580  LightMutexHolder holder(BulletWorld::get_global_lock());
581 
582  return btVector3_to_LVector3(_rigid->getAngularFactor());
583 }
584 
585 /**
586  *
587  */
588 void BulletRigidBodyNode::
589 set_linear_factor(const LVector3 &factor) {
590  LightMutexHolder holder(BulletWorld::get_global_lock());
591 
592  _rigid->setLinearFactor(LVecBase3_to_btVector3(factor));
593 }
594 
595 /**
596  *
597  */
598 void BulletRigidBodyNode::
599 set_angular_factor(const LVector3 &factor) {
600  LightMutexHolder holder(BulletWorld::get_global_lock());
601 
602  _rigid->setAngularFactor(LVecBase3_to_btVector3(factor));
603 }
604 
605 /**
606  *
607  */
608 LVector3 BulletRigidBodyNode::
609 get_total_force() const {
610  LightMutexHolder holder(BulletWorld::get_global_lock());
611 
612  return btVector3_to_LVector3(_rigid->getTotalForce());
613 }
614 
615 /**
616  *
617  */
618 LVector3 BulletRigidBodyNode::
619 get_total_torque() const {
620  LightMutexHolder holder(BulletWorld::get_global_lock());
621 
622  return btVector3_to_LVector3(_rigid->getTotalTorque());
623 }
624 
625 /**
626  *
627  */
628 BulletRigidBodyNode::MotionState::
629 MotionState() {
630 
631  _trans.setIdentity();
632  _disabled = false;
633  _dirty = false;
634  _was_dirty = false;
635 }
636 
637 /**
638  *
639  */
640 void BulletRigidBodyNode::MotionState::
641 getWorldTransform(btTransform &trans) const {
642 
643  trans = _trans;
644 }
645 
646 /**
647  *
648  */
649 void BulletRigidBodyNode::MotionState::
650 setWorldTransform(const btTransform &trans) {
651 
652  _trans = trans;
653  _dirty = true;
654  _was_dirty = true;
655 }
656 
657 /**
658  *
659  */
660 void BulletRigidBodyNode::MotionState::
661 sync_b2p(PandaNode *node) {
662 
663  if (!_dirty) return;
664 
665  NodePath np = NodePath::any_path(node);
666  LPoint3 p = btVector3_to_LPoint3(_trans.getOrigin());
667  LQuaternion q = btQuat_to_LQuaternion(_trans.getRotation());
668 
669  _disabled = true;
670  np.set_pos_quat(NodePath(), p, q);
671  _disabled = false;
672  _dirty = false;
673 }
674 
675 /**
676  * This method stores the global transform within the Motionstate. It is
677  * called from BulletRigidBodyNode::transform_changed(). For kinematic bodies
678  * the global transform is required since Bullet queries the body transform
679  * via MotionState::getGlobalStranform(). For dynamic bodies the global scale
680  * is required, since Bullet will overwrite the member _trans by calling
681  * MotionState::setGlobalTransform.
682  */
683 void BulletRigidBodyNode::MotionState::
684 set_net_transform(const TransformState *ts) {
685 
686  nassertv(ts);
687 
688  _trans = TransformState_to_btTrans(ts);
689 }
690 
691 /**
692  *
693  */
694 bool BulletRigidBodyNode::MotionState::
695 sync_disabled() const {
696 
697  return _disabled;
698 }
699 
700 /**
701  *
702  */
703 bool BulletRigidBodyNode::MotionState::
704 pick_dirty_flag() {
705 
706  bool rc = _was_dirty;
707  _was_dirty = false;
708  return rc;
709 }
710 
711 /**
712  * Returns TRUE if the transform of the rigid body has changed at least once
713  * since the last call to this method.
714  */
717 
718  return _motion.pick_dirty_flag();
719 }
720 
721 /**
722  * Tells the BamReader how to create objects of type BulletRigidBodyNode.
723  */
726  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
727 }
728 
729 /**
730  * Writes the contents of this object to the datagram for shipping out to a
731  * Bam file.
732  */
735  BulletBodyNode::write_datagram(manager, dg);
736 
737  dg.add_stdfloat(get_mass());
738  dg.add_stdfloat(get_linear_damping());
739  dg.add_stdfloat(get_angular_damping());
740  dg.add_stdfloat(get_linear_sleep_threshold());
741  dg.add_stdfloat(get_angular_sleep_threshold());
742  get_gravity().write_datagram(dg);
743  get_linear_factor().write_datagram(dg);
744  get_angular_factor().write_datagram(dg);
745  // dynamic state (?)
746  get_linear_velocity().write_datagram(dg);
747  get_angular_velocity().write_datagram(dg);
748 }
749 
750 /**
751  * This function is called by the BamReader's factory when a new object of
752  * this type is encountered in the Bam file. It should create the rigid body
753  * and extract its information from the file.
754  */
755 TypedWritable *BulletRigidBodyNode::
756 make_from_bam(const FactoryParams &params) {
758  DatagramIterator scan;
759  BamReader *manager;
760 
761  parse_params(params, scan, manager);
762  param->fillin(scan, manager);
763 
764  return param;
765 }
766 
767 /**
768  * This internal function is called by make_from_bam to read in all of the
769  * relevant data from the BamFile for the new BulletRigidBodyNode.
770  */
771 void BulletRigidBodyNode::
772 fillin(DatagramIterator &scan, BamReader *manager) {
773  BulletBodyNode::fillin(scan, manager);
774 
775  set_mass(scan.get_stdfloat());
776  set_linear_damping(scan.get_stdfloat());
777  set_angular_damping(scan.get_stdfloat());
778  set_linear_sleep_threshold(scan.get_stdfloat());
779  set_angular_sleep_threshold(scan.get_stdfloat());
780 
781  LVector3 gravity, linear_factor, angular_factor;
782  gravity.read_datagram(scan);
783  linear_factor.read_datagram(scan);
784  angular_factor.read_datagram(scan);
785 
786  set_gravity(gravity);
787  set_linear_factor(linear_factor);
788  set_angular_factor(angular_factor);
789 }
void do_sync_b2p()
Assumes the lock(bullet global lock) is held by the caller.
A basic node of the scene graph or data graph.
Definition: pandaNode.h:64
get_mass
Returns the total mass of a rigid body.
Indicates a coordinate-system transform on vertices.
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
get_num_parents
Returns the number of parent nodes this node has.
Definition: pandaNode.h:118
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
void do_sync_p2b()
Assumes the lock(bullet global lock) is held by the caller.
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
void set_pos_quat(const LVecBase3 &pos, const LQuaternion &quat)
Sets the translation and rotation component of the transform, leaving scale untouched.
Definition: nodePath.cxx:1201
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
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
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
Definition: datagram.I:133
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Similar to MutexHolder, but for a light mutex.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
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
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
set_inertia
Sets the inertia of a rigid body.
A class to retrieve the individual data elements previously stored in a Datagram.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
set_mass
Sets the mass of a rigid body.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
bool pick_dirty_flag()
Returns TRUE if the transform of the rigid body has changed at least once since the last call to this...
static void register_with_read_factory()
Tells the BamReader how to create objects of type BulletRigidBodyNode.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.