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) {
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 transform_changed() {
367 
368  if (_motion.sync_disabled()) return;
369 
370  LightMutexHolder holder(BulletWorld::get_global_lock());
371 
372  do_transform_changed();
373 }
374 
375 /**
376  * Assumes the lock(bullet global lock) is held by the caller
377  */
380 
381  if (get_object()->isKinematicObject()) {
382  do_transform_changed();
383  }
384 }
385 
386 /**
387  * Assumes the lock(bullet global lock) is held by the caller
388  */
391 
392  _motion.sync_b2p((PandaNode *)this);
393 }
394 
395 /**
396  *
397  */
398 LVector3 BulletRigidBodyNode::
399 get_linear_velocity() const {
400  LightMutexHolder holder(BulletWorld::get_global_lock());
401 
402  return btVector3_to_LVector3(_rigid->getLinearVelocity());
403 }
404 
405 /**
406  *
407  */
408 LVector3 BulletRigidBodyNode::
409 get_angular_velocity() const {
410  LightMutexHolder holder(BulletWorld::get_global_lock());
411 
412  return btVector3_to_LVector3(_rigid->getAngularVelocity());
413 }
414 
415 /**
416  *
417  */
418 void BulletRigidBodyNode::
419 set_linear_velocity(const LVector3 &velocity) {
420  LightMutexHolder holder(BulletWorld::get_global_lock());
421 
422  nassertv_always(!velocity.is_nan());
423 
424  _rigid->setLinearVelocity(LVecBase3_to_btVector3(velocity));
425 }
426 
427 /**
428  *
429  */
430 void BulletRigidBodyNode::
431 set_angular_velocity(const LVector3 &velocity) {
432  LightMutexHolder holder(BulletWorld::get_global_lock());
433 
434  nassertv_always(!velocity.is_nan());
435 
436  _rigid->setAngularVelocity(LVecBase3_to_btVector3(velocity));
437 }
438 
439 /**
440  *
441  */
442 void BulletRigidBodyNode::
443 set_linear_damping(PN_stdfloat value) {
444  LightMutexHolder holder(BulletWorld::get_global_lock());
445 
446  _rigid->setDamping(value, _rigid->getAngularDamping());
447 }
448 
449 /**
450  *
451  */
452 void BulletRigidBodyNode::
453 set_angular_damping(PN_stdfloat value) {
454  LightMutexHolder holder(BulletWorld::get_global_lock());
455 
456  _rigid->setDamping(_rigid->getLinearDamping(), value);
457 }
458 
459 /**
460  *
461  */
462 PN_stdfloat BulletRigidBodyNode::
463 get_linear_damping() const {
464  LightMutexHolder holder(BulletWorld::get_global_lock());
465 
466  return (PN_stdfloat)_rigid->getLinearDamping();
467 }
468 
469 /**
470  *
471  */
472 PN_stdfloat BulletRigidBodyNode::
473 get_angular_damping() const {
474  LightMutexHolder holder(BulletWorld::get_global_lock());
475 
476  return (PN_stdfloat)_rigid->getAngularDamping();
477 }
478 
479 /**
480  *
481  */
482 void BulletRigidBodyNode::
483 clear_forces() {
484  LightMutexHolder holder(BulletWorld::get_global_lock());
485 
486  _rigid->clearForces();
487 }
488 
489 /**
490  *
491  */
492 PN_stdfloat BulletRigidBodyNode::
493 get_linear_sleep_threshold() const {
494  LightMutexHolder holder(BulletWorld::get_global_lock());
495 
496  return _rigid->getLinearSleepingThreshold();
497 }
498 
499 /**
500  *
501  */
502 PN_stdfloat BulletRigidBodyNode::
503 get_angular_sleep_threshold() const {
504  LightMutexHolder holder(BulletWorld::get_global_lock());
505 
506  return _rigid->getAngularSleepingThreshold();
507 }
508 
509 /**
510  *
511  */
512 void BulletRigidBodyNode::
513 set_linear_sleep_threshold(PN_stdfloat threshold) {
514  LightMutexHolder holder(BulletWorld::get_global_lock());
515 
516  _rigid->setSleepingThresholds(threshold, _rigid->getAngularSleepingThreshold());
517 }
518 
519 /**
520  *
521  */
522 void BulletRigidBodyNode::
523 set_angular_sleep_threshold(PN_stdfloat threshold) {
524  LightMutexHolder holder(BulletWorld::get_global_lock());
525 
526  _rigid->setSleepingThresholds(_rigid->getLinearSleepingThreshold(), threshold);
527 }
528 
529 /**
530  *
531  */
532 void BulletRigidBodyNode::
533 set_gravity(const LVector3 &gravity) {
534  LightMutexHolder holder(BulletWorld::get_global_lock());
535 
536  nassertv_always(!gravity.is_nan());
537 
538  _rigid->setGravity(LVecBase3_to_btVector3(gravity));
539 }
540 
541 /**
542  *
543  */
544 LVector3 BulletRigidBodyNode::
545 get_gravity() const {
546  LightMutexHolder holder(BulletWorld::get_global_lock());
547 
548  return btVector3_to_LVector3(_rigid->getGravity());
549 }
550 
551 /**
552  *
553  */
554 LVector3 BulletRigidBodyNode::
555 get_linear_factor() const {
556  LightMutexHolder holder(BulletWorld::get_global_lock());
557 
558  return btVector3_to_LVector3(_rigid->getLinearFactor());
559 }
560 
561 /**
562  *
563  */
564 LVector3 BulletRigidBodyNode::
565 get_angular_factor() const {
566  LightMutexHolder holder(BulletWorld::get_global_lock());
567 
568  return btVector3_to_LVector3(_rigid->getAngularFactor());
569 }
570 
571 /**
572  *
573  */
574 void BulletRigidBodyNode::
575 set_linear_factor(const LVector3 &factor) {
576  LightMutexHolder holder(BulletWorld::get_global_lock());
577 
578  _rigid->setLinearFactor(LVecBase3_to_btVector3(factor));
579 }
580 
581 /**
582  *
583  */
584 void BulletRigidBodyNode::
585 set_angular_factor(const LVector3 &factor) {
586  LightMutexHolder holder(BulletWorld::get_global_lock());
587 
588  _rigid->setAngularFactor(LVecBase3_to_btVector3(factor));
589 }
590 
591 /**
592  *
593  */
594 LVector3 BulletRigidBodyNode::
595 get_total_force() const {
596  LightMutexHolder holder(BulletWorld::get_global_lock());
597 
598  return btVector3_to_LVector3(_rigid->getTotalForce());
599 }
600 
601 /**
602  *
603  */
604 LVector3 BulletRigidBodyNode::
605 get_total_torque() const {
606  LightMutexHolder holder(BulletWorld::get_global_lock());
607 
608  return btVector3_to_LVector3(_rigid->getTotalTorque());
609 }
610 
611 /**
612  *
613  */
614 BulletRigidBodyNode::MotionState::
615 MotionState() {
616 
617  _trans.setIdentity();
618  _disabled = false;
619  _dirty = false;
620  _was_dirty = false;
621 }
622 
623 /**
624  *
625  */
626 void BulletRigidBodyNode::MotionState::
627 getWorldTransform(btTransform &trans) const {
628 
629  trans = _trans;
630 }
631 
632 /**
633  *
634  */
635 void BulletRigidBodyNode::MotionState::
636 setWorldTransform(const btTransform &trans) {
637 
638  _trans = trans;
639  _dirty = true;
640  _was_dirty = true;
641 }
642 
643 /**
644  *
645  */
646 void BulletRigidBodyNode::MotionState::
647 sync_b2p(PandaNode *node) {
648 
649  if (!_dirty) return;
650 
651  NodePath np = NodePath::any_path(node);
652  LPoint3 p = btVector3_to_LPoint3(_trans.getOrigin());
653  LQuaternion q = btQuat_to_LQuaternion(_trans.getRotation());
654 
655  _disabled = true;
656  np.set_pos_quat(NodePath(), p, q);
657  _disabled = false;
658  _dirty = false;
659 }
660 
661 /**
662  * This method stores the global transform within the Motionstate. It is
663  * called from BulletRigidBodyNode::transform_changed(). For kinematic bodies
664  * the global transform is required since Bullet queries the body transform
665  * via MotionState::getGlobalStranform(). For dynamic bodies the global scale
666  * is required, since Bullet will overwrite the member _trans by calling
667  * MotionState::setGlobalTransform.
668  */
669 void BulletRigidBodyNode::MotionState::
670 set_net_transform(const TransformState *ts) {
671 
672  nassertv(ts);
673 
674  _trans = TransformState_to_btTrans(ts);
675 }
676 
677 /**
678  *
679  */
680 bool BulletRigidBodyNode::MotionState::
681 sync_disabled() const {
682 
683  return _disabled;
684 }
685 
686 /**
687  *
688  */
689 bool BulletRigidBodyNode::MotionState::
690 pick_dirty_flag() {
691 
692  bool rc = _was_dirty;
693  _was_dirty = false;
694  return rc;
695 }
696 
697 /**
698  * Returns TRUE if the transform of the rigid body has changed at least once
699  * since the last call to this method.
700  */
703 
704  return _motion.pick_dirty_flag();
705 }
706 
707 /**
708  * Tells the BamReader how to create objects of type BulletRigidBodyNode.
709  */
712  BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
713 }
714 
715 /**
716  * Writes the contents of this object to the datagram for shipping out to a
717  * Bam file.
718  */
721  BulletBodyNode::write_datagram(manager, dg);
722 
723  dg.add_stdfloat(get_mass());
724  dg.add_stdfloat(get_linear_damping());
725  dg.add_stdfloat(get_angular_damping());
726  dg.add_stdfloat(get_linear_sleep_threshold());
727  dg.add_stdfloat(get_angular_sleep_threshold());
728  get_gravity().write_datagram(dg);
729  get_linear_factor().write_datagram(dg);
730  get_angular_factor().write_datagram(dg);
731  // dynamic state (?)
732  get_linear_velocity().write_datagram(dg);
733  get_angular_velocity().write_datagram(dg);
734 }
735 
736 /**
737  * This function is called by the BamReader's factory when a new object of
738  * this type is encountered in the Bam file. It should create the rigid body
739  * and extract its information from the file.
740  */
741 TypedWritable *BulletRigidBodyNode::
742 make_from_bam(const FactoryParams &params) {
744  DatagramIterator scan;
745  BamReader *manager;
746 
747  parse_params(params, scan, manager);
748  param->fillin(scan, manager);
749 
750  return param;
751 }
752 
753 /**
754  * This internal function is called by make_from_bam to read in all of the
755  * relevant data from the BamFile for the new BulletRigidBodyNode.
756  */
757 void BulletRigidBodyNode::
758 fillin(DatagramIterator &scan, BamReader *manager) {
759  BulletBodyNode::fillin(scan, manager);
760 
761  set_mass(scan.get_stdfloat());
762  set_linear_damping(scan.get_stdfloat());
763  set_angular_damping(scan.get_stdfloat());
764  set_linear_sleep_threshold(scan.get_stdfloat());
765  set_angular_sleep_threshold(scan.get_stdfloat());
766 
767  LVector3 gravity, linear_factor, angular_factor;
768  gravity.read_datagram(scan);
769  linear_factor.read_datagram(scan);
770  angular_factor.read_datagram(scan);
771 
772  set_gravity(gravity);
773  set_linear_factor(linear_factor);
774  set_angular_factor(angular_factor);
775 }
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
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.