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  */
393 do_sync_p2b() {
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  */
404 do_sync_b2p() {
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  */
716 pick_dirty_flag() {
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  */
734 write_datagram(BamWriter *manager, Datagram &dg) {
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 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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
virtual PandaNode * make_copy() const
Returns a newly-allocated PandaNode that is a shallow copy of this one.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
set_mass
Sets the mass of a rigid body.
static void register_with_read_factory()
Tells the BamReader how to create objects of type BulletRigidBodyNode.
get_mass
Returns the total mass of a rigid body.
void do_sync_b2p()
Assumes the lock(bullet global lock) is held by the caller.
bool pick_dirty_flag()
Returns TRUE if the transform of the rigid body has changed at least once since the last call to this...
get_inv_mass
Returns the inverse mass of a rigid body.
set_inertia
Sets the inertia of a rigid body.
get_inertia
Returns the inertia of the rigid body.
void do_sync_p2b()
Assumes the lock(bullet global lock) is held by the caller.
A class to retrieve the individual data elements previously stored in a Datagram.
PN_stdfloat get_stdfloat()
Extracts either a 32-bit or a 64-bit floating-point number, according to Datagram::set_stdfloat_doubl...
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
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
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
Similar to MutexHolder, but for a light mutex.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:159
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 set_pos_quat(const LVecBase3 &pos, const LQuaternion &quat)
Sets the translation and rotation component of the transform, leaving scale untouched.
Definition: nodePath.cxx:1268
A basic node of the scene graph or data graph.
Definition: pandaNode.h:65
get_num_parents
Returns the number of parent nodes this node has.
Definition: pandaNode.h:118
Indicates a coordinate-system transform on vertices.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.