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