Panda3D
Loading...
Searching...
No Matches
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
21TypeHandle BulletRigidBodyNode::_type_handle;
22
23/**
24 *
25 */
26BulletRigidBodyNode::
27BulletRigidBodyNode(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 */
53BulletRigidBodyNode::
54BulletRigidBodyNode(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 */
72make_copy() const {
73
74 return new BulletRigidBodyNode(*this);
75}
76
77/**
78 *
79 */
80void BulletRigidBodyNode::
81output(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 */
92btCollisionObject *BulletRigidBodyNode::
93get_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 */
103void BulletRigidBodyNode::
104do_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 */
117void BulletRigidBodyNode::
118do_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 */
138set_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 */
149PN_stdfloat BulletRigidBodyNode::
150do_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 */
162PN_stdfloat BulletRigidBodyNode::
163get_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 */
173PN_stdfloat BulletRigidBodyNode::
174get_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 */
191set_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 */
210get_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 */
226LVector3 BulletRigidBodyNode::
227get_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 */
236LMatrix3 BulletRigidBodyNode::
237get_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 */
246void BulletRigidBodyNode::
247apply_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 */
260void BulletRigidBodyNode::
261apply_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 */
272void BulletRigidBodyNode::
273apply_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 */
284void BulletRigidBodyNode::
285apply_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 */
296void BulletRigidBodyNode::
297apply_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 */
310void BulletRigidBodyNode::
311apply_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 */
322void BulletRigidBodyNode::
323do_transform_changed() {
324
325 if (_motion.sync_disabled()) return;
326
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 */
365void BulletRigidBodyNode::
366parents_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 */
379void BulletRigidBodyNode::
380transform_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 */
393do_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 */
404do_sync_b2p() {
405
406 _motion.sync_b2p((PandaNode *)this);
407}
408
409/**
410 *
411 */
412LVector3 BulletRigidBodyNode::
413get_linear_velocity() const {
414 LightMutexHolder holder(BulletWorld::get_global_lock());
415
416 return btVector3_to_LVector3(_rigid->getLinearVelocity());
417}
418
419/**
420 *
421 */
422LVector3 BulletRigidBodyNode::
423get_angular_velocity() const {
424 LightMutexHolder holder(BulletWorld::get_global_lock());
425
426 return btVector3_to_LVector3(_rigid->getAngularVelocity());
427}
428
429/**
430 *
431 */
432void BulletRigidBodyNode::
433set_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 */
444void BulletRigidBodyNode::
445set_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 */
456void BulletRigidBodyNode::
457set_linear_damping(PN_stdfloat value) {
458 LightMutexHolder holder(BulletWorld::get_global_lock());
459
460 _rigid->setDamping(value, _rigid->getAngularDamping());
461}
462
463/**
464 *
465 */
466void BulletRigidBodyNode::
467set_angular_damping(PN_stdfloat value) {
468 LightMutexHolder holder(BulletWorld::get_global_lock());
469
470 _rigid->setDamping(_rigid->getLinearDamping(), value);
471}
472
473/**
474 *
475 */
476PN_stdfloat BulletRigidBodyNode::
477get_linear_damping() const {
478 LightMutexHolder holder(BulletWorld::get_global_lock());
479
480 return (PN_stdfloat)_rigid->getLinearDamping();
481}
482
483/**
484 *
485 */
486PN_stdfloat BulletRigidBodyNode::
487get_angular_damping() const {
488 LightMutexHolder holder(BulletWorld::get_global_lock());
489
490 return (PN_stdfloat)_rigid->getAngularDamping();
491}
492
493/**
494 *
495 */
496void BulletRigidBodyNode::
497clear_forces() {
498 LightMutexHolder holder(BulletWorld::get_global_lock());
499
500 _rigid->clearForces();
501}
502
503/**
504 *
505 */
506PN_stdfloat BulletRigidBodyNode::
507get_linear_sleep_threshold() const {
508 LightMutexHolder holder(BulletWorld::get_global_lock());
509
510 return _rigid->getLinearSleepingThreshold();
511}
512
513/**
514 *
515 */
516PN_stdfloat BulletRigidBodyNode::
517get_angular_sleep_threshold() const {
518 LightMutexHolder holder(BulletWorld::get_global_lock());
519
520 return _rigid->getAngularSleepingThreshold();
521}
522
523/**
524 *
525 */
526void BulletRigidBodyNode::
527set_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 */
536void BulletRigidBodyNode::
537set_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 */
546void BulletRigidBodyNode::
547set_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 */
558LVector3 BulletRigidBodyNode::
559get_gravity() const {
560 LightMutexHolder holder(BulletWorld::get_global_lock());
561
562 return btVector3_to_LVector3(_rigid->getGravity());
563}
564
565/**
566 *
567 */
568LVector3 BulletRigidBodyNode::
569get_linear_factor() const {
570 LightMutexHolder holder(BulletWorld::get_global_lock());
571
572 return btVector3_to_LVector3(_rigid->getLinearFactor());
573}
574
575/**
576 *
577 */
578LVector3 BulletRigidBodyNode::
579get_angular_factor() const {
580 LightMutexHolder holder(BulletWorld::get_global_lock());
581
582 return btVector3_to_LVector3(_rigid->getAngularFactor());
583}
584
585/**
586 *
587 */
588void BulletRigidBodyNode::
589set_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 */
598void BulletRigidBodyNode::
599set_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 */
608LVector3 BulletRigidBodyNode::
609get_total_force() const {
610 LightMutexHolder holder(BulletWorld::get_global_lock());
611
612 return btVector3_to_LVector3(_rigid->getTotalForce());
613}
614
615/**
616 *
617 */
618LVector3 BulletRigidBodyNode::
619get_total_torque() const {
620 LightMutexHolder holder(BulletWorld::get_global_lock());
621
622 return btVector3_to_LVector3(_rigid->getTotalTorque());
623}
624
625/**
626 *
627 */
628BulletRigidBodyNode::MotionState::
629MotionState() {
630
631 _trans.setIdentity();
632 _disabled = false;
633 _dirty = false;
634 _was_dirty = false;
635}
636
637/**
638 *
639 */
640void BulletRigidBodyNode::MotionState::
641getWorldTransform(btTransform &trans) const {
642
643 trans = _trans;
644}
645
646/**
647 *
648 */
649void BulletRigidBodyNode::MotionState::
650setWorldTransform(const btTransform &trans) {
651
652 _trans = trans;
653 _dirty = true;
654 _was_dirty = true;
655}
656
657/**
658 *
659 */
660void BulletRigidBodyNode::MotionState::
661sync_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 */
683void BulletRigidBodyNode::MotionState::
684set_net_transform(const TransformState *ts) {
685
686 nassertv(ts);
687
688 _trans = TransformState_to_btTrans(ts);
689}
690
691/**
692 *
693 */
694bool BulletRigidBodyNode::MotionState::
695sync_disabled() const {
696
697 return _disabled;
698}
699
700/**
701 *
702 */
703bool BulletRigidBodyNode::MotionState::
704pick_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 */
734write_datagram(BamWriter *manager, Datagram &dg) {
736
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 */
755TypedWritable *BulletRigidBodyNode::
756make_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 */
771void BulletRigidBodyNode::
772fillin(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...
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.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.