39 BulletBodyNode(
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();
161 void BulletBodyNode::
162 do_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";
177 void BulletBodyNode::
178 output(std::ostream &out)
const {
187 void BulletBodyNode::
188 set_collision_flag(
int flag,
bool value) {
191 int flags = get_object()->getCollisionFlags();
200 get_object()->setCollisionFlags(flags);
206 bool BulletBodyNode::
207 get_collision_flag(
int flag)
const {
210 return (get_object()->getCollisionFlags() & flag) ? true :
false;
216 bool BulletBodyNode::
220 return get_object()->isStaticObject();
226 bool BulletBodyNode::
227 is_kinematic()
const {
230 return get_object()->isKinematicObject();
236 PN_stdfloat BulletBodyNode::
237 get_restitution()
const {
240 return get_object()->getRestitution();
246 void BulletBodyNode::
247 set_restitution(PN_stdfloat restitution) {
250 return get_object()->setRestitution(restitution);
256 PN_stdfloat BulletBodyNode::
257 get_friction()
const {
260 return get_object()->getFriction();
266 void BulletBodyNode::
267 set_friction(PN_stdfloat friction) {
270 return get_object()->setFriction(friction);
273 #if BT_BULLET_VERSION >= 281
277 PN_stdfloat BulletBodyNode::
278 get_rolling_friction()
const {
281 return get_object()->getRollingFriction();
287 void BulletBodyNode::
288 set_rolling_friction(PN_stdfloat friction) {
291 return get_object()->setRollingFriction(friction);
298 bool BulletBodyNode::
299 has_anisotropic_friction()
const {
302 return get_object()->hasAnisotropicFriction();
309 get_num_shapes()
const {
312 return _shapes.size();
319 get_shape(
int idx)
const {
322 nassertr(idx >= 0 && idx < (
int)_shapes.size(),
nullptr);
329 void BulletBodyNode::
333 do_add_shape(bullet_shape, ts);
339 void BulletBodyNode::
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();
442 void BulletBodyNode::
446 nassertv(get_object());
448 BulletShapes::iterator found;
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());
510 bool BulletBodyNode::
511 is_identity(btTransform &trans) {
513 btVector3
null(0, 0, 0);
515 return (trans.getOrigin() ==
null
516 && trans.getRotation().getAxis() ==
null);
522 LPoint3 BulletBodyNode::
523 get_shape_pos(
int idx)
const {
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();
542 LMatrix4 BulletBodyNode::
543 get_shape_mat(
int idx)
const {
546 return do_get_shape_transform(idx)->get_mat();
553 do_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();
585 get_shape_transform(
int idx)
const {
588 return do_get_shape_transform(idx);
598 void BulletBodyNode::
606 void BulletBodyNode::
607 set_deactivation_time(PN_stdfloat dt) {
610 get_object()->setDeactivationTime(dt);
616 PN_stdfloat BulletBodyNode::
617 get_deactivation_time()
const {
620 return get_object()->getDeactivationTime();
626 bool BulletBodyNode::
630 return get_object()->isActive();
636 void BulletBodyNode::
637 set_active(
bool active,
bool force) {
641 get_object()->activate(force);
645 get_object()->forceActivationState(ISLAND_SLEEPING);
648 get_object()->setActivationState(ISLAND_SLEEPING);
656 void BulletBodyNode::
657 force_active(
bool active) {
659 set_active(active,
true);
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);
685 bool BulletBodyNode::
686 is_deactivation_enabled()
const {
689 return (get_object()->getActivationState() != DISABLE_DEACTIVATION);
695 bool BulletBodyNode::
699 btCollisionObject *obj = BulletWorld::get_collision_object(node);
702 return get_object()->checkCollideWith(obj);
712 LVecBase3 BulletBodyNode::
713 get_anisotropic_friction()
const {
716 return btVector3_to_LVecBase3(get_object()->getAnisotropicFriction());
722 void BulletBodyNode::
723 set_anisotropic_friction(
const LVecBase3 &friction) {
726 nassertv(!friction.is_nan());
727 get_object()->setAnisotropicFriction(LVecBase3_to_btVector3(friction));
733 bool BulletBodyNode::
734 has_contact_response()
const {
737 return get_object()->hasContactResponse();
743 PN_stdfloat BulletBodyNode::
744 get_contact_processing_threshold()
const {
747 return get_object()->getContactProcessingThreshold();
758 get_object()->setContactProcessingThreshold(threshold);
764 PN_stdfloat BulletBodyNode::
765 get_ccd_swept_sphere_radius()
const {
768 return get_object()->getCcdSweptSphereRadius();
774 void BulletBodyNode::
775 set_ccd_swept_sphere_radius(PN_stdfloat radius) {
778 return get_object()->setCcdSweptSphereRadius(radius);
784 PN_stdfloat BulletBodyNode::
785 get_ccd_motion_threshold()
const {
788 return get_object()->getCcdMotionThreshold();
794 void BulletBodyNode::
795 set_ccd_motion_threshold(PN_stdfloat threshold) {
798 return get_object()->setCcdMotionThreshold(threshold);
804 void BulletBodyNode::
810 for (
size_t j = 0; j < cnode->get_num_solids(); ++j) {
815 if (CollisionSphere::get_class_type() == type) {
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) {
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) {
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) {
842 do_add_shape(BulletPlaneShape::make_from_solid(plane));
846 else if (CollisionPolygon::get_class_type() == type) {
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) {
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);
987 void BulletBodyNode::
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);
CPT(TransformState) BulletBodyNode
Hook which will be called whenever the total shape of a body changed.
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.
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
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()
Returns a BitMask whose bits are 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 cuboid collision volume or object.
This implements a solid consisting of a cylinder with hemispherical endcaps, also known as a capsule ...
A node in the scene graph that can hold any number of CollisionSolids.
The abstract base class for all things that can collide with other things in the world,...
A spherical collision volume or object.
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.
This is a standard, non-reentrant mutex, similar to the Mutex class.
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.
Base class for objects that can be written to and read from Bam files.
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.