1 | /* |
---|
2 | ----------------------------------------------------------------------------- |
---|
3 | This source file is part of the OGRE Reference Application, a layer built |
---|
4 | on top of OGRE(Object-oriented Graphics Rendering Engine) |
---|
5 | For the latest info, see http://www.ogre3d.org/ |
---|
6 | |
---|
7 | Copyright (c) 2000-2006 Torus Knot Software Ltd |
---|
8 | Also see acknowledgements in Readme.html |
---|
9 | |
---|
10 | This program is free software; you can redistribute it and/or modify it under |
---|
11 | the terms of the GNU Lesser General Public License as published by the Free Software |
---|
12 | Foundation; either version 2 of the License, or (at your option) any later |
---|
13 | version. |
---|
14 | |
---|
15 | This program is distributed in the hope that it will be useful, but WITHOUT |
---|
16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
---|
17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
---|
18 | |
---|
19 | You should have received a copy of the GNU Lesser General Public License along with |
---|
20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
---|
21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to |
---|
22 | http://www.gnu.org/copyleft/lesser.txt. |
---|
23 | |
---|
24 | You may alternatively use this source under the terms of a specific version of |
---|
25 | the OGRE Unrestricted License provided you have obtained such a license from |
---|
26 | Torus Knot Software Ltd. |
---|
27 | ----------------------------------------------------------------------------- |
---|
28 | */ |
---|
29 | |
---|
30 | #include "OgreRefAppApplicationObject.h" |
---|
31 | #include "OgreRefAppWorld.h" |
---|
32 | #include "ode/collision.h" |
---|
33 | #include "OgreControllerManager.h" |
---|
34 | #include "OgreStringConverter.h" |
---|
35 | #include "OgreRoot.h" |
---|
36 | |
---|
37 | namespace OgreRefApp |
---|
38 | { |
---|
39 | //------------------------------------------------------------------------- |
---|
40 | ApplicationObject::ApplicationObject(const String& name) |
---|
41 | { |
---|
42 | mSceneNode = 0; |
---|
43 | mEntity = 0; |
---|
44 | mOdeBody = 0; |
---|
45 | mDynamicsEnabled = false; |
---|
46 | mReenableIfInteractedWith = false; |
---|
47 | mCollisionEnabled = true; |
---|
48 | mSoftness = 0.0; |
---|
49 | mBounceCoeffRestitution = 0; |
---|
50 | mBounceVelocityThreshold = 0.1; |
---|
51 | setFriction(Math::POS_INFINITY); |
---|
52 | dMassSetZero(&mMass); |
---|
53 | |
---|
54 | mDisableTimeEnd = 0; |
---|
55 | mDisableTime = 3000.0f; // millisenconds |
---|
56 | mAngularVelDisableThreshold = 1.0f; |
---|
57 | mLinearVelDisableThreshold = 1.0f; |
---|
58 | |
---|
59 | |
---|
60 | |
---|
61 | } |
---|
62 | //------------------------------------------------------------------------- |
---|
63 | ApplicationObject::~ApplicationObject() |
---|
64 | { |
---|
65 | SceneManager* sm = World::getSingleton().getSceneManager(); |
---|
66 | if (mSceneNode) |
---|
67 | { |
---|
68 | sm->destroySceneNode(mSceneNode->getName()); |
---|
69 | mSceneNode = 0; |
---|
70 | } |
---|
71 | |
---|
72 | // TODO destroy entity |
---|
73 | |
---|
74 | // Destroy mass |
---|
75 | if (mOdeBody) |
---|
76 | { |
---|
77 | delete mOdeBody; |
---|
78 | mOdeBody = 0; |
---|
79 | } |
---|
80 | |
---|
81 | // Destroy collision proxies |
---|
82 | CollisionProxyList::iterator i, iend; |
---|
83 | iend = mCollisionProxies.end(); |
---|
84 | for (i = mCollisionProxies.begin(); i != iend; ++i) |
---|
85 | { |
---|
86 | delete (*i); |
---|
87 | } |
---|
88 | |
---|
89 | |
---|
90 | |
---|
91 | } |
---|
92 | //------------------------------------------------------------------------- |
---|
93 | void ApplicationObject::setPosition(const Vector3& vec) |
---|
94 | { |
---|
95 | setPosition(vec.x, vec.y, vec.z); |
---|
96 | } |
---|
97 | //------------------------------------------------------------------------- |
---|
98 | void ApplicationObject::setPosition(Real x, Real y, Real z) |
---|
99 | { |
---|
100 | mSceneNode->setPosition(x, y, z); |
---|
101 | if (isDynamicsEnabled() && mOdeBody) |
---|
102 | mOdeBody->setPosition(x, y, z); |
---|
103 | updateCollisionProxies(); |
---|
104 | } |
---|
105 | //------------------------------------------------------------------------- |
---|
106 | void ApplicationObject::setOrientation(const Quaternion& orientation) |
---|
107 | { |
---|
108 | mSceneNode->setOrientation(orientation); |
---|
109 | if (isDynamicsEnabled() && mOdeBody) |
---|
110 | { |
---|
111 | dReal dquat[4] = {orientation.w, orientation.x, orientation.y, orientation.z }; |
---|
112 | mOdeBody->setQuaternion(dquat); |
---|
113 | } |
---|
114 | updateCollisionProxies(); |
---|
115 | } |
---|
116 | //------------------------------------------------------------------------- |
---|
117 | const Vector3& ApplicationObject::getPosition(void) |
---|
118 | { |
---|
119 | return mSceneNode->getPosition(); |
---|
120 | } |
---|
121 | //------------------------------------------------------------------------- |
---|
122 | const Quaternion& ApplicationObject::getOrientation(void) |
---|
123 | { |
---|
124 | return mSceneNode->getOrientation(); |
---|
125 | } |
---|
126 | //------------------------------------------------------------------------- |
---|
127 | void ApplicationObject::setDynamicsDisableThreshold(Real linearSq, |
---|
128 | Real angularSq, Real overTime) |
---|
129 | { |
---|
130 | mLinearVelDisableThreshold = linearSq; |
---|
131 | mAngularVelDisableThreshold = angularSq; |
---|
132 | mDisableTime = overTime * 1000; |
---|
133 | } |
---|
134 | //------------------------------------------------------------------------- |
---|
135 | void ApplicationObject::_updateFromDynamics() |
---|
136 | { |
---|
137 | if (!mOdeBody) |
---|
138 | { |
---|
139 | return; |
---|
140 | } |
---|
141 | // Update dynamics enabled flag from dynamics (may have been reenabled) |
---|
142 | if (mReenableIfInteractedWith) |
---|
143 | { |
---|
144 | mDynamicsEnabled = mOdeBody->isEnabled() == 0 ? false : true; |
---|
145 | } |
---|
146 | |
---|
147 | if (mDynamicsEnabled) |
---|
148 | { |
---|
149 | // Get position & rotation from ODE |
---|
150 | const dReal* pos = mOdeBody->getPosition(); |
---|
151 | const dReal* quat = mOdeBody->getQuaternion(); |
---|
152 | |
---|
153 | mSceneNode->setPosition((Real)pos[0], (Real)pos[1], (Real)pos[2]); |
---|
154 | mSceneNode->setOrientation((Real)quat[0], (Real)quat[1], |
---|
155 | (Real)quat[2], (Real)quat[3]); |
---|
156 | |
---|
157 | updateCollisionProxies(); |
---|
158 | |
---|
159 | // Check to see if object has stabilised, if so turn off dynamics |
---|
160 | // to save processor time |
---|
161 | // NB will be reenabled if interacted with |
---|
162 | |
---|
163 | if (this->getLinearVelocity().squaredLength() <= mLinearVelDisableThreshold |
---|
164 | && this->getAngularVelocity().squaredLength() <= mAngularVelDisableThreshold) |
---|
165 | { |
---|
166 | if (mDisableTimeEnd > 0.0f) |
---|
167 | { |
---|
168 | // We're counting, check disable time |
---|
169 | if (Root::getSingleton().getTimer()->getMilliseconds() > mDisableTimeEnd) |
---|
170 | { |
---|
171 | this->setDynamicsEnabled(false, true); |
---|
172 | //LogManager::getSingleton().logMessage(mEntity->getName() + " disabled"); |
---|
173 | mDisableTimeEnd = 0.0f; |
---|
174 | } |
---|
175 | |
---|
176 | } |
---|
177 | else |
---|
178 | { |
---|
179 | // We're not counting down yet, so start the count |
---|
180 | // NB is mDisableTime = 0 we never disable |
---|
181 | if (mDisableTime > 0) |
---|
182 | { |
---|
183 | mDisableTimeEnd = Root::getSingleton().getTimer()->getMilliseconds() + mDisableTime; |
---|
184 | //LogManager::getSingleton().logMessage("Starting countdown..."); |
---|
185 | } |
---|
186 | } |
---|
187 | } |
---|
188 | else |
---|
189 | { |
---|
190 | // We're still moving |
---|
191 | mDisableTimeEnd = 0.0f; |
---|
192 | } |
---|
193 | |
---|
194 | } |
---|
195 | } |
---|
196 | //------------------------------------------------------------------------- |
---|
197 | bool ApplicationObject::isCollisionEnabled(void) |
---|
198 | { |
---|
199 | return mCollisionEnabled; |
---|
200 | } |
---|
201 | //------------------------------------------------------------------------- |
---|
202 | bool ApplicationObject::isDynamicsEnabled(void) |
---|
203 | { |
---|
204 | return (mDynamicsEnabled || mReenableIfInteractedWith); |
---|
205 | } |
---|
206 | //------------------------------------------------------------------------- |
---|
207 | void ApplicationObject::setCollisionEnabled(bool enabled) |
---|
208 | { |
---|
209 | mCollisionEnabled = enabled; |
---|
210 | setEntityQueryFlags(); |
---|
211 | } |
---|
212 | //------------------------------------------------------------------------- |
---|
213 | void ApplicationObject::setDynamicsEnabled(bool enabled, bool reEnableOnInteraction) |
---|
214 | { |
---|
215 | |
---|
216 | mDynamicsEnabled = enabled; |
---|
217 | mReenableIfInteractedWith = reEnableOnInteraction; |
---|
218 | |
---|
219 | // World must keep an eye on enabled or potentially reenabled objects |
---|
220 | World::getSingleton()._notifyDynamicsStateForObject(this, |
---|
221 | mDynamicsEnabled || mReenableIfInteractedWith); |
---|
222 | |
---|
223 | if (mDynamicsEnabled) |
---|
224 | { |
---|
225 | // Ensure body is synced |
---|
226 | mOdeBody->enable(); |
---|
227 | } |
---|
228 | else if (mOdeBody) |
---|
229 | { |
---|
230 | mOdeBody->disable(); |
---|
231 | } |
---|
232 | // Set properties |
---|
233 | if (mDynamicsEnabled || mReenableIfInteractedWith) |
---|
234 | { |
---|
235 | const Vector3& pos = getPosition(); |
---|
236 | mOdeBody->setPosition(pos.x, pos.y, pos.z); |
---|
237 | const Quaternion& q = getOrientation(); |
---|
238 | dReal dquat[4] = {q.w, q.x, q.y, q.z }; |
---|
239 | mOdeBody->setQuaternion(dquat); |
---|
240 | } |
---|
241 | } |
---|
242 | //------------------------------------------------------------------------- |
---|
243 | void ApplicationObject::addForce(const Vector3& direction, const Vector3& atPosition) |
---|
244 | { |
---|
245 | addForce(direction.x, direction.y, direction.z, |
---|
246 | atPosition.x, atPosition.y, atPosition.z); |
---|
247 | } |
---|
248 | //------------------------------------------------------------------------- |
---|
249 | void ApplicationObject::addForce(Real dir_x, Real dir_y, Real dir_z, |
---|
250 | Real pos_x, Real pos_y, Real pos_z) |
---|
251 | { |
---|
252 | assert (mOdeBody && "No dynamics body set up for this object"); |
---|
253 | mOdeBody->addRelForceAtRelPos(dir_x, dir_y, dir_z, |
---|
254 | pos_x, pos_y, pos_z); |
---|
255 | |
---|
256 | } |
---|
257 | //------------------------------------------------------------------------- |
---|
258 | void ApplicationObject::addForceWorldSpace(const Vector3& direction, const Vector3& atPosition) |
---|
259 | { |
---|
260 | addForceWorldSpace(direction.x, direction.y, direction.z, |
---|
261 | atPosition.x, atPosition.y, atPosition.z); |
---|
262 | } |
---|
263 | //------------------------------------------------------------------------- |
---|
264 | void ApplicationObject::addForceWorldSpace(Real dir_x, Real dir_y, Real dir_z, |
---|
265 | Real pos_x, Real pos_y, Real pos_z) |
---|
266 | { |
---|
267 | assert (mOdeBody && "No dynamics body set up for this object"); |
---|
268 | mOdeBody->addForceAtPos(dir_x, dir_y, dir_z, |
---|
269 | pos_x, pos_y, pos_z); |
---|
270 | } |
---|
271 | //------------------------------------------------------------------------- |
---|
272 | void ApplicationObject::addTorque(const Vector3& direction) |
---|
273 | { |
---|
274 | addTorque(direction.x, direction.y, direction.z); |
---|
275 | } |
---|
276 | //------------------------------------------------------------------------- |
---|
277 | void ApplicationObject::addTorque(Real x, Real y, Real z) |
---|
278 | { |
---|
279 | assert (mOdeBody && "No dynamics body set up for this object"); |
---|
280 | mOdeBody->addRelTorque(x, y, z); |
---|
281 | } |
---|
282 | //------------------------------------------------------------------------- |
---|
283 | void ApplicationObject::addTorqueWorldSpace(const Vector3& direction) |
---|
284 | { |
---|
285 | addTorqueWorldSpace(direction.x, direction.y, direction.z); |
---|
286 | } |
---|
287 | //------------------------------------------------------------------------- |
---|
288 | void ApplicationObject::addTorqueWorldSpace(Real x, Real y, Real z) |
---|
289 | { |
---|
290 | assert (mOdeBody && "No dynamics body set up for this object"); |
---|
291 | mOdeBody->addTorque(x, y, z); |
---|
292 | } |
---|
293 | //------------------------------------------------------------------------- |
---|
294 | SceneNode* ApplicationObject::getSceneNode(void) |
---|
295 | { |
---|
296 | return mSceneNode; |
---|
297 | } |
---|
298 | //------------------------------------------------------------------------- |
---|
299 | Entity* ApplicationObject::getEntity(void) |
---|
300 | { |
---|
301 | return mEntity; |
---|
302 | } |
---|
303 | //------------------------------------------------------------------------- |
---|
304 | dBody* ApplicationObject::getOdeBody(void) |
---|
305 | { |
---|
306 | if (isDynamicsEnabled()) |
---|
307 | { |
---|
308 | return mOdeBody; |
---|
309 | } |
---|
310 | else |
---|
311 | { |
---|
312 | // dynamics are disabled |
---|
313 | return 0; |
---|
314 | } |
---|
315 | } |
---|
316 | //------------------------------------------------------------------------- |
---|
317 | void ApplicationObject::updateCollisionProxies(void) |
---|
318 | { |
---|
319 | CollisionProxyList::iterator i, iend; |
---|
320 | iend = mCollisionProxies.end(); |
---|
321 | for (i = mCollisionProxies.begin(); i != iend; ++i) |
---|
322 | { |
---|
323 | // set from node |
---|
324 | const Vector3& pos = mSceneNode->getPosition(); |
---|
325 | dGeom* pProxy = *i; |
---|
326 | pProxy->setPosition(pos.x, pos.y, pos.z); |
---|
327 | const Quaternion& orientation = mSceneNode->getOrientation(); |
---|
328 | // Hmm, no setQuaternion on proxy |
---|
329 | // Do a conversion |
---|
330 | dReal dquat[4] = {orientation.w, orientation.x, orientation.y, orientation.z }; |
---|
331 | dMatrix3 dm3; |
---|
332 | memset(dm3, 0, sizeof(dMatrix3)); |
---|
333 | dQtoR(dquat, dm3); |
---|
334 | pProxy->setRotation(dm3); |
---|
335 | |
---|
336 | } |
---|
337 | |
---|
338 | } |
---|
339 | //------------------------------------------------------------------------- |
---|
340 | bool ApplicationObject::testCollide(ApplicationObject* otherObj) |
---|
341 | { |
---|
342 | bool collided = false; |
---|
343 | dContactGeom contactGeom; |
---|
344 | dGeom *o1, *o2; |
---|
345 | CollisionProxyList::const_iterator proxy1, proxy2, proxy1end, proxy2end; |
---|
346 | proxy1end = mCollisionProxies.end(); |
---|
347 | proxy2end = otherObj->mCollisionProxies.end(); |
---|
348 | |
---|
349 | CollisionInfo collInfo; |
---|
350 | |
---|
351 | for (proxy1 = mCollisionProxies.begin(); proxy1 != proxy1end; ++proxy1) |
---|
352 | { |
---|
353 | for (proxy2 = otherObj->mCollisionProxies.begin(); proxy2 != proxy2end; ++proxy2) |
---|
354 | { |
---|
355 | o1 = *proxy1; |
---|
356 | o2 = *proxy2; |
---|
357 | int numc = dCollide(o1->id(), o2->id(), 0, &contactGeom, sizeof(dContactGeom)); |
---|
358 | if (numc) |
---|
359 | { |
---|
360 | // Create contact joints if either object is dynamics simulated |
---|
361 | // If one is not, then sim will not affect it anyway, it will be fixed |
---|
362 | // However if one is enabled, we need the contact joint |
---|
363 | if (this->isDynamicsEnabled() || otherObj->isDynamicsEnabled()) |
---|
364 | { |
---|
365 | // We use the most agressive parameters from both objects for the contact |
---|
366 | dContact contact; |
---|
367 | Real bounce, velThresh, softness; |
---|
368 | // Use the highest coeff of restitution from both objects |
---|
369 | bounce = std::max(this->getBounceRestitutionValue(), |
---|
370 | otherObj->getBounceRestitutionValue()); |
---|
371 | // Use the lowest velocity threshold from both objects |
---|
372 | velThresh = std::min(this->getBounceVelocityThreshold(), |
---|
373 | otherObj->getBounceVelocityThreshold()); |
---|
374 | // Set flags |
---|
375 | contact.surface.mode = dContactBounce | dContactApprox1; |
---|
376 | contact.surface.bounce = bounce; |
---|
377 | contact.surface.bounce_vel = velThresh; |
---|
378 | |
---|
379 | softness = this->getSoftness() + otherObj->getSoftness(); |
---|
380 | if (softness > 0) |
---|
381 | { |
---|
382 | contact.surface.mode |= dContactSoftCFM; |
---|
383 | contact.surface.soft_cfm = softness; |
---|
384 | } |
---|
385 | |
---|
386 | // Set friction to min of 2 objects |
---|
387 | // Note that ODE dInfinity == Math::POS_INFINITY |
---|
388 | contact.surface.mu = std::min(this->getFriction(), otherObj->getFriction()); |
---|
389 | contact.surface.mu2 = 0; |
---|
390 | contact.geom = contactGeom; |
---|
391 | dContactJoint contactJoint( |
---|
392 | World::getSingleton().getOdeWorld()->id(), |
---|
393 | World::getSingleton().getOdeContactJointGroup()->id(), |
---|
394 | &contact); |
---|
395 | |
---|
396 | // Get ODE bodies |
---|
397 | // May be null, if so use 0 (immovable) body ids |
---|
398 | dBody *b1, *b2; |
---|
399 | dBodyID bid1, bid2; |
---|
400 | bid1 = bid2 = 0; |
---|
401 | b1 = this->getOdeBody(); |
---|
402 | b2 = otherObj->getOdeBody(); |
---|
403 | if (b1) bid1 = b1->id(); |
---|
404 | if (b2) bid2 = b2->id(); |
---|
405 | contactJoint.attach(bid1, bid2); |
---|
406 | } |
---|
407 | |
---|
408 | // Tell both objects about the collision |
---|
409 | collInfo.position.x = contactGeom.pos[0]; |
---|
410 | collInfo.position.y = contactGeom.pos[1]; |
---|
411 | collInfo.position.z = contactGeom.pos[2]; |
---|
412 | collInfo.normal.x = contactGeom.normal[0]; |
---|
413 | collInfo.normal.y = contactGeom.normal[1]; |
---|
414 | collInfo.normal.z = contactGeom.normal[2]; |
---|
415 | collInfo.penetrationDepth = contactGeom.depth; |
---|
416 | this->_notifyCollided(otherObj, collInfo); |
---|
417 | otherObj->_notifyCollided(this, collInfo); |
---|
418 | |
---|
419 | |
---|
420 | // set return |
---|
421 | collided = true; |
---|
422 | } |
---|
423 | } |
---|
424 | } |
---|
425 | return collided; |
---|
426 | |
---|
427 | } |
---|
428 | //------------------------------------------------------------------------- |
---|
429 | bool ApplicationObject::testCollide(SceneQuery::WorldFragment* wf) |
---|
430 | { |
---|
431 | switch (wf->fragmentType) |
---|
432 | { |
---|
433 | case SceneQuery::WFT_NONE: |
---|
434 | return false; |
---|
435 | case SceneQuery::WFT_PLANE_BOUNDED_REGION: |
---|
436 | return testCollidePlaneBounds(wf); |
---|
437 | default: |
---|
438 | break; |
---|
439 | }; |
---|
440 | |
---|
441 | // not handled |
---|
442 | return false; |
---|
443 | } |
---|
444 | //------------------------------------------------------------------------- |
---|
445 | bool ApplicationObject::testCollidePlaneBounds(SceneQuery::WorldFragment* wf) |
---|
446 | { |
---|
447 | bool collided = false; |
---|
448 | dContactGeom contactGeom; |
---|
449 | dGeom *obj; |
---|
450 | CollisionProxyList::const_iterator proxy, proxyend; |
---|
451 | proxyend = mCollisionProxies.end(); |
---|
452 | |
---|
453 | std::list<Plane>::const_iterator pi, piend; |
---|
454 | piend = wf->planes->end(); |
---|
455 | |
---|
456 | CollisionInfo collInfo; |
---|
457 | |
---|
458 | for (proxy = mCollisionProxies.begin(); proxy != proxyend; ++proxy) |
---|
459 | { |
---|
460 | // Hack, simply collide against planes which is facing towards center |
---|
461 | // We can't do this properly without mesh collision |
---|
462 | obj = *proxy; |
---|
463 | Real maxdist = -1.0f; |
---|
464 | const Plane* bestPlane = 0; |
---|
465 | for (pi = wf->planes->begin(); pi != piend; ++pi) |
---|
466 | { |
---|
467 | const Plane *boundPlane = &(*pi); |
---|
468 | Real dist = boundPlane->getDistance(this->getPosition()); |
---|
469 | if (dist >= 0.0f) |
---|
470 | { |
---|
471 | dPlane odePlane(0, boundPlane->normal.x, boundPlane->normal.y, boundPlane->normal.z, |
---|
472 | -boundPlane->d); |
---|
473 | |
---|
474 | int numc = dCollide(obj->id(), odePlane.id() , 0, &contactGeom, sizeof(dContactGeom)); |
---|
475 | if (numc) |
---|
476 | { |
---|
477 | // Create contact joints if object is dynamics simulated |
---|
478 | if (this->isDynamicsEnabled()) |
---|
479 | { |
---|
480 | // TODO: combine object parameters with WorldFragment physical properties |
---|
481 | dContact contact; |
---|
482 | // Set flags |
---|
483 | contact.surface.mode = dContactBounce | dContactApprox1; |
---|
484 | contact.surface.bounce = this->getBounceRestitutionValue(); |
---|
485 | contact.surface.bounce_vel = this->getBounceVelocityThreshold(); |
---|
486 | Real softness = this->getSoftness(); |
---|
487 | if (softness > 0) |
---|
488 | { |
---|
489 | contact.surface.mode |= dContactSoftCFM; |
---|
490 | contact.surface.soft_cfm = softness; |
---|
491 | } |
---|
492 | |
---|
493 | // Set friction |
---|
494 | contact.surface.mu = this->getFriction(); |
---|
495 | contact.surface.mu2 = 0; |
---|
496 | contact.geom = contactGeom; |
---|
497 | dContactJoint contactJoint( |
---|
498 | World::getSingleton().getOdeWorld()->id(), |
---|
499 | World::getSingleton().getOdeContactJointGroup()->id(), |
---|
500 | &contact); |
---|
501 | |
---|
502 | // Get ODE body,world fragment body is 0 clearly (immovable) |
---|
503 | dBody* body = this->getOdeBody(); |
---|
504 | dBodyID bid; |
---|
505 | bid = 0; |
---|
506 | if (body) bid = body->id(); |
---|
507 | contactJoint.attach(bid, 0); |
---|
508 | } |
---|
509 | |
---|
510 | // Tell object about the collision |
---|
511 | collInfo.position.x = contactGeom.pos[0]; |
---|
512 | collInfo.position.y = contactGeom.pos[1]; |
---|
513 | collInfo.position.z = contactGeom.pos[2]; |
---|
514 | collInfo.normal.x = contactGeom.normal[0]; |
---|
515 | collInfo.normal.y = contactGeom.normal[1]; |
---|
516 | collInfo.normal.z = contactGeom.normal[2]; |
---|
517 | |
---|
518 | // NB clamp the depth to compensate for crazy results |
---|
519 | collInfo.penetrationDepth = contactGeom.depth; |
---|
520 | //collInfo.penetrationDepth = std::max(collInfo.penetrationDepth, |
---|
521 | // this->getLinearVelocity().length()); |
---|
522 | this->_notifyCollided(wf, collInfo); |
---|
523 | |
---|
524 | |
---|
525 | // set return |
---|
526 | collided = true; |
---|
527 | } |
---|
528 | } |
---|
529 | } |
---|
530 | |
---|
531 | } |
---|
532 | return collided; |
---|
533 | } |
---|
534 | //------------------------------------------------------------------------- |
---|
535 | void ApplicationObject::_notifyCollided(ApplicationObject* otherObj, |
---|
536 | const ApplicationObject::CollisionInfo& info) |
---|
537 | { |
---|
538 | // NB contacts for physics are not created here but in testCollide |
---|
539 | // Application subclasses should do their own respose here if required |
---|
540 | } |
---|
541 | //------------------------------------------------------------------------- |
---|
542 | void ApplicationObject::_notifyCollided(SceneQuery::WorldFragment* wf, |
---|
543 | const CollisionInfo& info) |
---|
544 | { |
---|
545 | // NB contacts for physics are not created here but in testCollide |
---|
546 | // Application subclasses should do their own respose here if required |
---|
547 | } |
---|
548 | //------------------------------------------------------------------------- |
---|
549 | void ApplicationObject::setBounceParameters(Real restitutionValue, |
---|
550 | Real velocityThreshold) |
---|
551 | { |
---|
552 | mBounceCoeffRestitution = restitutionValue; |
---|
553 | mBounceVelocityThreshold = velocityThreshold; |
---|
554 | } |
---|
555 | //------------------------------------------------------------------------- |
---|
556 | Real ApplicationObject::getBounceRestitutionValue(void) |
---|
557 | { |
---|
558 | return mBounceCoeffRestitution; |
---|
559 | } |
---|
560 | //------------------------------------------------------------------------- |
---|
561 | Real ApplicationObject::getBounceVelocityThreshold(void) |
---|
562 | { |
---|
563 | return mBounceVelocityThreshold; |
---|
564 | } |
---|
565 | //------------------------------------------------------------------------- |
---|
566 | void ApplicationObject::setSoftness(Real softness) |
---|
567 | { |
---|
568 | mSoftness = softness; |
---|
569 | } |
---|
570 | //------------------------------------------------------------------------- |
---|
571 | Real ApplicationObject::getSoftness(void) |
---|
572 | { |
---|
573 | return mSoftness; |
---|
574 | } |
---|
575 | //------------------------------------------------------------------------- |
---|
576 | void ApplicationObject::setFriction(Real friction) |
---|
577 | { |
---|
578 | if (friction == Math::POS_INFINITY) |
---|
579 | { |
---|
580 | mFriction = dInfinity; |
---|
581 | } |
---|
582 | else |
---|
583 | { |
---|
584 | mFriction = friction; |
---|
585 | } |
---|
586 | } |
---|
587 | //------------------------------------------------------------------------- |
---|
588 | Real ApplicationObject::getFriction(void) |
---|
589 | { |
---|
590 | return mFriction; |
---|
591 | } |
---|
592 | //------------------------------------------------------------------------- |
---|
593 | void ApplicationObject::setMassSphere(Real density, Real radius) |
---|
594 | { |
---|
595 | dMassSetSphere(&mMass, density, radius); |
---|
596 | mOdeBody->setMass(&mMass); |
---|
597 | } |
---|
598 | //------------------------------------------------------------------------- |
---|
599 | void ApplicationObject::setMassBox(Real density, const Vector3& dimensions, |
---|
600 | const Quaternion& orientation) |
---|
601 | { |
---|
602 | dMassSetBox(&mMass, density, dimensions.x, dimensions.y, dimensions.z); |
---|
603 | |
---|
604 | Matrix3 m3; |
---|
605 | orientation.ToRotationMatrix(m3); |
---|
606 | dMatrix3 dm3; |
---|
607 | OgreToOde(m3, dm3); |
---|
608 | dMassRotate(&mMass, dm3); |
---|
609 | |
---|
610 | mOdeBody->setMass(&mMass); |
---|
611 | |
---|
612 | |
---|
613 | } |
---|
614 | //------------------------------------------------------------------------- |
---|
615 | void ApplicationObject::setMassCappedCylinder(Real density, Real length, Real width, |
---|
616 | const Quaternion& orientation) |
---|
617 | { |
---|
618 | dMassSetCappedCylinder(&mMass, density, 3, width, length); |
---|
619 | |
---|
620 | Matrix3 m3; |
---|
621 | orientation.ToRotationMatrix(m3); |
---|
622 | dMatrix3 dm3; |
---|
623 | OgreToOde(m3, dm3); |
---|
624 | dMassRotate(&mMass, dm3); |
---|
625 | |
---|
626 | mOdeBody->setMass(&mMass); |
---|
627 | } |
---|
628 | //------------------------------------------------------------------------- |
---|
629 | void ApplicationObject::setMassExpert(Real mass, const Vector3 center, const Matrix3 inertia) |
---|
630 | { |
---|
631 | |
---|
632 | mMass.mass = mass; |
---|
633 | mMass.c[0] = center.x; |
---|
634 | mMass.c[1] = center.y; |
---|
635 | mMass.c[2] = center.z; |
---|
636 | OgreToOde(inertia, mMass.I); |
---|
637 | |
---|
638 | mOdeBody->setMass(&mMass); |
---|
639 | |
---|
640 | } |
---|
641 | //------------------------------------------------------------------------- |
---|
642 | const dMass* ApplicationObject::getOdeMass(void) |
---|
643 | { |
---|
644 | return &mMass; |
---|
645 | } |
---|
646 | //------------------------------------------------------------------------- |
---|
647 | void ApplicationObject::setLinearVelocity(const Vector3& vel) |
---|
648 | { |
---|
649 | setLinearVelocity(vel.x, vel.y, vel.z); |
---|
650 | } |
---|
651 | //------------------------------------------------------------------------- |
---|
652 | void ApplicationObject::setLinearVelocity(Real x, Real y, Real z) |
---|
653 | { |
---|
654 | assert(mOdeBody && isDynamicsEnabled() && |
---|
655 | "Cannot set velocity on an object unless dynamics are enabled and" |
---|
656 | " an ODE body exists"); |
---|
657 | mOdeBody->setLinearVel(x, y, z); |
---|
658 | // Reenable if on trigger |
---|
659 | setDynamicsEnabled(true, true); |
---|
660 | } |
---|
661 | //------------------------------------------------------------------------- |
---|
662 | const Vector3& ApplicationObject::getLinearVelocity(void) |
---|
663 | { |
---|
664 | assert(mOdeBody && isDynamicsEnabled() && |
---|
665 | "Cannot get velocity on an object unless dynamics are enabled and" |
---|
666 | " an ODE body exists"); |
---|
667 | static Vector3 vel; |
---|
668 | const dReal* odeVel = mOdeBody->getLinearVel(); |
---|
669 | vel.x = odeVel[0]; |
---|
670 | vel.y = odeVel[1]; |
---|
671 | vel.z = odeVel[2]; |
---|
672 | return vel; |
---|
673 | |
---|
674 | } |
---|
675 | //------------------------------------------------------------------------- |
---|
676 | const Vector3& ApplicationObject::getAngularVelocity(void) |
---|
677 | { |
---|
678 | assert(mOdeBody && isDynamicsEnabled() && |
---|
679 | "Cannot get velocity on an object unless dynamics are enabled and" |
---|
680 | " an ODE body exists"); |
---|
681 | static Vector3 vel; |
---|
682 | const dReal* odeVel = mOdeBody->getAngularVel(); |
---|
683 | vel.x = odeVel[0]; |
---|
684 | vel.y = odeVel[1]; |
---|
685 | vel.z = odeVel[2]; |
---|
686 | return vel; |
---|
687 | } |
---|
688 | //------------------------------------------------------------------------- |
---|
689 | void ApplicationObject::setAngularVelocity(const Vector3& vel) |
---|
690 | { |
---|
691 | setAngularVelocity(vel.x, vel.y, vel.z); |
---|
692 | } |
---|
693 | //------------------------------------------------------------------------- |
---|
694 | void ApplicationObject::setAngularVelocity(Real x, Real y, Real z) |
---|
695 | { |
---|
696 | assert(mOdeBody && isDynamicsEnabled() && |
---|
697 | "Cannot set velocity on an object unless dynamics are enabled and" |
---|
698 | " an ODE body exists"); |
---|
699 | mOdeBody->setAngularVel(x, y, z); |
---|
700 | // Reenable if on trigger |
---|
701 | setDynamicsEnabled(true, true); |
---|
702 | } |
---|
703 | //------------------------------------------------------------------------- |
---|
704 | void ApplicationObject::translate(const Vector3& d) |
---|
705 | { |
---|
706 | // Adjust position by rotation |
---|
707 | Vector3 newTrans = mSceneNode->getOrientation() * d; |
---|
708 | translateWorldSpace(newTrans); |
---|
709 | } |
---|
710 | //------------------------------------------------------------------------- |
---|
711 | void ApplicationObject::translate(Real x, Real y, Real z) |
---|
712 | { |
---|
713 | translate(Vector3(x, y, z)); |
---|
714 | } |
---|
715 | //------------------------------------------------------------------------- |
---|
716 | void ApplicationObject::translateWorldSpace(const Vector3& d) |
---|
717 | { |
---|
718 | setPosition(getPosition() + d); |
---|
719 | } |
---|
720 | //------------------------------------------------------------------------- |
---|
721 | void ApplicationObject::translateWorldSpace(Real x, Real y, Real z) |
---|
722 | { |
---|
723 | translateWorldSpace(Vector3(x, y, z)); |
---|
724 | } |
---|
725 | //------------------------------------------------------------------------- |
---|
726 | void ApplicationObject::roll(const Radian& angle) |
---|
727 | { |
---|
728 | rotate(Vector3::UNIT_Z, angle); |
---|
729 | } |
---|
730 | //------------------------------------------------------------------------- |
---|
731 | void ApplicationObject::pitch(const Radian& angle) |
---|
732 | { |
---|
733 | rotate(Vector3::UNIT_X, angle); |
---|
734 | } |
---|
735 | //------------------------------------------------------------------------- |
---|
736 | void ApplicationObject::yaw(const Radian& angle) |
---|
737 | { |
---|
738 | rotate(Vector3::UNIT_Y, angle); |
---|
739 | } |
---|
740 | //------------------------------------------------------------------------- |
---|
741 | void ApplicationObject::rotate(const Vector3& axis, const Radian& angle) |
---|
742 | { |
---|
743 | Quaternion q; |
---|
744 | q.FromAngleAxis(angle,axis); |
---|
745 | rotate(q); |
---|
746 | } |
---|
747 | //------------------------------------------------------------------------- |
---|
748 | void ApplicationObject::rotate(const Quaternion& q) |
---|
749 | { |
---|
750 | setOrientation(getOrientation() * q); |
---|
751 | } |
---|
752 | //------------------------------------------------------------------------- |
---|
753 | void ApplicationObject::setEntityQueryFlags(void) |
---|
754 | { |
---|
755 | // Real basic query mask usage for now |
---|
756 | // collision enabled = 0xFFFFFFFF |
---|
757 | // collision disabled = 0x0 |
---|
758 | if (mEntity) |
---|
759 | { |
---|
760 | mEntity->setQueryFlags( mCollisionEnabled ? 0xFFFFFFFF : 0 ); |
---|
761 | } |
---|
762 | } |
---|
763 | |
---|
764 | |
---|
765 | |
---|
766 | } |
---|
767 | |
---|