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);