00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of the OGRE Reference Application, a layer built 00004 on top of OGRE(Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright © 2000-2002 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 00026 #include "OgreRefAppApplicationObject.h" 00027 #include "OgreRefAppWorld.h" 00028 #include "ode/collision.h" 00029 #include "OgreControllerManager.h" 00030 #include "OgreStringConverter.h" 00031 #include "OgreRoot.h" 00032 00033 namespace OgreRefApp 00034 { 00035 //------------------------------------------------------------------------- 00036 ApplicationObject::ApplicationObject(const String& name) 00037 { 00038 mSceneNode = 0; 00039 mEntity = 0; 00040 mOdeBody = 0; 00041 mDynamicsEnabled = false; 00042 mReenableIfInteractedWith = false; 00043 mCollisionEnabled = true; 00044 mSoftness = 0.0; 00045 mBounceCoeffRestitution = 0; 00046 mBounceVelocityThreshold = 0.1; 00047 setFriction(Math::POS_INFINITY); 00048 dMassSetZero(&mMass); 00049 00050 mDisableTimeEnd = 0; 00051 mDisableTime = 3000.0f; // millisenconds 00052 mAngularVelDisableThreshold = 1.0f; 00053 mLinearVelDisableThreshold = 1.0f; 00054 00055 00056 00057 } 00058 //------------------------------------------------------------------------- 00059 ApplicationObject::~ApplicationObject() 00060 { 00061 SceneManager* sm = World::getSingleton().getSceneManager(); 00062 if (mSceneNode) 00063 { 00064 sm->destroySceneNode(mSceneNode->getName()); 00065 mSceneNode = 0; 00066 } 00067 00068 // TODO destroy entity 00069 00070 // Destroy mass 00071 if (mOdeBody) 00072 { 00073 delete mOdeBody; 00074 mOdeBody = 0; 00075 } 00076 00077 // Destroy collision proxies 00078 CollisionProxyList::iterator i, iend; 00079 iend = mCollisionProxies.end(); 00080 for (i = mCollisionProxies.begin(); i != iend; ++i) 00081 { 00082 delete (*i); 00083 } 00084 00085 00086 00087 } 00088 //------------------------------------------------------------------------- 00089 void ApplicationObject::setPosition(const Vector3& vec) 00090 { 00091 setPosition(vec.x, vec.y, vec.z); 00092 } 00093 //------------------------------------------------------------------------- 00094 void ApplicationObject::setPosition(Real x, Real y, Real z) 00095 { 00096 mSceneNode->setPosition(x, y, z); 00097 if (isDynamicsEnabled() && mOdeBody) 00098 mOdeBody->setPosition(x, y, z); 00099 updateCollisionProxies(); 00100 } 00101 //------------------------------------------------------------------------- 00102 void ApplicationObject::setOrientation(const Quaternion& orientation) 00103 { 00104 mSceneNode->setOrientation(orientation); 00105 if (isDynamicsEnabled() && mOdeBody) 00106 { 00107 dReal dquat[4] = {orientation.w, orientation.x, orientation.y, orientation.z }; 00108 mOdeBody->setQuaternion(dquat); 00109 } 00110 updateCollisionProxies(); 00111 } 00112 //------------------------------------------------------------------------- 00113 const Vector3& ApplicationObject::getPosition(void) 00114 { 00115 return mSceneNode->getPosition(); 00116 } 00117 //------------------------------------------------------------------------- 00118 const Quaternion& ApplicationObject::getOrientation(void) 00119 { 00120 return mSceneNode->getOrientation(); 00121 } 00122 //------------------------------------------------------------------------- 00123 void ApplicationObject::setDynamicsDisableThreshold(Real linearSq, 00124 Real angularSq, Real overTime) 00125 { 00126 mLinearVelDisableThreshold = linearSq; 00127 mAngularVelDisableThreshold = angularSq; 00128 mDisableTime = overTime * 1000; 00129 } 00130 //------------------------------------------------------------------------- 00131 void ApplicationObject::_updateFromDynamics() 00132 { 00133 if (!mOdeBody) 00134 { 00135 return; 00136 } 00137 // Update dynamics enabled flag from dynamics (may have been reenabled) 00138 if (mReenableIfInteractedWith) 00139 { 00140 mDynamicsEnabled = mOdeBody->isEnabled() == 0 ? false : true; 00141 } 00142 00143 if (mDynamicsEnabled) 00144 { 00145 // Get position & rotation from ODE 00146 const dReal* pos = mOdeBody->getPosition(); 00147 const dReal* quat = mOdeBody->getQuaternion(); 00148 00149 mSceneNode->setPosition((Real)pos[0], (Real)pos[1], (Real)pos[2]); 00150 mSceneNode->setOrientation((Real)quat[0], (Real)quat[1], 00151 (Real)quat[2], (Real)quat[3]); 00152 00153 updateCollisionProxies(); 00154 00155 // Check to see if object has stabilised, if so turn off dynamics 00156 // to save processor time 00157 // NB will be reenabled if interacted with 00158 00159 if (this->getLinearVelocity().squaredLength() <= mLinearVelDisableThreshold 00160 && this->getAngularVelocity().squaredLength() <= mAngularVelDisableThreshold) 00161 { 00162 if (mDisableTimeEnd > 0.0f) 00163 { 00164 // We're counting, check disable time 00165 if (Root::getSingleton().getTimer()->getMilliseconds() > mDisableTimeEnd) 00166 { 00167 this->setDynamicsEnabled(false, true); 00168 //LogManager::getSingleton().logMessage(mEntity->getName() + " disabled"); 00169 mDisableTimeEnd = 0.0f; 00170 } 00171 00172 } 00173 else 00174 { 00175 // We're not counting down yet, so start the count 00176 // NB is mDisableTime = 0 we never disable 00177 if (mDisableTime > 0) 00178 { 00179 mDisableTimeEnd = Root::getSingleton().getTimer()->getMilliseconds() + mDisableTime; 00180 //LogManager::getSingleton().logMessage("Starting countdown..."); 00181 } 00182 } 00183 } 00184 else 00185 { 00186 // We're still moving 00187 mDisableTimeEnd = 0.0f; 00188 } 00189 00190 } 00191 } 00192 //------------------------------------------------------------------------- 00193 bool ApplicationObject::isCollisionEnabled(void) 00194 { 00195 return mCollisionEnabled; 00196 } 00197 //------------------------------------------------------------------------- 00198 bool ApplicationObject::isDynamicsEnabled(void) 00199 { 00200 return (mDynamicsEnabled || mReenableIfInteractedWith); 00201 } 00202 //------------------------------------------------------------------------- 00203 void ApplicationObject::setCollisionEnabled(bool enabled) 00204 { 00205 mCollisionEnabled = enabled; 00206 setEntityQueryFlags(); 00207 } 00208 //------------------------------------------------------------------------- 00209 void ApplicationObject::setDynamicsEnabled(bool enabled, bool reEnableOnInteraction) 00210 { 00211 00212 mDynamicsEnabled = enabled; 00213 mReenableIfInteractedWith = reEnableOnInteraction; 00214 00215 // World must keep an eye on enabled or potentially reenabled objects 00216 World::getSingleton()._notifyDynamicsStateForObject(this, 00217 mDynamicsEnabled || mReenableIfInteractedWith); 00218 00219 if (mDynamicsEnabled) 00220 { 00221 // Ensure body is synced 00222 mOdeBody->enable(); 00223 } 00224 else 00225 { 00226 mOdeBody->disable(); 00227 } 00228 // Set properties 00229 if (mDynamicsEnabled || mReenableIfInteractedWith) 00230 { 00231 const Vector3& pos = getPosition(); 00232 mOdeBody->setPosition(pos.x, pos.y, pos.z); 00233 const Quaternion& q = getOrientation(); 00234 dReal dquat[4] = {q.w, q.x, q.y, q.z }; 00235 mOdeBody->setQuaternion(dquat); 00236 } 00237 } 00238 //------------------------------------------------------------------------- 00239 void ApplicationObject::addForce(const Vector3& direction, const Vector3& atPosition) 00240 { 00241 addForce(direction.x, direction.y, direction.z, 00242 atPosition.x, atPosition.y, atPosition.z); 00243 } 00244 //------------------------------------------------------------------------- 00245 void ApplicationObject::addForce(Real dir_x, Real dir_y, Real dir_z, 00246 Real pos_x, Real pos_y, Real pos_z) 00247 { 00248 assert (mOdeBody && "No dynamics body set up for this object"); 00249 mOdeBody->addRelForceAtRelPos(dir_x, dir_y, dir_z, 00250 pos_x, pos_y, pos_z); 00251 00252 } 00253 //------------------------------------------------------------------------- 00254 void ApplicationObject::addForceWorldSpace(const Vector3& direction, const Vector3& atPosition) 00255 { 00256 addForceWorldSpace(direction.x, direction.y, direction.z, 00257 atPosition.x, atPosition.y, atPosition.z); 00258 } 00259 //------------------------------------------------------------------------- 00260 void ApplicationObject::addForceWorldSpace(Real dir_x, Real dir_y, Real dir_z, 00261 Real pos_x, Real pos_y, Real pos_z) 00262 { 00263 assert (mOdeBody && "No dynamics body set up for this object"); 00264 mOdeBody->addRelForceAtPos(dir_x, dir_y, dir_z, 00265 pos_x, pos_y, pos_z); 00266 } 00267 //------------------------------------------------------------------------- 00268 void ApplicationObject::addTorque(const Vector3& direction) 00269 { 00270 addTorque(direction.x, direction.y, direction.z); 00271 } 00272 //------------------------------------------------------------------------- 00273 void ApplicationObject::addTorque(Real x, Real y, Real z) 00274 { 00275 assert (mOdeBody && "No dynamics body set up for this object"); 00276 mOdeBody->addRelTorque(x, y, z); 00277 } 00278 //------------------------------------------------------------------------- 00279 void ApplicationObject::addTorqueWorldSpace(const Vector3& direction) 00280 { 00281 addTorqueWorldSpace(direction.x, direction.y, direction.z); 00282 } 00283 //------------------------------------------------------------------------- 00284 void ApplicationObject::addTorqueWorldSpace(Real x, Real y, Real z) 00285 { 00286 assert (mOdeBody && "No dynamics body set up for this object"); 00287 mOdeBody->addTorque(x, y, z); 00288 } 00289 //------------------------------------------------------------------------- 00290 SceneNode* ApplicationObject::getSceneNode(void) 00291 { 00292 return mSceneNode; 00293 } 00294 //------------------------------------------------------------------------- 00295 Entity* ApplicationObject::getEntity(void) 00296 { 00297 return mEntity; 00298 } 00299 //------------------------------------------------------------------------- 00300 dBody* ApplicationObject::getOdeBody(void) 00301 { 00302 if (isDynamicsEnabled()) 00303 { 00304 return mOdeBody; 00305 } 00306 else 00307 { 00308 // dynamics are disabled 00309 return 0; 00310 } 00311 } 00312 //------------------------------------------------------------------------- 00313 void ApplicationObject::updateCollisionProxies(void) 00314 { 00315 CollisionProxyList::iterator i, iend; 00316 iend = mCollisionProxies.end(); 00317 for (i = mCollisionProxies.begin(); i != iend; ++i) 00318 { 00319 // set from node 00320 const Vector3& pos = mSceneNode->getPosition(); 00321 dGeom* pProxy = *i; 00322 pProxy->setPosition(pos.x, pos.y, pos.z); 00323 const Quaternion& orientation = mSceneNode->getOrientation(); 00324 // Hmm, no setQuaternion on proxy 00325 // Do a conversion 00326 dReal dquat[4] = {orientation.w, orientation.x, orientation.y, orientation.z }; 00327 dMatrix3 dm3; 00328 memset(dm3, 0, sizeof(dMatrix3)); 00329 dQtoR(dquat, dm3); 00330 pProxy->setRotation(dm3); 00331 00332 } 00333 00334 } 00335 //------------------------------------------------------------------------- 00336 bool ApplicationObject::testCollide(ApplicationObject* otherObj) 00337 { 00338 bool collided = false; 00339 dContactGeom contactGeom; 00340 dGeom *o1, *o2; 00341 CollisionProxyList::const_iterator proxy1, proxy2, proxy1end, proxy2end; 00342 proxy1end = mCollisionProxies.end(); 00343 proxy2end = otherObj->mCollisionProxies.end(); 00344 00345 CollisionInfo collInfo; 00346 00347 for (proxy1 = mCollisionProxies.begin(); proxy1 != proxy1end; ++proxy1) 00348 { 00349 for (proxy2 = otherObj->mCollisionProxies.begin(); proxy2 != proxy2end; ++proxy2) 00350 { 00351 o1 = *proxy1; 00352 o2 = *proxy2; 00353 int numc = dCollide(o1->id(), o2->id(), 0, &contactGeom, sizeof(dContactGeom)); 00354 if (numc) 00355 { 00356 // Create contact joints if either object is dynamics simulated 00357 // If one is not, then sim will not affect it anyway, it will be fixed 00358 // However if one is enabled, we need the contact joint 00359 if (this->isDynamicsEnabled() || otherObj->isDynamicsEnabled()) 00360 { 00361 // We use the most agressive parameters from both objects for the contact 00362 dContact contact; 00363 Real bounce, velThresh, softness; 00364 // Use the highest coeff of restitution from both objects 00365 bounce = std::max(this->getBounceRestitutionValue(), 00366 otherObj->getBounceRestitutionValue()); 00367 // Use the lowest velocity threshold from both objects 00368 velThresh = std::min(this->getBounceVelocityThreshold(), 00369 otherObj->getBounceVelocityThreshold()); 00370 // Set flags 00371 contact.surface.mode = dContactBounce | dContactApprox1; 00372 contact.surface.bounce = bounce; 00373 contact.surface.bounce_vel = velThresh; 00374 00375 softness = this->getSoftness() + otherObj->getSoftness(); 00376 if (softness > 0) 00377 { 00378 contact.surface.mode |= dContactSoftCFM; 00379 contact.surface.soft_cfm = softness; 00380 } 00381 00382 // Set friction to min of 2 objects 00383 // Note that ODE dInfinity == Math::POS_INFINITY 00384 contact.surface.mu = std::min(this->getFriction(), otherObj->getFriction()); 00385 contact.surface.mu2 = 0; 00386 contact.geom = contactGeom; 00387 dContactJoint contactJoint( 00388 World::getSingleton().getOdeWorld()->id(), 00389 World::getSingleton().getOdeContactJointGroup()->id(), 00390 &contact); 00391 00392 // Get ODE bodies 00393 // May be null, if so use 0 (immovable) body ids 00394 dBody *b1, *b2; 00395 dBodyID bid1, bid2; 00396 bid1 = bid2 = 0; 00397 b1 = this->getOdeBody(); 00398 b2 = otherObj->getOdeBody(); 00399 if (b1) bid1 = b1->id(); 00400 if (b2) bid2 = b2->id(); 00401 contactJoint.attach(bid1, bid2); 00402 } 00403 00404 // Tell both objects about the collision 00405 collInfo.position.x = contactGeom.pos[0]; 00406 collInfo.position.y = contactGeom.pos[1]; 00407 collInfo.position.z = contactGeom.pos[2]; 00408 collInfo.normal.x = contactGeom.normal[0]; 00409 collInfo.normal.y = contactGeom.normal[1]; 00410 collInfo.normal.z = contactGeom.normal[2]; 00411 collInfo.penetrationDepth = contactGeom.depth; 00412 this->_notifyCollided(otherObj, collInfo); 00413 otherObj->_notifyCollided(this, collInfo); 00414 00415 00416 // set return 00417 collided = true; 00418 } 00419 } 00420 } 00421 return collided; 00422 00423 } 00424 //------------------------------------------------------------------------- 00425 bool ApplicationObject::testCollide(SceneQuery::WorldFragment* wf) 00426 { 00427 switch (wf->fragmentType) 00428 { 00429 case SceneQuery::WFT_NONE: 00430 return false; 00431 case SceneQuery::WFT_PLANE_BOUNDED_REGION: 00432 return testCollidePlaneBounds(wf); 00433 default: 00434 break; 00435 }; 00436 00437 // not handled 00438 return false; 00439 } 00440 //------------------------------------------------------------------------- 00441 bool ApplicationObject::testCollidePlaneBounds(SceneQuery::WorldFragment* wf) 00442 { 00443 bool collided = false; 00444 dContactGeom contactGeom; 00445 dGeom *obj; 00446 CollisionProxyList::const_iterator proxy, proxyend; 00447 proxyend = mCollisionProxies.end(); 00448 00449 std::list<Plane>::const_iterator pi, piend; 00450 piend = wf->planes->end(); 00451 00452 CollisionInfo collInfo; 00453 00454 for (proxy = mCollisionProxies.begin(); proxy != proxyend; ++proxy) 00455 { 00456 // Hack, simply collide against planes which is facing towards center 00457 // We can't do this properly without mesh collision 00458 obj = *proxy; 00459 Real maxdist = -1.0f; 00460 const Plane* bestPlane = 0; 00461 for (pi = wf->planes->begin(); pi != piend; ++pi) 00462 { 00463 const Plane *boundPlane = &(*pi); 00464 Real dist = boundPlane->getDistance(this->getPosition()); 00465 if (dist >= 0.0f) 00466 { 00467 dPlane odePlane(0, boundPlane->normal.x, boundPlane->normal.y, boundPlane->normal.z, 00468 -boundPlane->d); 00469 00470 int numc = dCollide(obj->id(), odePlane.id() , 0, &contactGeom, sizeof(dContactGeom)); 00471 if (numc) 00472 { 00473 // Create contact joints if object is dynamics simulated 00474 if (this->isDynamicsEnabled()) 00475 { 00476 // TODO: combine object parameters with WorldFragment physical properties 00477 dContact contact; 00478 // Set flags 00479 contact.surface.mode = dContactBounce | dContactApprox1; 00480 contact.surface.bounce = this->getBounceRestitutionValue(); 00481 contact.surface.bounce_vel = this->getBounceVelocityThreshold(); 00482 Real softness = this->getSoftness(); 00483 if (softness > 0) 00484 { 00485 contact.surface.mode |= dContactSoftCFM; 00486 contact.surface.soft_cfm = softness; 00487 } 00488 00489 // Set friction 00490 contact.surface.mu = this->getFriction(); 00491 contact.surface.mu2 = 0; 00492 contact.geom = contactGeom; 00493 dContactJoint contactJoint( 00494 World::getSingleton().getOdeWorld()->id(), 00495 World::getSingleton().getOdeContactJointGroup()->id(), 00496 &contact); 00497 00498 // Get ODE body,world fragment body is 0 clearly (immovable) 00499 dBody* body = this->getOdeBody(); 00500 dBodyID bid; 00501 bid = 0; 00502 if (body) bid = body->id(); 00503 contactJoint.attach(bid, 0); 00504 } 00505 00506 // Tell object about the collision 00507 collInfo.position.x = contactGeom.pos[0]; 00508 collInfo.position.y = contactGeom.pos[1]; 00509 collInfo.position.z = contactGeom.pos[2]; 00510 collInfo.normal.x = contactGeom.normal[0]; 00511 collInfo.normal.y = contactGeom.normal[1]; 00512 collInfo.normal.z = contactGeom.normal[2]; 00513 00514 // NB clamp the depth to compensate for crazy results 00515 collInfo.penetrationDepth = contactGeom.depth; 00516 //collInfo.penetrationDepth = std::max(collInfo.penetrationDepth, 00517 // this->getLinearVelocity().length()); 00518 this->_notifyCollided(wf, collInfo); 00519 00520 00521 // set return 00522 collided = true; 00523 } 00524 } 00525 } 00526 00527 } 00528 return collided; 00529 } 00530 //------------------------------------------------------------------------- 00531 void ApplicationObject::_notifyCollided(ApplicationObject* otherObj, 00532 const ApplicationObject::CollisionInfo& info) 00533 { 00534 // NB contacts for physics are not created here but in testCollide 00535 // Application subclasses should do their own respose here if required 00536 } 00537 //------------------------------------------------------------------------- 00538 void ApplicationObject::_notifyCollided(SceneQuery::WorldFragment* wf, 00539 const CollisionInfo& info) 00540 { 00541 // NB contacts for physics are not created here but in testCollide 00542 // Application subclasses should do their own respose here if required 00543 } 00544 //------------------------------------------------------------------------- 00545 void ApplicationObject::setBounceParameters(Real restitutionValue, 00546 Real velocityThreshold) 00547 { 00548 mBounceCoeffRestitution = restitutionValue; 00549 mBounceVelocityThreshold = velocityThreshold; 00550 } 00551 //------------------------------------------------------------------------- 00552 Real ApplicationObject::getBounceRestitutionValue(void) 00553 { 00554 return mBounceCoeffRestitution; 00555 } 00556 //------------------------------------------------------------------------- 00557 Real ApplicationObject::getBounceVelocityThreshold(void) 00558 { 00559 return mBounceVelocityThreshold; 00560 } 00561 //------------------------------------------------------------------------- 00562 void ApplicationObject::setSoftness(Real softness) 00563 { 00564 mSoftness = softness; 00565 } 00566 //------------------------------------------------------------------------- 00567 Real ApplicationObject::getSoftness(void) 00568 { 00569 return mSoftness; 00570 } 00571 //------------------------------------------------------------------------- 00572 void ApplicationObject::setFriction(Real friction) 00573 { 00574 if (friction == Math::POS_INFINITY) 00575 { 00576 mFriction = dInfinity; 00577 } 00578 else 00579 { 00580 mFriction = friction; 00581 } 00582 } 00583 //------------------------------------------------------------------------- 00584 Real ApplicationObject::getFriction(void) 00585 { 00586 return mFriction; 00587 } 00588 //------------------------------------------------------------------------- 00589 void ApplicationObject::setMassSphere(Real density, Real radius) 00590 { 00591 dMassSetSphere(&mMass, density, radius); 00592 mOdeBody->setMass(&mMass); 00593 } 00594 //------------------------------------------------------------------------- 00595 void ApplicationObject::setMassBox(Real density, const Vector3& dimensions, 00596 const Quaternion& orientation) 00597 { 00598 dMassSetBox(&mMass, density, dimensions.x, dimensions.y, dimensions.z); 00599 00600 Matrix3 m3; 00601 orientation.ToRotationMatrix(m3); 00602 dMatrix3 dm3; 00603 OgreToOde(m3, dm3); 00604 dMassRotate(&mMass, dm3); 00605 00606 mOdeBody->setMass(&mMass); 00607 00608 00609 } 00610 //------------------------------------------------------------------------- 00611 void ApplicationObject::setMassCappedCylinder(Real density, Real length, Real width, 00612 const Quaternion& orientation) 00613 { 00614 dMassSetCappedCylinder(&mMass, density, 3, width, length); 00615 00616 Matrix3 m3; 00617 orientation.ToRotationMatrix(m3); 00618 dMatrix3 dm3; 00619 OgreToOde(m3, dm3); 00620 dMassRotate(&mMass, dm3); 00621 00622 mOdeBody->setMass(&mMass); 00623 } 00624 //------------------------------------------------------------------------- 00625 void ApplicationObject::setMassExpert(Real mass, const Vector3 center, const Matrix3 inertia) 00626 { 00627 00628 mMass.mass = mass; 00629 mMass.c[0] = center.x; 00630 mMass.c[1] = center.y; 00631 mMass.c[2] = center.z; 00632 OgreToOde(inertia, mMass.I); 00633 00634 mOdeBody->setMass(&mMass); 00635 00636 } 00637 //------------------------------------------------------------------------- 00638 const dMass* ApplicationObject::getOdeMass(void) 00639 { 00640 return &mMass; 00641 } 00642 //------------------------------------------------------------------------- 00643 void ApplicationObject::setLinearVelocity(const Vector3& vel) 00644 { 00645 setLinearVelocity(vel.x, vel.y, vel.z); 00646 } 00647 //------------------------------------------------------------------------- 00648 void ApplicationObject::setLinearVelocity(Real x, Real y, Real z) 00649 { 00650 assert(mOdeBody && isDynamicsEnabled() && 00651 "Cannot set velocity on an object unless dynamics are enabled and" 00652 " an ODE body exists"); 00653 mOdeBody->setLinearVel(x, y, z); 00654 // Reenable if on trigger 00655 setDynamicsEnabled(true, true); 00656 } 00657 //------------------------------------------------------------------------- 00658 const Vector3& ApplicationObject::getLinearVelocity(void) 00659 { 00660 assert(mOdeBody && isDynamicsEnabled() && 00661 "Cannot get velocity on an object unless dynamics are enabled and" 00662 " an ODE body exists"); 00663 static Vector3 vel; 00664 const dReal* odeVel = mOdeBody->getLinearVel(); 00665 vel.x = odeVel[0]; 00666 vel.y = odeVel[1]; 00667 vel.z = odeVel[2]; 00668 return vel; 00669 00670 } 00671 //------------------------------------------------------------------------- 00672 const Vector3& ApplicationObject::getAngularVelocity(void) 00673 { 00674 assert(mOdeBody && isDynamicsEnabled() && 00675 "Cannot get velocity on an object unless dynamics are enabled and" 00676 " an ODE body exists"); 00677 static Vector3 vel; 00678 const dReal* odeVel = mOdeBody->getAngularVel(); 00679 vel.x = odeVel[0]; 00680 vel.y = odeVel[1]; 00681 vel.z = odeVel[2]; 00682 return vel; 00683 } 00684 //------------------------------------------------------------------------- 00685 void ApplicationObject::setAngularVelocity(const Vector3& vel) 00686 { 00687 setAngularVelocity(vel.x, vel.y, vel.z); 00688 } 00689 //------------------------------------------------------------------------- 00690 void ApplicationObject::setAngularVelocity(Real x, Real y, Real z) 00691 { 00692 assert(mOdeBody && isDynamicsEnabled() && 00693 "Cannot set velocity on an object unless dynamics are enabled and" 00694 " an ODE body exists"); 00695 mOdeBody->setAngularVel(x, y, z); 00696 // Reenable if on trigger 00697 setDynamicsEnabled(true, true); 00698 } 00699 //------------------------------------------------------------------------- 00700 void ApplicationObject::translate(const Vector3& d) 00701 { 00702 // Adjust position by rotation 00703 Vector3 newTrans = mSceneNode->getOrientation() * d; 00704 translateWorldSpace(newTrans); 00705 } 00706 //------------------------------------------------------------------------- 00707 void ApplicationObject::translate(Real x, Real y, Real z) 00708 { 00709 translate(Vector3(x, y, z)); 00710 } 00711 //------------------------------------------------------------------------- 00712 void ApplicationObject::translateWorldSpace(const Vector3& d) 00713 { 00714 setPosition(getPosition() + d); 00715 } 00716 //------------------------------------------------------------------------- 00717 void ApplicationObject::translateWorldSpace(Real x, Real y, Real z) 00718 { 00719 translateWorldSpace(Vector3(x, y, z)); 00720 } 00721 //------------------------------------------------------------------------- 00722 void ApplicationObject::roll(Real angleunits) 00723 { 00724 rotate(Vector3::UNIT_Z, angleunits); 00725 } 00726 //------------------------------------------------------------------------- 00727 void ApplicationObject::pitch(Real angleunits) 00728 { 00729 rotate(Vector3::UNIT_X, angleunits); 00730 } 00731 //------------------------------------------------------------------------- 00732 void ApplicationObject::yaw(Real angleunits) 00733 { 00734 rotate(Vector3::UNIT_Y, angleunits); 00735 } 00736 //------------------------------------------------------------------------- 00737 void ApplicationObject::rotate(const Vector3& axis, Real angleunits) 00738 { 00739 Quaternion q; 00740 q.FromAngleAxis(Math::AngleUnitsToRadians(angleunits),axis); 00741 rotate(q); 00742 } 00743 //------------------------------------------------------------------------- 00744 void ApplicationObject::rotate(const Quaternion& q) 00745 { 00746 setOrientation(getOrientation() * q); 00747 } 00748 //------------------------------------------------------------------------- 00749 void ApplicationObject::setEntityQueryFlags(void) 00750 { 00751 // Real basic query mask usage for now 00752 // collision enabled = 0xFFFFFFFF 00753 // collision disabled = 0x0 00754 if (mEntity) 00755 { 00756 mEntity->setQueryFlags( mCollisionEnabled ? 0xFFFFFFFF : 0 ); 00757 } 00758 } 00759 00760 00761 00762 } 00763
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:24 2004