Panda3D
 All Classes Functions Variables Enumerations
bulletRigidBodyNode.cxx
00001 // Filename: bulletRigidBodyNode.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 "bulletRigidBodyNode.h"
00016 #include "bulletShape.h"
00017 
00018 TypeHandle BulletRigidBodyNode::_type_handle;
00019 
00020 ////////////////////////////////////////////////////////////////////
00021 //     Function: BulletRigidBodyNode::Constructor
00022 //       Access: Published
00023 //  Description:
00024 ////////////////////////////////////////////////////////////////////
00025 BulletRigidBodyNode::
00026 BulletRigidBodyNode(const char *name) : BulletBodyNode(name) {
00027 
00028   // Synchronised transform
00029   _sync = TransformState::make_identity();
00030   _sync_disable = false;
00031 
00032   // Mass properties
00033   btScalar mass(0.0);
00034   btVector3 inertia(0, 0, 0);
00035 
00036   // Motion state and construction info
00037   MotionState *motion = new MotionState(_sync);
00038   btRigidBody::btRigidBodyConstructionInfo ci(mass, motion, _shape, inertia);
00039 
00040   // Additional damping
00041   if (bullet_additional_damping) {
00042     ci.m_additionalDamping = true;
00043     ci.m_additionalDampingFactor = bullet_additional_damping_linear_factor;
00044     ci.m_additionalLinearDampingThresholdSqr = bullet_additional_damping_linear_threshold;
00045     ci.m_additionalAngularDampingFactor = bullet_additional_damping_angular_factor;
00046     ci.m_additionalAngularDampingThresholdSqr = bullet_additional_damping_angular_threshold;
00047   }
00048 
00049   // Rigid body
00050   _rigid = new btRigidBody(ci);
00051   _rigid->setUserPointer(this);
00052 }
00053 
00054 ////////////////////////////////////////////////////////////////////
00055 //     Function: BulletRigidBodyNode::output
00056 //       Access: Public, Virtual
00057 //  Description: 
00058 ////////////////////////////////////////////////////////////////////
00059 void BulletRigidBodyNode::
00060 output(ostream &out) const {
00061 
00062   BulletBodyNode::output(out);
00063 
00064   out << " mass=" << get_mass();
00065 }
00066 
00067 ////////////////////////////////////////////////////////////////////
00068 //     Function: BulletRigidBodyNode::get_object
00069 //       Access: Public
00070 //  Description:
00071 ////////////////////////////////////////////////////////////////////
00072 btCollisionObject *BulletRigidBodyNode::
00073 get_object() const {
00074 
00075   return _rigid;
00076 }
00077 
00078 ////////////////////////////////////////////////////////////////////
00079 //     Function: BulletRigidBodyNode::shape_changed
00080 //       Access: Published
00081 //  Description: Hook which should be called whenever the total
00082 //               shape of a body changed. Used for example to update
00083 //               the mass properties (inertia) of a rigid body.
00084 //               The default implementation does nothing.
00085 ////////////////////////////////////////////////////////////////////
00086 void BulletRigidBodyNode::
00087 shape_changed() {
00088 
00089   set_mass(get_mass());
00090 }
00091 
00092 ////////////////////////////////////////////////////////////////////
00093 //     Function: BulletRigidBodyNode::set_mass
00094 //       Access: Published
00095 //  Description: Sets the mass of a rigid body. This also modifies
00096 //               the inertia, which is automatically computed from
00097 //               the shape of the body. Setting a value of zero
00098 //               for mass will make the body static. A value of
00099 //               zero can be considered an infinite mass.
00100 ////////////////////////////////////////////////////////////////////
00101 void BulletRigidBodyNode::
00102 set_mass(PN_stdfloat mass) {
00103 
00104   btScalar bt_mass = mass;
00105   btVector3 bt_inertia(0.0, 0.0, 0.0);
00106 
00107   if (bt_mass > 0.0) {
00108     _rigid->getCollisionShape()->calculateLocalInertia(bt_mass, bt_inertia);
00109   }
00110 
00111   _rigid->setMassProps(bt_mass, bt_inertia);
00112   _rigid->updateInertiaTensor();
00113 }
00114 
00115 ////////////////////////////////////////////////////////////////////
00116 //     Function: BulletRigidBodyNode::get_mass
00117 //       Access: Published
00118 //  Description: Returns the total mass of a rigid body.
00119 //               A value of zero means that the body is staic, i.e.
00120 //               has an infinite mass.
00121 ////////////////////////////////////////////////////////////////////
00122 PN_stdfloat BulletRigidBodyNode::
00123 get_mass() const {
00124 
00125   btScalar inv_mass = _rigid->getInvMass();
00126   btScalar mass = inv_mass == btScalar(0.0) ? btScalar(0.0) : btScalar(1.0) / inv_mass;
00127 
00128   return mass;
00129 }
00130 
00131 ////////////////////////////////////////////////////////////////////
00132 //     Function: BulletRigidBodyNode::set_inertia
00133 //       Access: Published
00134 //  Description: Sets the inertia of a rigid body. Inertia is given
00135 //               as a three-component vector. A component value of
00136 //               zero means infinite inertia along this direction.
00137 //               Setting the intertia will override the value which
00138 //               is automatically calculated from the rigid bodies
00139 //               shape. However, it is possible that automatic
00140 //               calculation of intertia is trigger after calling
00141 //               this method, and thus overwriting the explicitly
00142 //               set value again. This happens when:
00143 //               (a) the mass is set after the inertia.
00144 //               (b) a shape is added or removed from the body.
00145 //               (c) the scale of the body changed.
00146 ////////////////////////////////////////////////////////////////////
00147 void BulletRigidBodyNode::
00148 set_inertia(const LVecBase3 &inertia) {
00149 
00150   btVector3 inv_inertia(
00151     inertia.get_x() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_x()),
00152     inertia.get_y() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_y()),
00153     inertia.get_z() == 0.0 ? btScalar(0.0) : btScalar(1.0 / inertia.get_z())
00154     );
00155 
00156   _rigid->setInvInertiaDiagLocal(inv_inertia);
00157   _rigid->updateInertiaTensor();
00158 }
00159 
00160 ////////////////////////////////////////////////////////////////////
00161 //     Function: BulletRigidBodyNode::get_inertia
00162 //       Access: Published
00163 //  Description: Returns the inertia of the rigid body. Inertia is
00164 //               given as a three component vector. A component
00165 //               value of zero means infinite inertia along this
00166 //               direction.
00167 ////////////////////////////////////////////////////////////////////
00168 LVector3 BulletRigidBodyNode::
00169 get_inertia() const {
00170 
00171   btVector3 inv_inertia = _rigid->getInvInertiaDiagLocal();
00172   LVector3 inertia(
00173     inv_inertia.x() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.x(),
00174     inv_inertia.y() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.y(),
00175     inv_inertia.z() == btScalar(0.0) ? 0.0 : 1.0 / inv_inertia.z()
00176     );
00177 
00178   return inertia;
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: BulletRigidBodyNode::apply_force
00183 //       Access: Published
00184 //  Description:
00185 ////////////////////////////////////////////////////////////////////
00186 void BulletRigidBodyNode::
00187 apply_force(const LVector3 &force, const LPoint3 &pos) {
00188 
00189   nassertv_always(!force.is_nan());
00190   nassertv_always(!pos.is_nan());
00191 
00192   _rigid->applyForce(LVecBase3_to_btVector3(force),
00193                      LVecBase3_to_btVector3(pos));
00194 }
00195 
00196 ////////////////////////////////////////////////////////////////////
00197 //     Function: BulletRigidBodyNode::apply_central_force
00198 //       Access: Published
00199 //  Description:
00200 ////////////////////////////////////////////////////////////////////
00201 void BulletRigidBodyNode::
00202 apply_central_force(const LVector3 &force) {
00203 
00204   nassertv_always(!force.is_nan());
00205 
00206   _rigid->applyCentralForce(LVecBase3_to_btVector3(force));
00207 }
00208 
00209 ////////////////////////////////////////////////////////////////////
00210 //     Function: BulletRigidBodyNode::apply_torque
00211 //       Access: Published
00212 //  Description:
00213 ////////////////////////////////////////////////////////////////////
00214 void BulletRigidBodyNode::
00215 apply_torque(const LVector3 &torque) {
00216 
00217   nassertv_always(!torque.is_nan());
00218 
00219   _rigid->applyTorque(LVecBase3_to_btVector3(torque));
00220 }
00221 
00222 ////////////////////////////////////////////////////////////////////
00223 //     Function: BulletRigidBodyNode::apply_torque_impulse
00224 //       Access: Published
00225 //  Description:
00226 ////////////////////////////////////////////////////////////////////
00227 void BulletRigidBodyNode::
00228 apply_torque_impulse(const LVector3 &torque) {
00229 
00230   nassertv_always(!torque.is_nan());
00231 
00232   _rigid->applyTorqueImpulse(LVecBase3_to_btVector3(torque));
00233 }
00234 
00235 ////////////////////////////////////////////////////////////////////
00236 //     Function: BulletRigidBodyNode::apply_impulse
00237 //       Access: Published
00238 //  Description:
00239 ////////////////////////////////////////////////////////////////////
00240 void BulletRigidBodyNode::
00241 apply_impulse(const LVector3 &impulse, const LPoint3 &pos) {
00242 
00243   nassertv_always(!impulse.is_nan());
00244   nassertv_always(!pos.is_nan());
00245 
00246   _rigid->applyImpulse(LVecBase3_to_btVector3(impulse),
00247                        LVecBase3_to_btVector3(pos));
00248 }
00249 
00250 ////////////////////////////////////////////////////////////////////
00251 //     Function: BulletRigidBodyNode::apply_central_impulse
00252 //       Access: Published
00253 //  Description:
00254 ////////////////////////////////////////////////////////////////////
00255 void BulletRigidBodyNode::
00256 apply_central_impulse(const LVector3 &impulse) {
00257 
00258   nassertv_always(!impulse.is_nan());
00259 
00260   _rigid->applyCentralImpulse(LVecBase3_to_btVector3(impulse));
00261 }
00262 
00263 ////////////////////////////////////////////////////////////////////
00264 //     Function: BulletRigidBodyNode::transform_changed
00265 //       Access: Protected
00266 //  Description:
00267 ////////////////////////////////////////////////////////////////////
00268 void BulletRigidBodyNode::
00269 transform_changed() {
00270 
00271   if (_sync_disable) return;
00272 
00273   NodePath np = NodePath::any_path((PandaNode *)this);
00274   CPT(TransformState) ts = np.get_net_transform();
00275 
00276   LMatrix4 m_sync = _sync->get_mat();
00277   LMatrix4 m_ts = ts->get_mat();
00278 
00279   if (!m_sync.almost_equal(m_ts)) {
00280     _sync = ts;
00281 
00282     btTransform trans = TransformState_to_btTrans(ts);
00283     _rigid->setCenterOfMassTransform(trans);
00284 
00285     if (ts->has_scale()) {
00286       LVecBase3 scale = ts->get_scale();
00287       if (!scale.almost_equal(LVecBase3(1.0f, 1.0f, 1.0f))) {
00288         for (int i=0; i<get_num_shapes(); i++) {
00289           PT(BulletShape) shape = _shapes[i];
00290           shape->set_local_scale(scale);
00291         }
00292 
00293         shape_changed();
00294       }
00295     }
00296 
00297     // Activate the body if it has been sleeping
00298     if (!_rigid->isActive()) {
00299       _rigid->activate(true);
00300     }
00301   }
00302 }
00303 
00304 ////////////////////////////////////////////////////////////////////
00305 //     Function: BulletRigidBodyNode::sync_p2b
00306 //       Access: Public
00307 //  Description:
00308 ////////////////////////////////////////////////////////////////////
00309 void BulletRigidBodyNode::
00310 sync_p2b() {
00311 
00312   transform_changed();
00313 }
00314 
00315 ////////////////////////////////////////////////////////////////////
00316 //     Function: BulletRigidBodyNode::sync_b2p
00317 //       Access: Public
00318 //  Description:
00319 ////////////////////////////////////////////////////////////////////
00320 void BulletRigidBodyNode::
00321 sync_b2p() {
00322 
00323   NodePath np = NodePath::any_path((PandaNode *)this);
00324   LVecBase3 scale = np.get_net_transform()->get_scale();
00325 
00326   btTransform trans = _rigid->getWorldTransform();
00327   CPT(TransformState) ts = btTrans_to_TransformState(trans, scale);
00328 
00329   LMatrix4 m_sync = _sync->get_mat();
00330   LMatrix4 m_ts = ts->get_mat();
00331 
00332   if (!m_sync.almost_equal(m_ts)) {
00333     _sync = ts;
00334     _sync_disable = true;
00335     np.set_transform(NodePath(), ts);
00336     _sync_disable = false;
00337   }
00338 }
00339 
00340 ////////////////////////////////////////////////////////////////////
00341 //     Function: BulletRigidBodyNode::get_linear_velocity
00342 //       Access: Published
00343 //  Description:
00344 ////////////////////////////////////////////////////////////////////
00345 LVector3 BulletRigidBodyNode::
00346 get_linear_velocity() const {
00347 
00348   return btVector3_to_LVector3(_rigid->getLinearVelocity());
00349 }
00350 
00351 ////////////////////////////////////////////////////////////////////
00352 //     Function: BulletRigidBodyNode::get_angular_velocity
00353 //       Access: Published
00354 //  Description:
00355 ////////////////////////////////////////////////////////////////////
00356 LVector3 BulletRigidBodyNode::
00357 get_angular_velocity() const {
00358 
00359   return btVector3_to_LVector3(_rigid->getAngularVelocity());
00360 }
00361 
00362 ////////////////////////////////////////////////////////////////////
00363 //     Function: BulletRigidBodyNode::set_linear_velocity
00364 //       Access: Published
00365 //  Description:
00366 ////////////////////////////////////////////////////////////////////
00367 void BulletRigidBodyNode::
00368 set_linear_velocity(const LVector3 &velocity) {
00369 
00370   nassertv_always(!velocity.is_nan());
00371 
00372   _rigid->setLinearVelocity(LVecBase3_to_btVector3(velocity));
00373 }
00374 
00375 ////////////////////////////////////////////////////////////////////
00376 //     Function: BulletRigidBodyNode::set_angular_velocity
00377 //       Access: Published
00378 //  Description:
00379 ////////////////////////////////////////////////////////////////////
00380 void BulletRigidBodyNode::
00381 set_angular_velocity(const LVector3 &velocity) {
00382 
00383   nassertv_always(!velocity.is_nan());
00384 
00385   _rigid->setAngularVelocity(LVecBase3_to_btVector3(velocity));
00386 }
00387 
00388 ////////////////////////////////////////////////////////////////////
00389 //     Function: BulletRigidBodyNode::clear_forces
00390 //       Access: Published
00391 //  Description:
00392 ////////////////////////////////////////////////////////////////////
00393 void BulletRigidBodyNode::
00394 clear_forces() {
00395 
00396   _rigid->clearForces();
00397 }
00398 
00399 ////////////////////////////////////////////////////////////////////
00400 //     Function: BulletRigidBodyNode::get_linear_sleep_threshold
00401 //       Access: Published
00402 //  Description:
00403 ////////////////////////////////////////////////////////////////////
00404 PN_stdfloat BulletRigidBodyNode::
00405 get_linear_sleep_threshold() const {
00406 
00407   return _rigid->getLinearSleepingThreshold();
00408 }
00409 
00410 ////////////////////////////////////////////////////////////////////
00411 //     Function: BulletRigidBodyNode::get_angular_sleep_threshold
00412 //       Access: Published
00413 //  Description:
00414 ////////////////////////////////////////////////////////////////////
00415 PN_stdfloat BulletRigidBodyNode::
00416 get_angular_sleep_threshold() const {
00417 
00418   return _rigid->getAngularSleepingThreshold();
00419 }
00420 
00421 ////////////////////////////////////////////////////////////////////
00422 //     Function: BulletRigidBodyNode::set_linear_sleep_threshold
00423 //       Access: Published
00424 //  Description:
00425 ////////////////////////////////////////////////////////////////////
00426 void BulletRigidBodyNode::
00427 set_linear_sleep_threshold(PN_stdfloat threshold) {
00428 
00429   _rigid->setSleepingThresholds(threshold, _rigid->getAngularSleepingThreshold());
00430 }
00431 
00432 ////////////////////////////////////////////////////////////////////
00433 //     Function: BulletRigidBodyNode::set_angular_sleep_threshold
00434 //       Access: Published
00435 //  Description:
00436 ////////////////////////////////////////////////////////////////////
00437 void BulletRigidBodyNode::
00438 set_angular_sleep_threshold(PN_stdfloat threshold) {
00439 
00440   _rigid->setSleepingThresholds(_rigid->getLinearSleepingThreshold(), threshold);
00441 }
00442 
00443 ////////////////////////////////////////////////////////////////////
00444 //     Function: BulletRigidBodyNode::set_gravity
00445 //       Access: Published
00446 //  Description:
00447 ////////////////////////////////////////////////////////////////////
00448 void BulletRigidBodyNode::
00449 set_gravity(const LVector3 &gravity) {
00450 
00451   nassertv_always(!gravity.is_nan());
00452 
00453   _rigid->setGravity(LVecBase3_to_btVector3(gravity));
00454 }
00455 
00456 ////////////////////////////////////////////////////////////////////
00457 //     Function: BulletRigidBodyNode::get_gravity
00458 //       Access: Published
00459 //  Description:
00460 ////////////////////////////////////////////////////////////////////
00461 LVector3 BulletRigidBodyNode::
00462 get_gravity() const {
00463 
00464   return btVector3_to_LVector3(_rigid->getGravity());
00465 }
00466 
00467 ////////////////////////////////////////////////////////////////////
00468 //     Function: BulletRigidBodyNode::set_linear_factor
00469 //       Access: Published
00470 //  Description:
00471 ////////////////////////////////////////////////////////////////////
00472 void BulletRigidBodyNode::
00473 set_linear_factor(const LVector3 &factor) {
00474 
00475   _rigid->setLinearFactor(LVecBase3_to_btVector3(factor));
00476 }
00477 
00478 ////////////////////////////////////////////////////////////////////
00479 //     Function: BulletRigidBodyNode::set_angular_factor
00480 //       Access: Published
00481 //  Description:
00482 ////////////////////////////////////////////////////////////////////
00483 void BulletRigidBodyNode::
00484 set_angular_factor(const LVector3 &factor) {
00485 
00486   _rigid->setAngularFactor(LVecBase3_to_btVector3(factor));
00487 }
00488 
00489 ////////////////////////////////////////////////////////////////////
00490 //     Function: BulletRigidBodyNode::MotionState::getWorldTransform
00491 //       Access: Public
00492 //  Description: 
00493 ////////////////////////////////////////////////////////////////////
00494 void BulletRigidBodyNode::MotionState::
00495 getWorldTransform(btTransform &trans) const {
00496 
00497   trans = TransformState_to_btTrans(_sync);
00498 }
00499 
00500 ////////////////////////////////////////////////////////////////////
00501 //     Function: BulletRigidBodyNode::MotionState::setWorldTransform
00502 //       Access: Public
00503 //  Description: 
00504 ////////////////////////////////////////////////////////////////////
00505 void BulletRigidBodyNode::MotionState::
00506 setWorldTransform(const btTransform &trans) {
00507 
00508 }
00509 
 All Classes Functions Variables Enumerations