Panda3D

bulletBodyNode.cxx

00001 // Filename: bulletBodyNode.cxx
00002 // Created by:  enn0x (19Nov10)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "bulletBodyNode.h"
00016 #include "bulletShape.h"
00017 #include "bulletWorld.h"
00018 #include "bulletTriangleMesh.h"
00019 
00020 #include "collisionBox.h"
00021 #include "collisionPlane.h"
00022 #include "collisionSphere.h"
00023 #include "collisionPolygon.h"
00024 
00025 TypeHandle BulletBodyNode::_type_handle;
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: BulletBodyNode::Constructor
00029 //       Access: Published
00030 //  Description:
00031 ////////////////////////////////////////////////////////////////////
00032 BulletBodyNode::
00033 BulletBodyNode(const char *name) : PandaNode(name) {
00034 
00035   // Shape
00036   _shape = new btEmptyShape();
00037 
00038   // Default collide mask
00039   set_into_collide_mask(CollideMask::all_on());
00040 }
00041 
00042 ////////////////////////////////////////////////////////////////////
00043 //     Function: BulletBodyNode::get_legal_collide_mask
00044 //       Access: Public, virtual
00045 //  Description: Returns the subset of CollideMask bits that may be
00046 //               set for this particular type of PandaNode.  For 
00047 //               BodyNodes this returns all bits on.
00048 ////////////////////////////////////////////////////////////////////
00049 CollideMask BulletBodyNode::
00050 get_legal_collide_mask() const {
00051 
00052   return CollideMask::all_on();
00053 }
00054 
00055 ////////////////////////////////////////////////////////////////////
00056 //     Function: BulletBodyNode::safe_to_flatten
00057 //       Access: Public, Virtual
00058 //  Description: Returns true if it is generally safe to flatten out
00059 //               this particular kind of Node by duplicating
00060 //               instances, false otherwise (for instance, a Camera
00061 //               cannot be safely flattened, because the Camera
00062 //               pointer itself is meaningful).
00063 ////////////////////////////////////////////////////////////////////
00064 bool BulletBodyNode::
00065 safe_to_flatten() const {
00066 
00067   return false;
00068 }
00069 
00070 ////////////////////////////////////////////////////////////////////
00071 //     Function: BulletBodyNode::safe_to_transform
00072 //       Access: Public, Virtual
00073 //  Description: Returns true if it is generally safe to transform
00074 //               this particular kind of Node by calling the xform()
00075 //               method, false otherwise.  For instance, it's usually
00076 //               a bad idea to attempt to xform a Character.
00077 ////////////////////////////////////////////////////////////////////
00078 bool BulletBodyNode::
00079 safe_to_transform() const {
00080 
00081   return false;
00082 }
00083 
00084 ////////////////////////////////////////////////////////////////////
00085 //     Function: BulletBodyNode::safe_to_modify_transform
00086 //       Access: Public, Virtual
00087 //  Description: Returns true if it is safe to automatically adjust
00088 //               the transform on this kind of node.  Usually, this is
00089 //               only a bad idea if the user expects to find a
00090 //               particular transform on the node.
00091 //
00092 //               ModelNodes with the preserve_transform flag set are
00093 //               presently the only kinds of nodes that should not
00094 //               have their transform even adjusted.
00095 ////////////////////////////////////////////////////////////////////
00096 bool BulletBodyNode::
00097 safe_to_modify_transform() const {
00098 
00099   return false;
00100 }
00101 
00102 ////////////////////////////////////////////////////////////////////
00103 //     Function: BulletBodyNode::safe_to_combine
00104 //       Access: Public, Virtual
00105 //  Description: Returns true if it is generally safe to combine this
00106 //               particular kind of PandaNode with other kinds of
00107 //               PandaNodes of compatible type, adding children or
00108 //               whatever.  For instance, an LODNode should not be
00109 //               combined with any other PandaNode, because its set of
00110 //               children is meaningful.
00111 ////////////////////////////////////////////////////////////////////
00112 bool BulletBodyNode::
00113 safe_to_combine() const {
00114 
00115   return false;
00116 }
00117 
00118 ////////////////////////////////////////////////////////////////////
00119 //     Function: BulletBodyNode::safe_to_combine_children
00120 //       Access: Public, Virtual
00121 //  Description: Returns true if it is generally safe to combine the
00122 //               children of this PandaNode with each other.  For
00123 //               instance, an LODNode's children should not be
00124 //               combined with each other, because the set of children
00125 //               is meaningful.
00126 ////////////////////////////////////////////////////////////////////
00127 bool BulletBodyNode::
00128 safe_to_combine_children() const {
00129 
00130   return false;
00131 }
00132 
00133 ////////////////////////////////////////////////////////////////////
00134 //     Function: BulletBodyNode::safe_to_flatten_below
00135 //       Access: Public, Virtual
00136 //  Description: Returns true if a flatten operation may safely
00137 //               continue past this node, or false if nodes below this
00138 //               node may not be molested.
00139 ////////////////////////////////////////////////////////////////////
00140 bool BulletBodyNode::
00141 safe_to_flatten_below() const {
00142 
00143   return false;
00144 }
00145 
00146 ////////////////////////////////////////////////////////////////////
00147 //     Function: BulletBodyNode::output
00148 //       Access: Public, Virtual
00149 //  Description: 
00150 ////////////////////////////////////////////////////////////////////
00151 void BulletBodyNode::
00152 output(ostream &out) const {
00153 
00154   PandaNode::output(out);
00155 
00156   out << " (" << get_num_shapes() << " shapes)";
00157 
00158   if (is_static()) out << " static";
00159   if (is_kinematic()) out << " kinematic";
00160 }
00161 
00162 ////////////////////////////////////////////////////////////////////
00163 //     Function: BulletBodyNode::add_shape
00164 //       Access: Published
00165 //  Description:
00166 ////////////////////////////////////////////////////////////////////
00167 void BulletBodyNode::
00168 add_shape(BulletShape *shape, CPT(TransformState) ts) {
00169 
00170   nassertv(get_object());
00171 
00172   nassertv(!(shape->ptr()->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE 
00173     && ((btConvexHullShape *)shape->ptr())->getNumVertices() == 0));
00174 
00175   // Transform
00176   btTransform trans = btTransform::getIdentity();
00177   if (ts) {
00178     trans = TransformState_to_btTrans(ts);
00179   }
00180 
00181   // Root shape
00182   btCollisionShape *previous = get_object()->getCollisionShape();
00183   btCollisionShape *next;
00184 
00185   if (_shapes.size() == 0) {
00186     nassertv(previous->getShapeType() == EMPTY_SHAPE_PROXYTYPE);
00187 
00188     if (ts) {
00189       // One shape, with transform
00190       next = new btCompoundShape();
00191       ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
00192     }
00193     else {
00194       // One shape, w/o transform
00195       next = shape->ptr();
00196     }
00197 
00198     get_object()->setCollisionShape(next);
00199     _shape = next;
00200 
00201     delete previous;
00202   }
00203   else if (_shapes.size() == 1) {
00204     // Two shapes. Previous shape might already be a compound.
00205     if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
00206       next = previous;
00207     }
00208     else {
00209       next = new btCompoundShape();
00210 
00211       btTransform previous_trans = btTransform::getIdentity();
00212       ((btCompoundShape *)next)->addChildShape(previous_trans, previous);
00213     }
00214 
00215     ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
00216 
00217     get_object()->setCollisionShape(next);
00218     _shape = next;
00219   }
00220   else {
00221     // Three or more shapes. Previous shape is always a compound
00222     nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
00223 
00224     ((btCompoundShape *)previous)->addChildShape(trans, shape->ptr());
00225   }
00226 
00227   _shapes.push_back(shape);
00228 
00229   shape_changed();
00230 }
00231 
00232 ////////////////////////////////////////////////////////////////////
00233 //     Function: BulletBodyNode::remove_shape
00234 //       Access: Published
00235 //  Description:
00236 ////////////////////////////////////////////////////////////////////
00237 void BulletBodyNode::
00238 remove_shape(BulletShape *shape) {
00239 
00240   nassertv(get_object());
00241 
00242   BulletShapes::iterator found;
00243   PT(BulletShape) ptshape = shape;
00244   found = find(_shapes.begin(), _shapes.end(), ptshape);
00245 
00246   if (found == _shapes.end()) {
00247     bullet_cat.warning() << "shape not attached" << endl;
00248   }
00249   else {
00250     _shapes.erase(found);
00251 
00252     // Determine the new root shape
00253     btCollisionShape *previous = get_object()->getCollisionShape();
00254     btCollisionShape *next;
00255 
00256     if (_shapes.size() == 0) {
00257       // No more shapes remaining
00258       next = new btEmptyShape();
00259 
00260       get_object()->setCollisionShape(next);
00261       _shape = next;
00262 
00263       // The previous shape might be a compound. Then delete it.
00264       if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
00265         delete previous;
00266       }
00267     }
00268     else if (_shapes.size() == 1) {
00269       // Only one shape remaining
00270       nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
00271 
00272       btCompoundShape *compound = (btCompoundShape *)previous;
00273       compound->removeChildShape(shape->ptr());
00274 
00275       nassertv(compound->getNumChildShapes() == 1);
00276 
00277       // The compound is no longer required if the remaining shape 
00278       // has no transform
00279       btTransform trans = compound->getChildTransform(0);
00280       if (is_identity(trans)) {
00281         next = compound->getChildShape(0);
00282 
00283         get_object()->setCollisionShape(next);
00284         _shape = next;
00285 
00286         delete compound;
00287       }
00288     }
00289     else {
00290       // More than one shape are remaining
00291       nassertv(previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE)
00292 
00293       btCompoundShape *compound = (btCompoundShape *)previous;
00294       compound->removeChildShape(shape->ptr());
00295     }
00296 
00297     shape_changed();
00298   }
00299 }
00300 
00301 ////////////////////////////////////////////////////////////////////
00302 //     Function: BulletBodyNode::is_identity
00303 //       Access: Private
00304 //  Description: Returns TRUE if the transform is an identity
00305 //               transform, otherwise FALSE.
00306 ////////////////////////////////////////////////////////////////////
00307 bool BulletBodyNode::
00308 is_identity(btTransform &trans) {
00309 
00310   btVector3 null(0, 0, 0);
00311 
00312   return (trans.getOrigin() == null 
00313        && trans.getRotation().getAxis() == null);
00314 }
00315 
00316 ////////////////////////////////////////////////////////////////////
00317 //     Function: BulletBodyNode::get_shape_pos
00318 //       Access: Published
00319 //  Description:
00320 ////////////////////////////////////////////////////////////////////
00321 LPoint3 BulletBodyNode::
00322 get_shape_pos(int idx) const {
00323 
00324   nassertr(idx >= 0 && idx < (int)_shapes.size(), LPoint3::zero());
00325   return get_shape_mat(idx).get_row3(3);
00326 }
00327 
00328 ////////////////////////////////////////////////////////////////////
00329 //     Function: BulletBodyNode::get_shape_mat
00330 //       Access: Published
00331 //  Description:
00332 ////////////////////////////////////////////////////////////////////
00333 LMatrix4 BulletBodyNode::
00334 get_shape_mat(int idx) const {
00335 
00336   nassertr(idx >= 0 && idx < (int)_shapes.size(), LMatrix4::ident_mat());
00337 
00338   btCollisionShape *root = get_object()->getCollisionShape();
00339   if (root->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
00340     btCompoundShape *compound = (btCompoundShape *)root;
00341 
00342     btTransform trans = compound->getChildTransform(idx);
00343     return btTrans_to_LMatrix4(trans);
00344 
00345     // The above code assumes that shape's index in _shapes member
00346     // is the same as the shapes index within the compound. If it
00347     // turns out that this is not always true we could use the
00348     // following code:
00349     /*
00350     btCollisionShape *shape = get_shape(idx)->ptr();
00351     for (int i=0; i<compound->getNumChildShapes(); i++) {
00352       if (compound->getChildShape(i) == shape) {
00353          btTransform trans = compound->getChildTransform(idx);
00354          return btTrans_to_LMatrix4(trans);
00355       }
00356     }
00357     */
00358   }
00359 
00360   return LMatrix4::ident_mat();
00361 }
00362 
00363 ////////////////////////////////////////////////////////////////////
00364 //     Function: BulletBodyNode::shape_changed
00365 //       Access: Published
00366 //  Description: Hook which will be called whenever the total shape
00367 //               of a body changed. Used for example to update
00368 //               the mass properties (inertia) of a rigid body.
00369 //               The default implementation does nothing.
00370 ////////////////////////////////////////////////////////////////////
00371 void BulletBodyNode::
00372 shape_changed() {
00373 
00374 }
00375 
00376 ////////////////////////////////////////////////////////////////////
00377 //     Function: BulletBodyNode::set_deactivation_time
00378 //       Access: Published
00379 //  Description:
00380 ////////////////////////////////////////////////////////////////////
00381 void BulletBodyNode::
00382 set_deactivation_time(PN_stdfloat dt) {
00383 
00384   get_object()->setDeactivationTime(dt);
00385 }
00386 
00387 ////////////////////////////////////////////////////////////////////
00388 //     Function: BulletBodyNode::get_deactivation_time
00389 //       Access: Published
00390 //  Description:
00391 ////////////////////////////////////////////////////////////////////
00392 PN_stdfloat BulletBodyNode::
00393 get_deactivation_time() const {
00394 
00395   return get_object()->getDeactivationTime();
00396 }
00397 
00398 ////////////////////////////////////////////////////////////////////
00399 //     Function: BulletBodyNode::is_active
00400 //       Access: Published
00401 //  Description:
00402 ////////////////////////////////////////////////////////////////////
00403 bool BulletBodyNode::
00404 is_active() const {
00405 
00406   return get_object()->isActive();
00407 }
00408 
00409 ////////////////////////////////////////////////////////////////////
00410 //     Function: BulletBodyNode::set_active
00411 //       Access: Published
00412 //  Description:
00413 ////////////////////////////////////////////////////////////////////
00414 void BulletBodyNode::
00415 set_active(bool active, bool force) {
00416 
00417   if (active) {
00418     get_object()->activate(force);
00419   }
00420   else {
00421     if (force) {
00422       get_object()->forceActivationState(ISLAND_SLEEPING);
00423     }
00424     else {
00425       get_object()->setActivationState(ISLAND_SLEEPING);
00426     }
00427   }
00428 }
00429 
00430 ////////////////////////////////////////////////////////////////////
00431 //     Function: BulletBodyNode::set_deactivation_enabled
00432 //       Access: Published
00433 //  Description:
00434 ////////////////////////////////////////////////////////////////////
00435 void BulletBodyNode::
00436 set_deactivation_enabled(const bool enabled, const bool force) {
00437 
00438   int state = (enabled) ? WANTS_DEACTIVATION : DISABLE_DEACTIVATION;
00439 
00440   if (force) {
00441     get_object()->forceActivationState(state);
00442   }
00443   else {
00444     get_object()->setActivationState(state);
00445   }
00446 }
00447 
00448 ////////////////////////////////////////////////////////////////////
00449 //     Function: BulletBodyNode::is_deactivation_enabled
00450 //       Access: Published
00451 //  Description:
00452 ////////////////////////////////////////////////////////////////////
00453 bool BulletBodyNode::
00454 is_deactivation_enabled() const {
00455 
00456   return (get_object()->getActivationState() & DISABLE_DEACTIVATION) == 0;
00457 }
00458 
00459 ////////////////////////////////////////////////////////////////////
00460 //     Function: BulletBodyNode::check_collision_with
00461 //       Access: Published
00462 //  Description:
00463 ////////////////////////////////////////////////////////////////////
00464 bool BulletBodyNode::
00465 check_collision_with(PandaNode *node) {
00466 
00467   btCollisionObject *obj = BulletWorld::get_collision_object(node);
00468 
00469   if (obj) {
00470     return get_object()->checkCollideWith(obj);
00471   }
00472   else {
00473     return false;
00474   }
00475 }
00476 
00477 ////////////////////////////////////////////////////////////////////
00478 //     Function: BulletBodyNode::get_anisotropic_friction
00479 //       Access: Published
00480 //  Description:
00481 ////////////////////////////////////////////////////////////////////
00482 LVecBase3 BulletBodyNode::
00483 get_anisotropic_friction() const {
00484 
00485   return btVector3_to_LVecBase3(get_object()->getAnisotropicFriction());
00486 }
00487 
00488 ////////////////////////////////////////////////////////////////////
00489 //     Function: BulletBodyNode::set_anisotropic_friction
00490 //       Access: Published
00491 //  Description:
00492 ////////////////////////////////////////////////////////////////////
00493 void BulletBodyNode::
00494 set_anisotropic_friction(const LVecBase3 &friction) {
00495 
00496   nassertv(!friction.is_nan());
00497   get_object()->setAnisotropicFriction(LVecBase3_to_btVector3(friction));
00498 }
00499 
00500 ////////////////////////////////////////////////////////////////////
00501 //     Function: BulletBodyNode::has_contact_response
00502 //       Access: Published
00503 //  Description:
00504 ////////////////////////////////////////////////////////////////////
00505 bool BulletBodyNode::
00506 has_contact_response() const {
00507 
00508   return get_object()->hasContactResponse();
00509 }
00510 
00511 ////////////////////////////////////////////////////////////////////
00512 //     Function: BulletBodyNode::get_contact_processing_threshold
00513 //       Access: Published
00514 //  Description:
00515 ////////////////////////////////////////////////////////////////////
00516 PN_stdfloat BulletBodyNode::
00517 get_contact_processing_threshold() const {
00518 
00519   return get_object()->getContactProcessingThreshold();
00520 }
00521 
00522 ////////////////////////////////////////////////////////////////////
00523 //     Function: BulletBodyNode::set_contact_processing_threshold
00524 //       Access: Published
00525 //  Description: The constraint solver can discard solving
00526 //               contacts, if the distance is above this threshold.
00527 ////////////////////////////////////////////////////////////////////
00528 void BulletBodyNode::
00529 set_contact_processing_threshold(PN_stdfloat threshold) {
00530 
00531   get_object()->setContactProcessingThreshold(threshold);
00532 }
00533 
00534 ////////////////////////////////////////////////////////////////////
00535 //     Function: BulletBodyNode::get_ccd_swept_sphere_radius
00536 //       Access: Published
00537 //  Description:
00538 ////////////////////////////////////////////////////////////////////
00539 PN_stdfloat BulletBodyNode::
00540 get_ccd_swept_sphere_radius() const {
00541 
00542   return get_object()->getCcdSweptSphereRadius();
00543 }
00544 
00545 ////////////////////////////////////////////////////////////////////
00546 //     Function: BulletBodyNode::set_ccd_swept_sphere_radius
00547 //       Access: Published
00548 //  Description:
00549 ////////////////////////////////////////////////////////////////////
00550 void BulletBodyNode::
00551 set_ccd_swept_sphere_radius(PN_stdfloat radius) {
00552 
00553   return get_object()->setCcdSweptSphereRadius(radius);
00554 }
00555 
00556 ////////////////////////////////////////////////////////////////////
00557 //     Function: BulletBodyNode::get_ccd_motion_threshold
00558 //       Access: Published
00559 //  Description:
00560 ////////////////////////////////////////////////////////////////////
00561 PN_stdfloat BulletBodyNode::
00562 get_ccd_motion_threshold() const {
00563 
00564   return get_object()->getCcdMotionThreshold();
00565 }
00566 
00567 ////////////////////////////////////////////////////////////////////
00568 //     Function: BulletBodyNode::set_ccd_motion_threshold
00569 //       Access: Published
00570 //  Description:
00571 ////////////////////////////////////////////////////////////////////
00572 void BulletBodyNode::
00573 set_ccd_motion_threshold(PN_stdfloat threshold) {
00574 
00575   return get_object()->setCcdMotionThreshold(threshold);
00576 }
00577 
00578 ////////////////////////////////////////////////////////////////////
00579 //     Function: BulletBodyNode::add_shapes_from_collision_solids
00580 //       Access: Published
00581 //  Description:
00582 ////////////////////////////////////////////////////////////////////
00583 void BulletBodyNode::
00584 add_shapes_from_collision_solids(CollisionNode *cnode) {
00585 
00586   PT(BulletTriangleMesh) mesh = NULL;
00587 
00588   for (int j=0; j<cnode->get_num_solids(); j++) {
00589     CPT(CollisionSolid) solid = cnode->get_solid(j);
00590     TypeHandle type = solid->get_type();
00591 
00592     // CollisionSphere
00593     if (CollisionSphere::get_class_type() == type) {
00594       CPT(CollisionSphere) sphere = DCAST(CollisionSphere, solid);
00595       CPT(TransformState) ts = TransformState::make_pos(sphere->get_center());
00596 
00597       add_shape(BulletSphereShape::make_from_solid(sphere), ts);
00598     }
00599 
00600     // CollisionBox
00601     else if (CollisionBox::get_class_type() == type) {
00602       CPT(CollisionBox) box = DCAST(CollisionBox, solid);
00603       CPT(TransformState) ts = TransformState::make_pos(box->get_approx_center());
00604 
00605       add_shape(BulletBoxShape::make_from_solid(box), ts);
00606     }
00607 
00608     // CollisionPlane
00609     else if (CollisionPlane::get_class_type() == type) {
00610       CPT(CollisionPlane) plane = DCAST(CollisionPlane, solid);
00611 
00612       add_shape(BulletPlaneShape::make_from_solid(plane));
00613     }
00614 
00615     // CollisionGeom
00616     else if (CollisionPolygon::get_class_type() == type) {
00617       CPT(CollisionPolygon) polygon = DCAST(CollisionPolygon, solid);
00618 
00619       if (!mesh) {
00620          mesh = new BulletTriangleMesh();
00621       }
00622 
00623       for (int i=2; i < polygon->get_num_points(); i++ ) {
00624         LPoint3 p1 = polygon->get_point(0);
00625         LPoint3 p2 = polygon->get_point(i-1);
00626         LPoint3 p3 = polygon->get_point(i);
00627 
00628         mesh->add_triangle(p1, p2, p3, true);
00629       }
00630     }
00631   }
00632 
00633   if (mesh && mesh->get_num_triangles() > 0) {
00634     add_shape(new BulletTriangleMeshShape(mesh, true));
00635   }
00636 }
00637 
 All Classes Functions Variables Enumerations