Panda3D
|
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