39BulletBodyNode(
const char *name) :
PandaNode(name) {
42 _shape =
new btEmptyShape();
57 _shapes = copy._shapes;
58 if (copy._shape && copy._shape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
60 btCompoundShape *shape =
new btCompoundShape;
63 btCompoundShape *copy_shape = (btCompoundShape *)copy._shape;
64 int num_children = copy_shape->getNumChildShapes();
65 for (
int i = 0; i < num_children; ++i) {
66 shape->addChildShape(copy_shape->getChildTransform(i),
67 copy_shape->getChildShape(i));
70 else if (copy._shape && copy._shape->getShapeType() == EMPTY_SHAPE_PROXYTYPE) {
71 _shape =
new btEmptyShape();
162do_output(std::ostream &out)
const {
164 PandaNode::output(out);
166 out <<
" (" << _shapes.size() <<
" shapes)";
168 out << (get_object()->isActive() ?
" active" :
" inactive");
170 if (get_object()->isStaticObject()) out <<
" static";
171 if (get_object()->isKinematicObject()) out <<
" kinematic";
178output(std::ostream &out)
const {
179 LightMutexHolder holder(BulletWorld::get_global_lock());
188set_collision_flag(
int flag,
bool value) {
189 LightMutexHolder holder(BulletWorld::get_global_lock());
191 int flags = get_object()->getCollisionFlags();
200 get_object()->setCollisionFlags(flags);
207get_collision_flag(
int flag)
const {
208 LightMutexHolder holder(BulletWorld::get_global_lock());
210 return (get_object()->getCollisionFlags() & flag) ? true :
false;
218 LightMutexHolder holder(BulletWorld::get_global_lock());
220 return get_object()->isStaticObject();
227is_kinematic()
const {
228 LightMutexHolder holder(BulletWorld::get_global_lock());
230 return get_object()->isKinematicObject();
236PN_stdfloat BulletBodyNode::
237get_restitution()
const {
238 LightMutexHolder holder(BulletWorld::get_global_lock());
240 return get_object()->getRestitution();
247set_restitution(PN_stdfloat restitution) {
248 LightMutexHolder holder(BulletWorld::get_global_lock());
250 return get_object()->setRestitution(restitution);
256PN_stdfloat BulletBodyNode::
257get_friction()
const {
258 LightMutexHolder holder(BulletWorld::get_global_lock());
260 return get_object()->getFriction();
267set_friction(PN_stdfloat friction) {
268 LightMutexHolder holder(BulletWorld::get_global_lock());
270 return get_object()->setFriction(friction);
273#if BT_BULLET_VERSION >= 281
277PN_stdfloat BulletBodyNode::
278get_rolling_friction()
const {
279 LightMutexHolder holder(BulletWorld::get_global_lock());
281 return get_object()->getRollingFriction();
288set_rolling_friction(PN_stdfloat friction) {
289 LightMutexHolder holder(BulletWorld::get_global_lock());
291 return get_object()->setRollingFriction(friction);
299has_anisotropic_friction()
const {
300 LightMutexHolder holder(BulletWorld::get_global_lock());
302 return get_object()->hasAnisotropicFriction();
309get_num_shapes()
const {
310 LightMutexHolder holder(BulletWorld::get_global_lock());
312 return _shapes.size();
319get_shape(
int idx)
const {
320 LightMutexHolder holder(BulletWorld::get_global_lock());
322 nassertr(idx >= 0 && idx < (
int)_shapes.size(),
nullptr);
331 LightMutexHolder holder(BulletWorld::get_global_lock());
333 do_add_shape(bullet_shape, ts);
342 nassertv(get_object());
345 btCollisionShape *shape = bullet_shape->ptr();
346 nassertv(shape !=
nullptr);
348 nassertv(!(shape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE &&
349 ((btConvexHullShape *)shape)->getNumVertices() == 0));
352 btTransform trans = TransformState_to_btTrans(ts);
357 bool scale_changed =
false;
358 if (!prev_transform->is_identity() && prev_transform->get_scale() != LVecBase3(1.0, 1.0, 1.0)) {
361 LightMutex &lock = BulletWorld::get_global_lock();
363 set_transform(prev_transform->set_scale(LVecBase3(1.0, 1.0, 1.0)));
365 scale_changed =
true;
369 btCollisionShape *previous = get_object()->getCollisionShape();
370 btCollisionShape *next;
372 if (_shapes.size() == 0) {
373 nassertv(previous->getShapeType() == EMPTY_SHAPE_PROXYTYPE);
384 next =
new btCompoundShape();
385 ((btCompoundShape *)next)->addChildShape(trans, shape);
388 get_object()->setCollisionShape(next);
393 else if (_shapes.size() == 1) {
394 if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
400 ((btCompoundShape *)next)->addChildShape(trans, shape);
405 next =
new btCompoundShape();
407 btTransform previous_trans = btTransform::getIdentity();
408 ((btCompoundShape *)next)->addChildShape(previous_trans, previous);
409 ((btCompoundShape *)next)->addChildShape(trans, shape);
411 get_object()->setCollisionShape(next);
419 nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
422 ((btCompoundShape *)next)->addChildShape(trans, shape);
425 _shapes.push_back(bullet_shape);
429 CPT(
TransformState) transform = get_transform()->set_scale(prev_transform->get_scale());
430 LightMutex &lock = BulletWorld::get_global_lock();
444 LightMutexHolder holder(BulletWorld::get_global_lock());
446 nassertv(get_object());
448 BulletShapes::iterator found;
449 PT(BulletShape) ptshape = shape;
450 found = find(_shapes.begin(), _shapes.end(), ptshape);
452 if (found == _shapes.end()) {
453 bullet_cat.warning() <<
"shape not attached" << std::endl;
456 _shapes.erase(found);
459 btCollisionShape *previous = get_object()->getCollisionShape();
460 btCollisionShape *next;
462 if (_shapes.size() == 0) {
464 next =
new btEmptyShape();
466 get_object()->setCollisionShape(next);
470 if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
474 else if (_shapes.size() == 1) {
476 nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
478 btCompoundShape *compound = (btCompoundShape *)previous;
479 compound->removeChildShape(shape->ptr());
481 nassertv(compound->getNumChildShapes() == 1);
485 btTransform trans = compound->getChildTransform(0);
486 if (is_identity(trans)) {
487 next = compound->getChildShape(0);
489 get_object()->setCollisionShape(next);
497 nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
499 btCompoundShape *compound = (btCompoundShape *)previous;
500 compound->removeChildShape(shape->ptr());
511is_identity(btTransform &trans) {
513 btVector3 null(0, 0, 0);
515 return (trans.getOrigin() == null
516 && trans.getRotation().getAxis() == null);
522LPoint3 BulletBodyNode::
523get_shape_pos(
int idx)
const {
524 LightMutexHolder holder(BulletWorld::get_global_lock());
526 nassertr(idx >= 0 && idx < (
int)_shapes.size(), LPoint3::zero());
528 btCollisionShape *root = get_object()->getCollisionShape();
529 if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
530 btCompoundShape *compound = (btCompoundShape *)root;
532 btTransform trans = compound->getChildTransform(idx);
533 return btVector3_to_LVector3(trans.getOrigin());
536 return LPoint3::zero();
542LMatrix4 BulletBodyNode::
543get_shape_mat(
int idx)
const {
544 LightMutexHolder holder(BulletWorld::get_global_lock());
546 return do_get_shape_transform(idx)->get_mat();
553do_get_shape_transform(
int idx)
const {
555 nassertr(idx >= 0 && idx < (
int)_shapes.size(), TransformState::make_identity());
557 btCollisionShape *root = get_object()->getCollisionShape();
558 if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
559 btCompoundShape *compound = (btCompoundShape *)root;
561 btTransform trans = compound->getChildTransform(idx);
562 return btTrans_to_TransformState(trans);
578 return TransformState::make_identity();
585get_shape_transform(
int idx)
const {
586 LightMutexHolder holder(BulletWorld::get_global_lock());
588 return do_get_shape_transform(idx);
607set_deactivation_time(PN_stdfloat dt) {
608 LightMutexHolder holder(BulletWorld::get_global_lock());
610 get_object()->setDeactivationTime(dt);
616PN_stdfloat BulletBodyNode::
617get_deactivation_time()
const {
618 LightMutexHolder holder(BulletWorld::get_global_lock());
620 return get_object()->getDeactivationTime();
628 LightMutexHolder holder(BulletWorld::get_global_lock());
630 return get_object()->isActive();
637set_active(
bool active,
bool force) {
638 LightMutexHolder holder(BulletWorld::get_global_lock());
641 get_object()->activate(force);
645 get_object()->forceActivationState(ISLAND_SLEEPING);
648 get_object()->setActivationState(ISLAND_SLEEPING);
657force_active(
bool active) {
659 set_active(active,
true);
668 LightMutexHolder holder(BulletWorld::get_global_lock());
672 bool is_enabled = get_object()->getActivationState() != DISABLE_DEACTIVATION;
673 if (enabled != is_enabled) {
677 int state = (enabled) ? ACTIVE_TAG : DISABLE_DEACTIVATION;
678 get_object()->forceActivationState(state);
686is_deactivation_enabled()
const {
687 LightMutexHolder holder(BulletWorld::get_global_lock());
689 return (get_object()->getActivationState() != DISABLE_DEACTIVATION);
697 LightMutexHolder holder(BulletWorld::get_global_lock());
699 btCollisionObject *obj = BulletWorld::get_collision_object(node);
702 return get_object()->checkCollideWith(obj);
712LVecBase3 BulletBodyNode::
713get_anisotropic_friction()
const {
714 LightMutexHolder holder(BulletWorld::get_global_lock());
716 return btVector3_to_LVecBase3(get_object()->getAnisotropicFriction());
723set_anisotropic_friction(
const LVecBase3 &friction) {
724 LightMutexHolder holder(BulletWorld::get_global_lock());
726 nassertv(!friction.is_nan());
727 get_object()->setAnisotropicFriction(LVecBase3_to_btVector3(friction));
734has_contact_response()
const {
735 LightMutexHolder holder(BulletWorld::get_global_lock());
737 return get_object()->hasContactResponse();
743PN_stdfloat BulletBodyNode::
744get_contact_processing_threshold()
const {
745 LightMutexHolder holder(BulletWorld::get_global_lock());
747 return get_object()->getContactProcessingThreshold();
756 LightMutexHolder holder(BulletWorld::get_global_lock());
758 get_object()->setContactProcessingThreshold(threshold);
764PN_stdfloat BulletBodyNode::
765get_ccd_swept_sphere_radius()
const {
766 LightMutexHolder holder(BulletWorld::get_global_lock());
768 return get_object()->getCcdSweptSphereRadius();
775set_ccd_swept_sphere_radius(PN_stdfloat radius) {
776 LightMutexHolder holder(BulletWorld::get_global_lock());
778 return get_object()->setCcdSweptSphereRadius(radius);
784PN_stdfloat BulletBodyNode::
785get_ccd_motion_threshold()
const {
786 LightMutexHolder holder(BulletWorld::get_global_lock());
788 return get_object()->getCcdMotionThreshold();
795set_ccd_motion_threshold(PN_stdfloat threshold) {
796 LightMutexHolder holder(BulletWorld::get_global_lock());
798 return get_object()->setCcdMotionThreshold(threshold);
806 LightMutexHolder holder(BulletWorld::get_global_lock());
808 PT(BulletTriangleMesh) mesh =
nullptr;
810 for (
size_t j = 0; j < cnode->get_num_solids(); ++j) {
811 CPT(CollisionSolid) solid = cnode->get_solid(j);
812 TypeHandle type = solid->get_type();
815 if (CollisionSphere::get_class_type() == type) {
816 CPT(CollisionSphere) sphere = DCAST(CollisionSphere, solid);
817 CPT(
TransformState) ts = TransformState::make_pos(sphere->get_center());
819 do_add_shape(BulletSphereShape::make_from_solid(sphere), ts);
823 else if (CollisionBox::get_class_type() == type) {
824 CPT(CollisionBox) box = DCAST(CollisionBox, solid);
825 CPT(
TransformState) ts = TransformState::make_pos(box->get_center());
827 do_add_shape(BulletBoxShape::make_from_solid(box), ts);
831 else if (CollisionCapsule::get_class_type() == type) {
832 CPT(CollisionCapsule) capsule = DCAST(CollisionCapsule, solid);
833 CPT(
TransformState) ts = TransformState::make_pos((capsule->get_point_b() + capsule->get_point_a()) / 2.0);
839 else if (CollisionPlane::get_class_type() == type) {
840 CPT(CollisionPlane) plane = DCAST(CollisionPlane, solid);
842 do_add_shape(BulletPlaneShape::make_from_solid(plane));
846 else if (CollisionPolygon::get_class_type() == type) {
847 CPT(CollisionPolygon) polygon = DCAST(CollisionPolygon, solid);
850 mesh =
new BulletTriangleMesh();
853 for (
size_t i = 2; i < polygon->get_num_points(); ++i) {
854 LPoint3 p1 = polygon->get_point(0);
855 LPoint3 p2 = polygon->get_point(i - 1);
856 LPoint3 p3 = polygon->get_point(i);
858 mesh->do_add_triangle(p1, p2, p3,
true);
863 if (mesh && mesh->do_get_num_triangles() > 0) {
864 do_add_shape(
new BulletTriangleMeshShape(mesh,
true));
901 _shape->getBoundingSphere(center, radius);
904 BoundingSphere bounds(btVector3_to_LPoint3(center), (PN_stdfloat)radius);
920 dg.
add_bool(get_collision_response());
924 dg.
add_bool(is_deactivation_enabled());
928#if BT_BULLET_VERSION >= 281
933 if (has_anisotropic_friction()) {
935 get_anisotropic_friction().write_datagram(dg);
942 for (
unsigned int i = 0; i < _shapes.size(); ++i) {
961 while (shape !=
nullptr) {
963 add_shape(shape, trans);
989 PandaNode::fillin(scan, manager);
994 set_collision_response(scan.
get_bool());
1001#if BT_BULLET_VERSION >= 281
1008 friction.read_datagram(scan);
1009 set_anisotropic_friction(friction);
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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...
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
static BitMask< uint32_t, nbits > all_on()
This defines a bounding sphere, consisting of a center and a radius.
virtual int complete_pointers(TypedWritable **plist, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
virtual bool require_fully_complete() const
Some objects require all of their nested pointers to have been completed before the objects themselve...
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of Node by duplicating insta...
void set_transform_dirty()
This method enforces an update of the Bullet transform, that is copies the scene graph transform to t...
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of Node by calling the xform()...
virtual bool safe_to_flatten_below() const
Returns true if a flatten operation may safely continue past this node, or false if nodes below this ...
get_shape_bounds
Returns the current bounds of all collision shapes owned by this body.
set_deactivation_enabled
If true, this object will be deactivated after a certain amount of time has passed without movement.
virtual bool safe_to_combine() const
Returns true if it is generally safe to combine this particular kind of PandaNode with other kinds of...
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 bool safe_to_modify_transform() const
Returns true if it is safe to automatically adjust the transform on this kind of node.
set_contact_processing_threshold
The constraint solver can discard solving contacts, if the distance is above this threshold.
virtual CollideMask get_legal_collide_mask() const
Returns the subset of CollideMask bits that may be set for this particular type of PandaNode.
virtual bool safe_to_combine_children() const
Returns true if it is generally safe to combine the children of this PandaNode with each other.
static BulletCapsuleShape * make_from_solid(const CollisionCapsule *solid)
Constructs a new BulletCapsuleShape using the information from a CollisionCapsule from the builtin co...
A node in the scene graph that can hold any number of CollisionSolids.
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...
bool get_bool()
Extracts a boolean value.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void add_stdfloat(PN_stdfloat value)
Adds either a 32-bit or a 64-bit floating-point number, according to set_stdfloat_double().
void add_bool(bool value)
Adds a boolean value to the datagram.
void release() const
Releases the lightMutex.
void acquire() const
Grabs the lightMutex if it is available.
Similar to MutexHolder, but for a light mutex.
A basic node of the scene graph or data graph.
set_transform
Sets the transform that will be applied to this node and below.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
TypeHandle is the identifier used to differentiate C++ class types.
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.