15 #include "bulletBodyNode.h" 16 #include "bulletShape.h" 17 #include "bulletWorld.h" 18 #include "bulletTriangleMesh.h" 20 #include "collisionBox.h" 21 #include "collisionPlane.h" 22 #include "collisionSphere.h" 23 #include "collisionPolygon.h" 33 BulletBodyNode(
const char *name) :
PandaNode(name) {
36 _shape =
new btEmptyShape();
151 void BulletBodyNode::
152 output(ostream &out)
const {
154 PandaNode::output(out);
156 out <<
" (" << get_num_shapes() <<
" shapes)";
158 if (is_static()) out <<
" static";
159 if (is_kinematic()) out <<
" kinematic";
167 void BulletBodyNode::
168 add_shape(
BulletShape *shape,
const TransformState *ts) {
170 nassertv(get_object());
173 nassertv(!(shape->ptr()->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE
174 && ((btConvexHullShape *)shape->ptr())->getNumVertices() == 0));
177 btTransform trans = TransformState_to_btTrans(ts);
186 btCollisionShape *previous = get_object()->getCollisionShape();
187 btCollisionShape *next;
189 if (_shapes.size() == 0) {
190 nassertv(previous->getShapeType() == EMPTY_SHAPE_PROXYTYPE);
192 if (ts->is_identity()) {
201 next =
new btCompoundShape();
202 ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
205 get_object()->setCollisionShape(next);
210 else if (_shapes.size() == 1) {
211 if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
217 ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
222 next =
new btCompoundShape();
224 btTransform previous_trans = btTransform::getIdentity();
225 ((btCompoundShape *)next)->addChildShape(previous_trans, previous);
226 ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
228 get_object()->setCollisionShape(next);
236 nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
239 ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
242 _shapes.push_back(shape);
255 void BulletBodyNode::
258 nassertv(get_object());
260 BulletShapes::iterator found;
262 found = find(_shapes.begin(), _shapes.end(), ptshape);
264 if (found == _shapes.end()) {
265 bullet_cat.warning() <<
"shape not attached" << endl;
268 _shapes.erase(found);
271 btCollisionShape *previous = get_object()->getCollisionShape();
272 btCollisionShape *next;
274 if (_shapes.size() == 0) {
276 next =
new btEmptyShape();
278 get_object()->setCollisionShape(next);
282 if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
286 else if (_shapes.size() == 1) {
288 nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
290 btCompoundShape *compound = (btCompoundShape *)previous;
291 compound->removeChildShape(shape->ptr());
293 nassertv(compound->getNumChildShapes() == 1);
297 btTransform trans = compound->getChildTransform(0);
298 if (is_identity(trans)) {
299 next = compound->getChildShape(0);
301 get_object()->setCollisionShape(next);
309 nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
311 btCompoundShape *compound = (btCompoundShape *)previous;
312 compound->removeChildShape(shape->ptr());
325 bool BulletBodyNode::
326 is_identity(btTransform &trans) {
328 btVector3 null(0, 0, 0);
330 return (trans.getOrigin() == null
331 && trans.getRotation().getAxis() == null);
340 get_shape_pos(
int idx)
const {
342 nassertr(idx >= 0 && idx < (
int)_shapes.size(),
LPoint3::zero());
343 return get_shape_mat(idx).
get_row3(3);
352 get_shape_mat(
int idx)
const {
356 btCollisionShape *root = get_object()->getCollisionShape();
357 if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
358 btCompoundShape *compound = (btCompoundShape *)root;
360 btTransform trans = compound->getChildTransform(idx);
361 return btTrans_to_LMatrix4(trans);
389 void BulletBodyNode::
399 void BulletBodyNode::
400 set_deactivation_time(PN_stdfloat dt) {
402 get_object()->setDeactivationTime(dt);
410 PN_stdfloat BulletBodyNode::
411 get_deactivation_time()
const {
413 return get_object()->getDeactivationTime();
421 bool BulletBodyNode::
424 return get_object()->isActive();
432 void BulletBodyNode::
433 set_active(
bool active,
bool force) {
436 get_object()->activate(force);
440 get_object()->forceActivationState(ISLAND_SLEEPING);
443 get_object()->setActivationState(ISLAND_SLEEPING);
453 void BulletBodyNode::
454 set_deactivation_enabled(
const bool enabled,
const bool force) {
456 int state = (enabled) ? WANTS_DEACTIVATION : DISABLE_DEACTIVATION;
459 get_object()->forceActivationState(state);
462 get_object()->setActivationState(state);
471 bool BulletBodyNode::
472 is_deactivation_enabled()
const {
474 return (get_object()->getActivationState() & DISABLE_DEACTIVATION) == 0;
482 bool BulletBodyNode::
485 btCollisionObject *obj = BulletWorld::get_collision_object(node);
488 return get_object()->checkCollideWith(obj);
501 get_anisotropic_friction()
const {
503 return btVector3_to_LVecBase3(get_object()->getAnisotropicFriction());
511 void BulletBodyNode::
512 set_anisotropic_friction(
const LVecBase3 &friction) {
514 nassertv(!friction.
is_nan());
515 get_object()->setAnisotropicFriction(LVecBase3_to_btVector3(friction));
523 bool BulletBodyNode::
524 has_contact_response()
const {
526 return get_object()->hasContactResponse();
534 PN_stdfloat BulletBodyNode::
535 get_contact_processing_threshold()
const {
537 return get_object()->getContactProcessingThreshold();
549 get_object()->setContactProcessingThreshold(threshold);
557 PN_stdfloat BulletBodyNode::
558 get_ccd_swept_sphere_radius()
const {
560 return get_object()->getCcdSweptSphereRadius();
568 void BulletBodyNode::
569 set_ccd_swept_sphere_radius(PN_stdfloat radius) {
571 return get_object()->setCcdSweptSphereRadius(radius);
579 PN_stdfloat BulletBodyNode::
580 get_ccd_motion_threshold()
const {
582 return get_object()->getCcdMotionThreshold();
590 void BulletBodyNode::
591 set_ccd_motion_threshold(PN_stdfloat threshold) {
593 return get_object()->setCcdMotionThreshold(threshold);
601 void BulletBodyNode::
606 for (
int j=0; j<cnode->get_num_solids(); j++) {
611 if (CollisionSphere::get_class_type() == type) {
613 CPT(TransformState) ts = TransformState::make_pos(sphere->get_center());
615 add_shape(BulletSphereShape::make_from_solid(sphere), ts);
619 else if (CollisionBox::get_class_type() == type) {
621 CPT(TransformState) ts = TransformState::make_pos(box->get_approx_center());
623 add_shape(BulletBoxShape::make_from_solid(box), ts);
627 else if (CollisionPlane::get_class_type() == type) {
630 add_shape(BulletPlaneShape::make_from_solid(plane));
634 else if (CollisionPolygon::get_class_type() == type) {
641 for (
int i=2; i < polygon->get_num_points(); i++ ) {
642 LPoint3 p1 = polygon->get_point(0);
643 LPoint3 p2 = polygon->get_point(i-1);
644 LPoint3 p3 = polygon->get_point(i);
646 mesh->add_triangle(p1, p2, p3,
true);
651 if (mesh && mesh->get_num_triangles() > 0) {
695 _shape->getBoundingSphere(center, radius);
698 BoundingSphere bounds(btVector3_to_LPoint3(center), (PN_stdfloat)radius);
static const LMatrix4f & ident_mat()
Returns an identity matrix.
A basic node of the scene graph or data graph.
BoundingSphere get_shape_bounds() const
Returns the current bounds of all collision shapes owned by this body.
This is the base class for all three-component vectors and points.
void set_transform_dirty()
This method enforces an update of the Bullet transform, that is copies the scene graph transform to t...
static BitMask< PN_uint32, nbits > all_on()
Returns a BitMask whose bits are all on.
The abstract base class for all things that can collide with other things in the world, and all the things they can collide with (except geometry).
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 ...
This defines a bounding sphere, consisting of a center and a radius.
static const LPoint3f & zero()
Returns a zero-length point.
A cuboid collision volume or object.
void set_scale(PN_stdfloat scale)
Sets the scale component of the transform, leaving translation and rotation untouched.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
A spherical collision volume or object.
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
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...
virtual bool safe_to_modify_transform() const
Returns true if it is safe to automatically adjust the transform on this kind of node.
void set_contact_processing_threshold(PN_stdfloat threshold)
The constraint solver can discard solving contacts, if the distance is above this threshold...
This is a 4-by-4 transform matrix.
virtual bool safe_to_flatten() const
Returns true if it is generally safe to flatten out this particular kind of Node by duplicating insta...
virtual CollideMask get_legal_collide_mask() const
Returns the subset of CollideMask bits that may be set for this particular type of PandaNode...
A node in the scene graph that can hold any number of CollisionSolids.
LVecBase3 get_scale() const
Retrieves the scale component of the transform.
virtual bool safe_to_transform() const
Returns true if it is generally safe to transform this particular kind of Node by calling the xform()...
TypeHandle is the identifier used to differentiate C++ class types.
LVecBase3f get_row3(int row) const
Retrieves the row column of the matrix as a 3-component vector, ignoring the last column...
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
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 bool safe_to_combine_children() const
Returns true if it is generally safe to combine the children of this PandaNode with each other...