00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00029
00030
00031
00032 BulletBodyNode::
00033 BulletBodyNode(const char *name) : PandaNode(name) {
00034
00035
00036 _shape = new btEmptyShape();
00037
00038
00039 set_into_collide_mask(CollideMask::all_on());
00040 }
00041
00042
00043
00044
00045
00046
00047
00048
00049 CollideMask BulletBodyNode::
00050 get_legal_collide_mask() const {
00051
00052 return CollideMask::all_on();
00053 }
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 bool BulletBodyNode::
00065 safe_to_flatten() const {
00066
00067 return false;
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 bool BulletBodyNode::
00079 safe_to_transform() const {
00080
00081 return false;
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 bool BulletBodyNode::
00097 safe_to_modify_transform() const {
00098
00099 return false;
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 bool BulletBodyNode::
00113 safe_to_combine() const {
00114
00115 return false;
00116 }
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 bool BulletBodyNode::
00128 safe_to_combine_children() const {
00129
00130 return false;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140 bool BulletBodyNode::
00141 safe_to_flatten_below() const {
00142
00143 return false;
00144 }
00145
00146
00147
00148
00149
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
00164
00165
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
00176 btTransform trans = btTransform::getIdentity();
00177 if (ts) {
00178 trans = TransformState_to_btTrans(ts);
00179 }
00180
00181
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
00190 next = new btCompoundShape();
00191 ((btCompoundShape *)next)->addChildShape(trans, shape->ptr());
00192 }
00193 else {
00194
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
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
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
00234
00235
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
00253 btCollisionShape *previous = get_object()->getCollisionShape();
00254 btCollisionShape *next;
00255
00256 if (_shapes.size() == 0) {
00257
00258 next = new btEmptyShape();
00259
00260 get_object()->setCollisionShape(next);
00261 _shape = next;
00262
00263
00264 if (previous->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) {
00265 delete previous;
00266 }
00267 }
00268 else if (_shapes.size() == 1) {
00269
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
00278
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
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
00303
00304
00305
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
00318
00319
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
00330
00331
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
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 }
00359
00360 return LMatrix4::ident_mat();
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 void BulletBodyNode::
00372 shape_changed() {
00373
00374 }
00375
00376
00377
00378
00379
00380
00381 void BulletBodyNode::
00382 set_deactivation_time(PN_stdfloat dt) {
00383
00384 get_object()->setDeactivationTime(dt);
00385 }
00386
00387
00388
00389
00390
00391
00392 PN_stdfloat BulletBodyNode::
00393 get_deactivation_time() const {
00394
00395 return get_object()->getDeactivationTime();
00396 }
00397
00398
00399
00400
00401
00402
00403 bool BulletBodyNode::
00404 is_active() const {
00405
00406 return get_object()->isActive();
00407 }
00408
00409
00410
00411
00412
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
00432
00433
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
00450
00451
00452
00453 bool BulletBodyNode::
00454 is_deactivation_enabled() const {
00455
00456 return (get_object()->getActivationState() & DISABLE_DEACTIVATION) == 0;
00457 }
00458
00459
00460
00461
00462
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
00479
00480
00481
00482 LVecBase3 BulletBodyNode::
00483 get_anisotropic_friction() const {
00484
00485 return btVector3_to_LVecBase3(get_object()->getAnisotropicFriction());
00486 }
00487
00488
00489
00490
00491
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
00502
00503
00504
00505 bool BulletBodyNode::
00506 has_contact_response() const {
00507
00508 return get_object()->hasContactResponse();
00509 }
00510
00511
00512
00513
00514
00515
00516 PN_stdfloat BulletBodyNode::
00517 get_contact_processing_threshold() const {
00518
00519 return get_object()->getContactProcessingThreshold();
00520 }
00521
00522
00523
00524
00525
00526
00527
00528 void BulletBodyNode::
00529 set_contact_processing_threshold(PN_stdfloat threshold) {
00530
00531 get_object()->setContactProcessingThreshold(threshold);
00532 }
00533
00534
00535
00536
00537
00538
00539 PN_stdfloat BulletBodyNode::
00540 get_ccd_swept_sphere_radius() const {
00541
00542 return get_object()->getCcdSweptSphereRadius();
00543 }
00544
00545
00546
00547
00548
00549
00550 void BulletBodyNode::
00551 set_ccd_swept_sphere_radius(PN_stdfloat radius) {
00552
00553 return get_object()->setCcdSweptSphereRadius(radius);
00554 }
00555
00556
00557
00558
00559
00560
00561 PN_stdfloat BulletBodyNode::
00562 get_ccd_motion_threshold() const {
00563
00564 return get_object()->getCcdMotionThreshold();
00565 }
00566
00567
00568
00569
00570
00571
00572 void BulletBodyNode::
00573 set_ccd_motion_threshold(PN_stdfloat threshold) {
00574
00575 return get_object()->setCcdMotionThreshold(threshold);
00576 }
00577
00578
00579
00580
00581
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
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
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
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
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