[692] | 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-2005 The OGRE Team
|
---|
| 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 | */
|
---|
| 25 | #include "OgreRefAppWorld.h"
|
---|
| 26 | #include "OgreRefAppOgreHead.h"
|
---|
| 27 | #include "OgreRefAppPlane.h"
|
---|
| 28 | #include "OgreRefAppBall.h"
|
---|
| 29 | #include "OgreRefAppJointSubtypes.h"
|
---|
| 30 | #include "OgreRefAppBox.h"
|
---|
| 31 | #include "OgreRefAppCollideCamera.h"
|
---|
| 32 |
|
---|
| 33 | //-------------------------------------------------------------------------
|
---|
| 34 | template<> OgreRefApp::World* Ogre::Singleton<OgreRefApp::World>::ms_Singleton = 0;
|
---|
| 35 | OgreRefApp::World* OgreRefApp::World::getSingletonPtr(void)
|
---|
| 36 | {
|
---|
| 37 | return ms_Singleton;
|
---|
| 38 | }
|
---|
| 39 | OgreRefApp::World& OgreRefApp::World::getSingleton(void)
|
---|
| 40 | {
|
---|
| 41 | assert( ms_Singleton ); return ( *ms_Singleton );
|
---|
| 42 | }
|
---|
| 43 | //-------------------------------------------------------------------------
|
---|
| 44 | namespace OgreRefApp
|
---|
| 45 | {
|
---|
| 46 | //-------------------------------------------------------------------------
|
---|
| 47 | World::World(SceneManager* sceneMgr, WorldType worldType)
|
---|
| 48 | : mSceneMgr(sceneMgr), mWorldType(worldType)
|
---|
| 49 | {
|
---|
| 50 | mSimulationStepSize = 0.01f;
|
---|
| 51 |
|
---|
| 52 | // Create the dynamics world
|
---|
| 53 | mOdeWorld = new dWorld();
|
---|
| 54 | mOdeContactGroup = new dJointGroup();
|
---|
| 55 |
|
---|
| 56 | mIntersectionQuery = mSceneMgr->createIntersectionQuery();
|
---|
| 57 | switch (worldType)
|
---|
| 58 | {
|
---|
| 59 | case World::WT_REFAPP_GENERIC:
|
---|
| 60 | mIntersectionQuery->setWorldFragmentType(SceneQuery::WFT_NONE);
|
---|
| 61 | break;
|
---|
| 62 | case World::WT_REFAPP_BSP:
|
---|
| 63 | mIntersectionQuery->setWorldFragmentType(SceneQuery::WFT_PLANE_BOUNDED_REGION);
|
---|
| 64 | break;
|
---|
| 65 | };
|
---|
| 66 |
|
---|
| 67 | }
|
---|
| 68 | //-------------------------------------------------------------------------
|
---|
| 69 | World::~World()
|
---|
| 70 | {
|
---|
| 71 | clear();
|
---|
| 72 |
|
---|
| 73 | delete mIntersectionQuery;
|
---|
| 74 |
|
---|
| 75 | // Destroy dynamix world
|
---|
| 76 | delete mOdeContactGroup;
|
---|
| 77 | delete mOdeWorld;
|
---|
| 78 |
|
---|
| 79 | }
|
---|
| 80 | //-------------------------------------------------------------------------
|
---|
| 81 | SceneManager* World::getSceneManager(void)
|
---|
| 82 | {
|
---|
| 83 | return mSceneMgr;
|
---|
| 84 | }
|
---|
| 85 | //-------------------------------------------------------------------------
|
---|
| 86 | OgreHead* World::createOgreHead(const String& name,
|
---|
| 87 | const Vector3& pos, const Quaternion& orientation)
|
---|
| 88 | {
|
---|
| 89 | OgreHead* head = new OgreHead(name);
|
---|
| 90 | head->setPosition(pos);
|
---|
| 91 | head->setOrientation(orientation);
|
---|
| 92 |
|
---|
| 93 | mObjects[name] = head;
|
---|
| 94 |
|
---|
| 95 | return head;
|
---|
| 96 | }
|
---|
| 97 | //-------------------------------------------------------------------------
|
---|
| 98 | FinitePlane* World::createPlane(const String& name, Real width, Real height, const Vector3& pos,
|
---|
| 99 | const Quaternion& orientation)
|
---|
| 100 | {
|
---|
| 101 | FinitePlane* plane = new FinitePlane(name, width, height);
|
---|
| 102 | plane->setPosition(pos);
|
---|
| 103 | plane->setOrientation(orientation);
|
---|
| 104 |
|
---|
| 105 | mObjects[name] = plane;
|
---|
| 106 |
|
---|
| 107 | return plane;
|
---|
| 108 | }
|
---|
| 109 | //-------------------------------------------------------------------------
|
---|
| 110 | Ball* World::createBall(const String& name, Real radius, const Vector3& pos,
|
---|
| 111 | const Quaternion& orientation)
|
---|
| 112 | {
|
---|
| 113 | OgreRefApp::Ball* ball = new OgreRefApp::Ball(name, radius);
|
---|
| 114 | ball->setPosition(pos);
|
---|
| 115 | ball->setOrientation(orientation);
|
---|
| 116 |
|
---|
| 117 | mObjects[name] = ball;
|
---|
| 118 |
|
---|
| 119 | return ball;
|
---|
| 120 | }
|
---|
| 121 | //-------------------------------------------------------------------------
|
---|
| 122 | void World::clear(void)
|
---|
| 123 | {
|
---|
| 124 | ObjectMap::iterator i;
|
---|
| 125 | for (i = mObjects.begin(); i != mObjects.end(); ++i)
|
---|
| 126 | {
|
---|
| 127 | delete i->second;
|
---|
| 128 | }
|
---|
| 129 | mObjects.clear();
|
---|
| 130 |
|
---|
| 131 | JointMap::iterator ji;
|
---|
| 132 | for (ji = mJoints.begin(); ji != mJoints.end(); ++ji)
|
---|
| 133 | {
|
---|
| 134 | delete ji->second;
|
---|
| 135 | }
|
---|
| 136 | mJoints.clear();
|
---|
| 137 | }
|
---|
| 138 | //-------------------------------------------------------------------------
|
---|
| 139 | dWorld* World::getOdeWorld(void)
|
---|
| 140 | {
|
---|
| 141 | return mOdeWorld;
|
---|
| 142 | }
|
---|
| 143 | //-------------------------------------------------------------------------
|
---|
| 144 | void World::_applyDynamics(Real timeElapsed)
|
---|
| 145 | {
|
---|
| 146 | if (timeElapsed != 0.0f)
|
---|
| 147 | {
|
---|
| 148 | // ODE will throw an error if timestep = 0
|
---|
| 149 |
|
---|
| 150 | mOdeWorld->step(dReal(timeElapsed));
|
---|
| 151 | // Now update the objects in the world
|
---|
| 152 | ObjectSet::iterator i, iend;
|
---|
| 153 | iend = mDynamicsObjects.end();
|
---|
| 154 | for (i = mDynamicsObjects.begin(); i != iend; ++i)
|
---|
| 155 | {
|
---|
| 156 | (*i)->_updateFromDynamics();
|
---|
| 157 | }
|
---|
| 158 | // Clear contacts
|
---|
| 159 | mOdeContactGroup->empty();
|
---|
| 160 | }
|
---|
| 161 |
|
---|
| 162 | }
|
---|
| 163 | //-------------------------------------------------------------------------
|
---|
| 164 | void World::_notifyDynamicsStateForObject(ApplicationObject* obj, bool dynamicsEnabled)
|
---|
| 165 | {
|
---|
| 166 | // NB std::set prevents duplicates & errors on erasing non-existent objects
|
---|
| 167 | if (dynamicsEnabled)
|
---|
| 168 | {
|
---|
| 169 | mDynamicsObjects.insert(obj);
|
---|
| 170 | }
|
---|
| 171 | else
|
---|
| 172 | {
|
---|
| 173 | mDynamicsObjects.erase(obj);
|
---|
| 174 | }
|
---|
| 175 | }
|
---|
| 176 | //-------------------------------------------------------------------------
|
---|
| 177 | void World::setGravity(const Vector3& vec)
|
---|
| 178 | {
|
---|
| 179 | mGravity = vec;
|
---|
| 180 | mOdeWorld->setGravity(vec.x, vec.y, vec.z);
|
---|
| 181 | }
|
---|
| 182 | //-------------------------------------------------------------------------
|
---|
| 183 | const Vector3& World::getGravity(void)
|
---|
| 184 | {
|
---|
| 185 | return mGravity;
|
---|
| 186 | }
|
---|
| 187 | //-------------------------------------------------------------------------
|
---|
| 188 | dJointGroup* World::getOdeContactJointGroup(void)
|
---|
| 189 | {
|
---|
| 190 | return mOdeContactGroup;
|
---|
| 191 | }
|
---|
| 192 | //-------------------------------------------------------------------------
|
---|
| 193 | void World::_applyCollision(void)
|
---|
| 194 | {
|
---|
| 195 | // Collision detection
|
---|
| 196 | IntersectionSceneQueryResult& results = mIntersectionQuery->execute();
|
---|
| 197 |
|
---|
| 198 | // Movables to Movables
|
---|
| 199 | SceneQueryMovableIntersectionList::iterator it, itend;
|
---|
| 200 | itend = results.movables2movables.end();
|
---|
| 201 | for (it = results.movables2movables.begin(); it != itend; ++it)
|
---|
| 202 | {
|
---|
| 203 | /* debugging
|
---|
| 204 | MovableObject *mo1, *mo2;
|
---|
| 205 | mo1 = it->first;
|
---|
| 206 | mo2 = it->second;
|
---|
| 207 | */
|
---|
| 208 |
|
---|
| 209 | // Get user defined objects (generic in OGRE)
|
---|
| 210 | UserDefinedObject *uo1, *uo2;
|
---|
| 211 | uo1 = it->first->getUserObject();
|
---|
| 212 | uo2 = it->second->getUserObject();
|
---|
| 213 |
|
---|
| 214 | // Only perform collision if we have UserDefinedObject links
|
---|
| 215 | if (uo1 && uo2)
|
---|
| 216 | {
|
---|
| 217 | // Cast to ApplicationObject
|
---|
| 218 | ApplicationObject *ao1, *ao2;
|
---|
| 219 | ao1 = static_cast<ApplicationObject*>(uo1);
|
---|
| 220 | ao2 = static_cast<ApplicationObject*>(uo2);
|
---|
| 221 | // Do detailed collision test
|
---|
| 222 | ao1->testCollide(ao2);
|
---|
| 223 | }
|
---|
| 224 | }
|
---|
| 225 |
|
---|
| 226 | // Movables to World
|
---|
| 227 | SceneQueryMovableWorldFragmentIntersectionList::iterator wit, witend;
|
---|
| 228 | witend = results.movables2world.end();
|
---|
| 229 | for (wit = results.movables2world.begin(); wit != witend; ++wit)
|
---|
| 230 | {
|
---|
| 231 | MovableObject *mo = wit->first;
|
---|
| 232 | SceneQuery::WorldFragment *wf = wit->second;
|
---|
| 233 |
|
---|
| 234 | // Get user defined objects (generic in OGRE)
|
---|
| 235 | UserDefinedObject *uo = mo->getUserObject();
|
---|
| 236 |
|
---|
| 237 | // Only perform collision if we have UserDefinedObject link
|
---|
| 238 | if (uo)
|
---|
| 239 | {
|
---|
| 240 | // Cast to ApplicationObject
|
---|
| 241 | ApplicationObject *ao = static_cast<ApplicationObject*>(uo);
|
---|
| 242 | // Do detailed collision test
|
---|
| 243 | ao->testCollide(wf);
|
---|
| 244 | }
|
---|
| 245 | }
|
---|
| 246 |
|
---|
| 247 | }
|
---|
| 248 | //-------------------------------------------------------------------------
|
---|
| 249 | Joint* World::createJoint(const String& name, Joint::JointType jtype,
|
---|
| 250 | ApplicationObject* obj1, ApplicationObject* obj2)
|
---|
| 251 | {
|
---|
| 252 | Joint* ret;
|
---|
| 253 | switch (jtype)
|
---|
| 254 | {
|
---|
| 255 | case Joint::JT_BALL:
|
---|
| 256 | ret = new BallJoint(jtype, obj1, obj2);
|
---|
| 257 | break;
|
---|
| 258 | case Joint::JT_HINGE:
|
---|
| 259 | ret = new HingeJoint(jtype, obj1, obj2);
|
---|
| 260 | break;
|
---|
| 261 | case Joint::JT_HINGE2:
|
---|
| 262 | ret = new Hinge2Joint(jtype, obj1, obj2);
|
---|
| 263 | break;
|
---|
| 264 | case Joint::JT_SLIDER:
|
---|
| 265 | ret = new SliderJoint(jtype, obj1, obj2);
|
---|
| 266 | break;
|
---|
| 267 | case Joint::JT_UNIVERSAL:
|
---|
| 268 | ret = new UniversalJoint(jtype, obj1, obj2);
|
---|
| 269 | break;
|
---|
| 270 |
|
---|
| 271 | }
|
---|
| 272 |
|
---|
| 273 | mJoints[name] = ret;
|
---|
| 274 | return ret;
|
---|
| 275 | }
|
---|
| 276 | //-------------------------------------------------------------------------
|
---|
| 277 | void World::setSimulationStepSize(Real step)
|
---|
| 278 | {
|
---|
| 279 | mSimulationStepSize = step;
|
---|
| 280 | }
|
---|
| 281 | //-------------------------------------------------------------------------
|
---|
| 282 | Real World::getSimulationStepSize(void)
|
---|
| 283 | {
|
---|
| 284 | return mSimulationStepSize;
|
---|
| 285 | }
|
---|
| 286 | //-------------------------------------------------------------------------
|
---|
| 287 | void World::simulationStep(Real timeElapsed)
|
---|
| 288 | {
|
---|
| 289 | /* Hmm, gives somewhat jerky results*/
|
---|
| 290 | static Real leftOverTime = 0.0f;
|
---|
| 291 |
|
---|
| 292 | Real time = timeElapsed + leftOverTime;
|
---|
| 293 | unsigned int steps = (unsigned int)(time / mSimulationStepSize);
|
---|
| 294 | for(unsigned int i=0; i < steps; ++i)
|
---|
| 295 | {
|
---|
| 296 | _applyCollision();
|
---|
| 297 | _applyDynamics(mSimulationStepSize);
|
---|
| 298 | }
|
---|
| 299 | leftOverTime = time - (steps * mSimulationStepSize);
|
---|
| 300 | /*
|
---|
| 301 | _applyCollision();
|
---|
| 302 | _applyDynamics(timeElapsed);
|
---|
| 303 | */
|
---|
| 304 |
|
---|
| 305 |
|
---|
| 306 | }
|
---|
| 307 | //-------------------------------------------------------------------------
|
---|
| 308 | OgreRefApp::Box* World::createBox(const String& name,
|
---|
| 309 | Real width, Real height, Real depth,
|
---|
| 310 | const Vector3& pos, const Quaternion& orientation)
|
---|
| 311 | {
|
---|
| 312 | OgreRefApp::Box* box = new OgreRefApp::Box(name, width, height, depth);
|
---|
| 313 | box->setPosition(pos);
|
---|
| 314 | box->setOrientation(orientation);
|
---|
| 315 |
|
---|
| 316 | mObjects[name] = box;
|
---|
| 317 |
|
---|
| 318 | return box;
|
---|
| 319 | }
|
---|
| 320 | //-------------------------------------------------------------------------
|
---|
| 321 | CollideCamera* World::createCamera(const String& name, const Vector3& pos,
|
---|
| 322 | const Quaternion& orientation )
|
---|
| 323 | {
|
---|
| 324 | CollideCamera* cam = new CollideCamera(name);
|
---|
| 325 | cam->setPosition(pos);
|
---|
| 326 | cam->setOrientation(orientation);
|
---|
| 327 |
|
---|
| 328 | mObjects[name] = cam;
|
---|
| 329 |
|
---|
| 330 | return cam;
|
---|
| 331 |
|
---|
| 332 | }
|
---|
| 333 | }
|
---|
| 334 |
|
---|