diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index f8b4d7a59..675c377a0 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -16,6 +16,7 @@ set(GAME_HEADER source_group(game FILES ${GAME} ${GAME_HEADER}) set(GAMEREND + mwrender/rendering_manager.cpp mwrender/mwscene.cpp mwrender/cellimp.cpp mwrender/interior.cpp @@ -24,6 +25,7 @@ set(GAMEREND mwrender/player.cpp ) set(GAMEREND_HEADER + mwrender/rendering_manager.hpp mwrender/cell.hpp mwrender/cellimp.hpp mwrender/mwscene.hpp @@ -137,6 +139,8 @@ source_group(apps\\openmw\\mwsound FILES ${GAMESOUND} ${GAMESOUND_HEADER}) set(GAMEWORLD mwworld/world.cpp + mwworld/scene.cpp + mwworld/physicssystem.cpp mwworld/globals.cpp mwworld/class.cpp mwworld/actionteleport.cpp @@ -149,7 +153,8 @@ set(GAMEWORLD set(GAMEWORLD_HEADER mwworld/refdata.hpp mwworld/world.hpp - mwworld/ptr.hpp + mwworld/physicssystem.hpp + mwworld/scene.hpp mwworld/environment.hpp mwworld/globals.hpp mwworld/class.hpp diff --git a/apps/openmw/mwrender/exterior.cpp b/apps/openmw/mwrender/exterior.cpp index 513fdac2a..6e6908a62 100644 --- a/apps/openmw/mwrender/exterior.cpp +++ b/apps/openmw/mwrender/exterior.cpp @@ -34,8 +34,8 @@ bool ExteriorCellRender::lightOutQuadInLin = false; int ExteriorCellRender::uniqueID = 0; ExteriorCellRender::ExteriorCellRender(ESMS::CellStore &_cell, MWWorld::Environment& environment, - MWScene &_scene) - : mCell(_cell), mEnvironment (environment), mScene(_scene), mBase(NULL), mInsert(NULL), mAmbientMode (0) + MWScene &_scene, MWWorld::PhysicsSystem *physics) + : mCell(_cell), mEnvironment (environment), mScene(_scene), mBase(NULL), mInsert(NULL), mAmbientMode (0), mPhysics(physics) { uniqueID = uniqueID +1; sg = mScene.getMgr()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); @@ -233,13 +233,15 @@ void ExteriorCellRender::insertMesh(const std::string &mesh) void ExteriorCellRender::insertObjectPhysics() { if (!mInsertMesh.empty()) - mScene.addObject (mInsert->getName(), mInsertMesh, mInsert->getOrientation(), + { + mPhysics->addObject (mInsert->getName(), mInsertMesh, mInsert->getOrientation(), mInsert->getScale().x, mInsert->getPosition()); + } } void ExteriorCellRender::insertActorPhysics() { - mScene.addActor (mInsert->getName(), mInsertMesh, mInsert->getPosition()); + mPhysics->addActor (mInsert->getName(), mInsertMesh, mInsert->getPosition()); } // insert a light related to the most recent insertBegin call. diff --git a/apps/openmw/mwrender/exterior.hpp b/apps/openmw/mwrender/exterior.hpp index 6c7f6effc..d8f6b9b96 100644 --- a/apps/openmw/mwrender/exterior.hpp +++ b/apps/openmw/mwrender/exterior.hpp @@ -3,6 +3,7 @@ #include "cell.hpp" #include "cellimp.hpp" +#include "../mwworld/physicssystem.hpp" #include "OgreColourValue.h" #include @@ -49,6 +50,7 @@ namespace MWRender ESMS::CellStore &mCell; MWWorld::Environment &mEnvironment; MWScene &mScene; + MWWorld::PhysicsSystem *mPhysics; /// The scene node that contains all objects belonging to this /// cell. @@ -101,7 +103,7 @@ namespace MWRender public: ExteriorCellRender(ESMS::CellStore &_cell, MWWorld::Environment& environment, - MWScene &_scene); + MWScene &_scene, MWWorld::PhysicsSystem *physics); virtual ~ExteriorCellRender() { destroy(); } diff --git a/apps/openmw/mwrender/interior.cpp b/apps/openmw/mwrender/interior.cpp index 02bed0898..bfde4b04e 100644 --- a/apps/openmw/mwrender/interior.cpp +++ b/apps/openmw/mwrender/interior.cpp @@ -195,13 +195,15 @@ void InteriorCellRender::insertMesh(const std::string &mesh) void InteriorCellRender::insertObjectPhysics() { if (!mInsertMesh.empty()) - scene.addObject (insert->getName(), mInsertMesh, insert->getOrientation(), + { + mPhysics->addObject (insert->getName(), mInsertMesh, insert->getOrientation(), insert->getScale().x, insert->getPosition()); + } } void InteriorCellRender::insertActorPhysics() { - scene.addActor (insert->getName(), mInsertMesh, insert->getPosition()); + mPhysics->addActor (insert->getName(), mInsertMesh, insert->getPosition()); } // insert a light related to the most recent insertBegin call. diff --git a/apps/openmw/mwrender/interior.hpp b/apps/openmw/mwrender/interior.hpp index 295eaa475..16fca0898 100644 --- a/apps/openmw/mwrender/interior.hpp +++ b/apps/openmw/mwrender/interior.hpp @@ -3,6 +3,7 @@ #include "cell.hpp" #include "cellimp.hpp" +#include "../mwworld/physicssystem.hpp" #include "OgreColourValue.h" #include @@ -48,6 +49,7 @@ namespace MWRender ESMS::CellStore &cell; MWWorld::Environment &mEnvironment; MWScene &scene; + MWWorld::PhysicsSystem *mPhysics; /// The scene node that contains all objects belonging to this /// cell. @@ -93,8 +95,11 @@ namespace MWRender public: InteriorCellRender(ESMS::CellStore &_cell, MWWorld::Environment& environment, - MWScene &_scene) - : cell(_cell), mEnvironment (environment), scene(_scene), base(NULL), insert(NULL), ambientMode (0) {} + MWScene &_scene, MWWorld::PhysicsSystem *physics) + : cell(_cell), mEnvironment (environment), scene(_scene), base(NULL), insert(NULL), ambientMode (0) + { + mPhysics = physics; + } virtual ~InteriorCellRender() { destroy(); } diff --git a/apps/openmw/mwrender/mwscene.cpp b/apps/openmw/mwrender/mwscene.cpp index e4d449bf2..a1d4aed03 100644 --- a/apps/openmw/mwrender/mwscene.cpp +++ b/apps/openmw/mwrender/mwscene.cpp @@ -76,121 +76,6 @@ std::pair MWScene::getFacedHandle (MWWorld::World& world) return eng->rayTest(from,to); } -void MWScene::doPhysics (float duration, MWWorld::World& world, - const std::vector >& actors) -{ - // stop changes to world from being reported back to the physics system - MWWorld::DoingPhysics scopeGuard; - - //set the DebugRenderingMode. To disable it,set it to 0 - //eng->setDebugRenderingMode(1); - - //set the walkdirection to 0 (no movement) for every actor) - for(std::map::iterator it = eng->PhysicActorMap.begin(); it != eng->PhysicActorMap.end();it++) - { - OEngine::Physic::PhysicActor* act = it->second; - act->setWalkDirection(btVector3(0,0,0)); - } - - for (std::vector >::const_iterator iter (actors.begin()); - iter!=actors.end(); ++iter) - { - OEngine::Physic::PhysicActor* act = eng->getCharacter(iter->first); - - //dirty stuff to get the camera orientation. Must be changed! - - Ogre::SceneNode *sceneNode = rend.getScene()->getSceneNode (iter->first); - Ogre::Vector3 dir; - Ogre::Node* yawNode = sceneNode->getChildIterator().getNext(); - Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); - if(mFreeFly) - { - Ogre::Quaternion yawQuat = yawNode->getOrientation(); - Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); - Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); - dir = 0.07*(yawQuat*pitchQuat*dir1); - } - else - { - Ogre::Quaternion quat = yawNode->getOrientation(); - Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); - dir = 0.025*(quat*dir1); - } - - //set the walk direction - act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y)); - } - eng->stepSimulation(duration); - - for(std::map::iterator it = eng->PhysicActorMap.begin(); it != eng->PhysicActorMap.end();it++) - { - OEngine::Physic::PhysicActor* act = it->second; - btVector3 newPos = act->getPosition(); - MWWorld::Ptr ptr = world.getPtrViaHandle (it->first); - world.moveObject (ptr, newPos.x(), newPos.y(), newPos.z()); - } -} - -void MWScene::addObject (const std::string& handle, const std::string& mesh, - const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position) -{ - OEngine::Physic::RigidBody* body = eng->createRigidBody(mesh,handle); - eng->addRigidBody(body); - btTransform tr; - tr.setOrigin(btVector3(position.x,position.y,position.z)); - tr.setRotation(btQuaternion(rotation.x,rotation.y,rotation.z,rotation.w)); - body->setWorldTransform(tr); -} - -void MWScene::addActor (const std::string& handle, const std::string& mesh, - const Ogre::Vector3& position) -{ - //TODO:optimize this. Searching the std::map isn't very efficient i think. - eng->addCharacter(handle); - OEngine::Physic::PhysicActor* act = eng->getCharacter(handle); - act->setPosition(btVector3(position.x,position.y,position.z)); -} - -void MWScene::removeObject (const std::string& handle) -{ - //TODO:check if actor??? - eng->removeCharacter(handle); - eng->removeRigidBody(handle); - eng->deleteRigidBody(handle); -} - -void MWScene::moveObject (const std::string& handle, const Ogre::Vector3& position, bool updatePhysics) -{ - rend.getScene()->getSceneNode(handle)->setPosition(position); - - if(updatePhysics)//TODO: is it an actor? Done? - { - if (OEngine::Physic::RigidBody* body = eng->getRigidBody(handle)) - { - // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow - // start positions others than 0, 0, 0 - btTransform tr = body->getWorldTransform(); - tr.setOrigin(btVector3(position.x,position.y,position.z)); - body->setWorldTransform(tr); - } - if (OEngine::Physic::PhysicActor* act = eng->getCharacter(handle)) - { - // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow - // start positions others than 0, 0, 0 - act->setPosition(btVector3(position.x,position.y,position.z)); - } - } -} - -void MWScene::rotateObject (const std::string& handle, const Ogre::Quaternion& rotation) -{ -} - -void MWScene::scaleObject (const std::string& handle, float scale) -{ - -} - bool MWScene::toggleCollisionMode() { for(std::map::iterator it = eng->PhysicActorMap.begin(); it != eng->PhysicActorMap.end();it++) diff --git a/apps/openmw/mwrender/mwscene.hpp b/apps/openmw/mwrender/mwscene.hpp index 7429ff21e..a9dfad7b5 100644 --- a/apps/openmw/mwrender/mwscene.hpp +++ b/apps/openmw/mwrender/mwscene.hpp @@ -65,30 +65,6 @@ namespace MWRender /// can be faced std::pair getFacedHandle (MWWorld::World& world); - /// Run physics simulation and modify \a world accordingly. - void doPhysics (float duration, MWWorld::World& world, - const std::vector >& actors); - - /// Add object to physics system. - void addObject (const std::string& handle, const std::string& mesh, - const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position); - - /// Add actor to physics system. - void addActor (const std::string& handle, const std::string& mesh, - const Ogre::Vector3& position); - - /// Remove object from physic systems. - void removeObject (const std::string& handle); - - /// Move object. - void moveObject (const std::string& handle, const Ogre::Vector3& position, bool updatePhysics); - - /// Change object's orientation. - void rotateObject (const std::string& handle, const Ogre::Quaternion& rotation); - - /// Change object's scale. - void scaleObject (const std::string& handle, float scale); - /// Toggle collision mode for player. If disabled player object should ignore /// collisions and gravity. /// \return Resulting mode diff --git a/apps/openmw/mwrender/rendering_manager.cpp b/apps/openmw/mwrender/rendering_manager.cpp new file mode 100644 index 000000000..66d178606 --- /dev/null +++ b/apps/openmw/mwrender/rendering_manager.cpp @@ -0,0 +1 @@ +#include "rendering_manager.hpp" diff --git a/apps/openmw/mwrender/rendering_manager.hpp b/apps/openmw/mwrender/rendering_manager.hpp new file mode 100644 index 000000000..19ea73f5c --- /dev/null +++ b/apps/openmw/mwrender/rendering_manager.hpp @@ -0,0 +1,43 @@ +#ifndef _GAME_RENDERING_MANAGER_H +#define _GAME_RENDERING_MANAGER_H + +#include "../mwworld/ptr.hpp" +#include +#include + +namespace MWRender +{ + +class RenderingManager { + public: + + void removeCell (MWWorld::Ptr::CellStore *store); // TODO do we want this? + + void addObject (const MWWorld::Ptr& ptr, MWWorld::Ptr::CellStore *store); + void removeObject (const MWWorld::Ptr& ptr, MWWorld::Ptr::CellStore *store); + + void moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position); + void scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& scale); + void rotateObject (const MWWorld::Ptr& ptr, const::Ogre::Quaternion& orientation); + void moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Vector3& position, MWWorld::Ptr::CellStore *store); + + void setPhysicsDebugRendering (bool); + bool getPhysicsDebugRendering() const; + + void update (float duration); + void skyEnable (); + void skyDisable (); + void skySetHour (double hour); + void skySetDate (int day, int month); + int skyGetMasserPhase() const; + int skyGetSecundaPhase() const; + void skySetMoonColour (bool red); + + private: + + +}; + +} + +#endif diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp new file mode 100644 index 000000000..e9a270c53 --- /dev/null +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -0,0 +1,173 @@ +#include "physicssystem.hpp" +#include "../mwworld/doingphysics.hpp" +#include "../mwworld/ptr.hpp" +#include "../mwworld/world.hpp" // FIXME + +#include "OgreRoot.h" +#include "OgreRenderWindow.h" +#include "OgreSceneManager.h" +#include "OgreViewport.h" +#include "OgreCamera.h" +#include "OgreTextureManager.h" + + +namespace MWWorld +{ + + PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend , OEngine::Physic::PhysicEngine* physEng) : + mRender(_rend), mEngine(physEng) + { + + } + + PhysicsSystem::~PhysicsSystem() + { + + } + + std::vector< std::pair > PhysicsSystem::doPhysics (float duration, + const std::vector >& actors) + { + // stop changes to world from being reported back to the physics system + MWWorld::DoingPhysics scopeGuard; + + //set the DebugRenderingMode. To disable it,set it to 0 + //eng->setDebugRenderingMode(1); + + //set the walkdirection to 0 (no movement) for every actor) + for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) + { + OEngine::Physic::PhysicActor* act = it->second; + act->setWalkDirection(btVector3(0,0,0)); + } + + for (std::vector >::const_iterator iter (actors.begin()); + iter!=actors.end(); ++iter) + { + OEngine::Physic::PhysicActor* act = mEngine->getCharacter(iter->first); + + //dirty stuff to get the camera orientation. Must be changed! + + Ogre::SceneNode *sceneNode = mRender.getScene()->getSceneNode (iter->first); + Ogre::Vector3 dir; + Ogre::Node* yawNode = sceneNode->getChildIterator().getNext(); + Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); + if(mFreeFly) + { + Ogre::Quaternion yawQuat = yawNode->getOrientation(); + Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); + Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); + dir = 0.07*(yawQuat*pitchQuat*dir1); + } + else + { + Ogre::Quaternion quat = yawNode->getOrientation(); + Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); + dir = 0.025*(quat*dir1); + } + + //set the walk direction + act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y)); + } + mEngine->stepSimulation(duration); + + std::vector< std::pair > response; + for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) + { + btVector3 newPos = it->second->getPosition(); + Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z()); + + response.push_back(std::pair(it->first, coord)); + } + return response; + } + + void PhysicsSystem::addObject (const std::string& handle, const std::string& mesh, + const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position) + { + OEngine::Physic::RigidBody* body = mEngine->createRigidBody(mesh,handle); + mEngine->addRigidBody(body); + btTransform tr; + tr.setOrigin(btVector3(position.x,position.y,position.z)); + tr.setRotation(btQuaternion(rotation.x,rotation.y,rotation.z,rotation.w)); + body->setWorldTransform(tr); + } + + void PhysicsSystem::addActor (const std::string& handle, const std::string& mesh, + const Ogre::Vector3& position) + { + //TODO:optimize this. Searching the std::map isn't very efficient i think. + mEngine->addCharacter(handle); + OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle); + act->setPosition(btVector3(position.x,position.y,position.z)); + } + + void PhysicsSystem::removeObject (const std::string& handle) + { + //TODO:check if actor??? + mEngine->removeCharacter(handle); + mEngine->removeRigidBody(handle); + mEngine->deleteRigidBody(handle); + } + + void PhysicsSystem::moveObject (const std::string& handle, const Ogre::Vector3& position, bool updatePhysics) + { + mRender.getScene()->getSceneNode(handle)->setPosition(position); + + if(updatePhysics)//TODO: is it an actor? Done? + { + if (OEngine::Physic::RigidBody* body = mEngine->getRigidBody(handle)) + { + // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow + // start positions others than 0, 0, 0 + btTransform tr = body->getWorldTransform(); + tr.setOrigin(btVector3(position.x,position.y,position.z)); + body->setWorldTransform(tr); + } + if (OEngine::Physic::PhysicActor* act = mEngine->getCharacter(handle)) + { + // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow + // start positions others than 0, 0, 0 + act->setPosition(btVector3(position.x,position.y,position.z)); + } + } + } + + void PhysicsSystem::rotateObject (const std::string& handle, const Ogre::Quaternion& rotation) + { + } + + void PhysicsSystem::scaleObject (const std::string& handle, float scale) + { + + } + + bool PhysicsSystem::toggleCollisionMode() + { + for(std::map::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) + { + OEngine::Physic::PhysicActor* act = it->second; + bool cmode = act->getCollisionMode(); + if(cmode) + { + act->enableCollisions(false); + act->setGravity(0.); + act->setVerticalVelocity(0); + mFreeFly = true; + return false; + } + else + { + mFreeFly = false; + act->enableCollisions(true); + act->setGravity(4.); + act->setVerticalVelocity(0); + return true; + } + } + + return false; // This should never happen, but it shall not bother us now, since + // this part of the code needs a rewrite anyway. + } + +} diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp new file mode 100644 index 000000000..57e3f363d --- /dev/null +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -0,0 +1,45 @@ +#ifndef GAME_MWWORLD_PHYSICSSYSTEM_H +#define GAME_MWWORLD_PHYSICSSYSTEM_H + +#include +#include +#include + +namespace MWWorld +{ + + class PhysicsSystem + { + public: + PhysicsSystem (OEngine::Render::OgreRenderer &_rend , OEngine::Physic::PhysicEngine* physEng); + ~PhysicsSystem (); + + std::vector< std::pair > doPhysics (float duration, + const std::vector >& actors); + + void addObject (const std::string& handle, const std::string& mesh, + const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position); + + void addActor (const std::string& handle, const std::string& mesh, + const Ogre::Vector3& position); + + void removeObject (const std::string& handle); + + void moveObject (const std::string& handle, const Ogre::Vector3& position, bool updatePhysics); + + void rotateObject (const std::string& handle, const Ogre::Quaternion& rotation); + + void scaleObject (const std::string& handle, float scale); + + bool toggleCollisionMode(); + + private: + OEngine::Render::OgreRenderer &mRender; + OEngine::Physic::PhysicEngine* mEngine; + bool mFreeFly; + + }; + +} + +#endif diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 259348938..8b9bc747b 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -17,6 +17,7 @@ namespace MWWorld mMale = !(player->flags & ESM::NPC::Female); mRace = player->race; mPlayer.ref.pos.pos[0] = mPlayer.ref.pos.pos[1] = mPlayer.ref.pos.pos[2] = 0; + std::cout << renderer->getHandle(); mPlayer.mData.setHandle (renderer->getHandle()); mClass = new ESM::Class (*world.getStore().classes.find (player->cls)); } diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp new file mode 100644 index 000000000..a6d06a75c --- /dev/null +++ b/apps/openmw/mwworld/scene.cpp @@ -0,0 +1,220 @@ +#include "scene.hpp" +#include "world.hpp" + +#include "../mwrender/interior.hpp" +#include "../mwrender/exterior.hpp" + +#include "../mwmechanics/mechanicsmanager.hpp" + +#include "../mwsound/soundmanager.hpp" + +#include "ptr.hpp" +#include "environment.hpp" +#include "player.hpp" + +#include "doingphysics.hpp" +#include "cellfunctors.hpp" + + +namespace MWWorld +{ + + void Scene::unloadCell (CellRenderCollection::iterator iter) + { + ListHandles functor; + iter->first->forEach(functor); + + { // silence annoying g++ warning + for (std::vector::const_iterator iter (functor.mHandles.begin()); + iter!=functor.mHandles.end(); ++iter) + mPhysics->removeObject (*iter); + } + + mWorld->removeScripts (iter->first); + + mEnvironment.mMechanicsManager->dropActors (iter->first); // FIXME: gehört in world? + mEnvironment.mSoundManager->stopSound (iter->first); // FIXME: same + delete iter->second; + mActiveCells.erase (iter); + } + + void Scene::loadCell (Ptr::CellStore *cell, MWRender::CellRender *render) + { + // register local scripts + mWorld->insertInteriorScripts (*cell); + + // This connects the cell data with the rendering scene. + std::pair result = + mActiveCells.insert (std::make_pair (cell, render)); + + if (result.second) + { + // Load the cell and insert it into the renderer + result.first->second->show(); + } + } + + void Scene::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, + bool adjustPlayerPos) + { + if (adjustPlayerPos) + mWorld->getPlayer().setPos (position.pos[0], position.pos[1], position.pos[2], false); + + mWorld->getPlayer().setCell (cell); + // TODO orientation + mEnvironment.mMechanicsManager->addActor (mWorld->getPlayer().getPlayer()); + mEnvironment.mMechanicsManager->watchActor (mWorld->getPlayer().getPlayer()); + } + + void Scene::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos) + { + SuppressDoingPhysics scopeGuard; + + // remove active + mEnvironment.mMechanicsManager->removeActor (mWorld->getPlayer().getPlayer()); + + CellRenderCollection::iterator active = mActiveCells.begin(); + + while (active!=mActiveCells.end()) + { + if (!(active->first->cell->data.flags & ESM::Cell::Interior)) + { + if (std::abs (X-active->first->cell->data.gridX)<=1 && + std::abs (Y-active->first->cell->data.gridY)<=1) + { + // keep cells within the new 3x3 grid + ++active; + continue; + } + } + + unloadCell (active++); + } + + // Load cells + for (int x=X-1; x<=X+1; ++x) + for (int y=Y-1; y<=Y+1; ++y) + { + CellRenderCollection::iterator iter = mActiveCells.begin(); + + while (iter!=mActiveCells.end()) + { + assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); + + if (x==iter->first->cell->data.gridX && + y==iter->first->cell->data.gridY) + break; + + ++iter; + } + + if (iter==mActiveCells.end()) + { + mWorld->getExterior(x, y)->loadExt (x, y, mWorld->getStore(), mWorld->getEsmReader()); + Ptr::CellStore *cell = mWorld->getExterior(x, y); + + loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene, mPhysics)); + } + } + + // find current cell + CellRenderCollection::iterator iter = mActiveCells.begin(); + + while (iter!=mActiveCells.end()) + { + assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); + + if (X==iter->first->cell->data.gridX && + Y==iter->first->cell->data.gridY) + break; + + ++iter; + } + + assert (iter!=mActiveCells.end()); + + mCurrentCell = iter->first; + + // adjust player + playerCellChange (mWorld->getExterior(X, Y), position, adjustPlayerPos); + + // Sky system + mWorld->adjustSky(); + + mCellChanged = true; + } + + Scene::Scene (Environment& environment, World *world, MWRender::MWScene& scene, PhysicsSystem *physics) + : mScene (scene), mCurrentCell (0), + mCellChanged (false), mEnvironment (environment), mWorld(world), mPhysics(physics) + { + } + + Scene::~Scene() + { + /*for (CellRenderCollection::iterator iter (mActiveCells.begin()); + iter!=mActiveCells.end(); ++iter) + delete iter->second;*/ + } + + bool Scene::hasCellChanged() const + { + return mCellChanged; + } + + std::map Scene::getActiveCells () + { + return mActiveCells; + } + + void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) + { + SuppressDoingPhysics scopeGuard; + + // remove active + CellRenderCollection::iterator active = mActiveCells.begin(); + + while (active!=mActiveCells.end()) + { + unloadCell (active++); + } + + // Load cell. + std::cout << "cellName:" << cellName << std::endl; + mWorld->getInterior(cellName)->loadInt (cellName, mWorld->getStore(), mWorld->getEsmReader()); + Ptr::CellStore *cell = mWorld->getInterior(cellName); + + loadCell (cell, new MWRender::InteriorCellRender (*cell, mEnvironment, mScene, mPhysics)); + + // adjust player + mCurrentCell = cell; + playerCellChange (cell, position); + + // Sky system + mWorld->adjustSky(); + + mCellChanged = true; + //currentRegion->name = ""; + } + + void Scene::changeToExteriorCell (const ESM::Position& position) + { + int x = 0; + int y = 0; + + mWorld->positionToIndex (position.pos[0], position.pos[1], x, y); + + changeCell (x, y, position, true); + } + + Ptr::CellStore* Scene::getCurrentCell () + { + return mCurrentCell; + } + + void Scene::markCellAsUnchanged() + { + mCellChanged = false; + } +} + diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp new file mode 100644 index 000000000..c6d996364 --- /dev/null +++ b/apps/openmw/mwworld/scene.hpp @@ -0,0 +1,104 @@ +#ifndef GAME_MWWORLD_SCENE_H +#define GAME_MWWORLD_SCENE_H + +#include +#include + +#include + +#include + +#include "../mwrender/mwscene.hpp" +#include "physicssystem.hpp" + +#include "refdata.hpp" +#include "ptr.hpp" +#include "globals.hpp" + +#include + +namespace Ogre +{ + class Vector3; +} + +namespace ESM +{ + struct Position; +} + +namespace Files +{ + class Collections; +} + +namespace Render +{ + class OgreRenderer; +} + +namespace MWRender +{ + class SkyManager; + class CellRender; +} + +namespace MWWorld +{ + class Environment; + class Player; + + class Scene + { + + public: + + private: + + typedef std::map CellRenderCollection; + + MWRender::MWScene mScene; + Ptr::CellStore *mCurrentCell; // the cell, the player is in + CellRenderCollection mActiveCells; + bool mCellChanged; + Environment& mEnvironment; + World *mWorld; + PhysicsSystem *mPhysics; + + + void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, + bool adjustPlayerPos = true); + public: + + Scene (Environment& environment, World *world, MWRender::MWScene& scene, PhysicsSystem *physics); + + ~Scene(); + + void unloadCell (CellRenderCollection::iterator iter); + + void loadCell (Ptr::CellStore *cell, MWRender::CellRender *render); + + void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos); + ///< Move from exterior to interior or from interior cell to a different + /// interior cell. + + Ptr::CellStore* getCurrentCell (); + + CellRenderCollection getActiveCells (); + + bool hasCellChanged() const; + ///< Has the player moved to a different cell, since the last frame? + + void changeToInteriorCell (const std::string& cellName, const ESM::Position& position); + ///< Move to interior cell. + + void changeToExteriorCell (const ESM::Position& position); + ///< Move to exterior cell. + + void markCellAsUnchanged(); + + std::string getFacedHandle(); + }; +} + +#endif diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 063f54d6f..abb1cf5ba 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -1,4 +1,3 @@ - #include "world.hpp" #include @@ -221,18 +220,12 @@ namespace MWWorld MWRender::CellRender *World::searchRender (Ptr::CellStore *store) { - CellRenderCollection::iterator iter = mActiveCells.find (store); + CellRenderCollection::iterator iter = mWorldScene->getActiveCells().find (store); - if (iter!=mActiveCells.end()) + if (iter!=mWorldScene->getActiveCells().end()) { return iter->second; } - else - { - iter = mBufferedCells.find (store); - if (iter!=mBufferedCells.end()) - return iter->second; - } return 0; } @@ -271,52 +264,6 @@ namespace MWWorld } } - void World::unloadCell (CellRenderCollection::iterator iter) - { - ListHandles functor; - iter->first->forEach(functor); - - { // silence annoying g++ warning - for (std::vector::const_iterator iter (functor.mHandles.begin()); - iter!=functor.mHandles.end(); ++iter) - mScene.removeObject (*iter); - } - - removeScripts (iter->first); - mEnvironment.mMechanicsManager->dropActors (iter->first); - mEnvironment.mSoundManager->stopSound (iter->first); - delete iter->second; - mActiveCells.erase (iter); - } - - void World::loadCell (Ptr::CellStore *cell, MWRender::CellRender *render) - { - // register local scripts - insertInteriorScripts (*cell); - - // This connects the cell data with the rendering scene. - std::pair result = - mActiveCells.insert (std::make_pair (cell, render)); - - if (result.second) - { - // Load the cell and insert it into the renderer - result.first->second->show(); - } - } - - void World::playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, - bool adjustPlayerPos) - { - if (adjustPlayerPos) - mPlayer->setPos (position.pos[0], position.pos[1], position.pos[2], false); - - mPlayer->setCell (cell); - // TODO orientation - mEnvironment.mMechanicsManager->addActor (mPlayer->getPlayer()); - mEnvironment.mMechanicsManager->watchActor (mPlayer->getPlayer()); - } - void World::adjustSky() { @@ -328,92 +275,16 @@ namespace MWWorld } } - void World::changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos) - { - SuppressDoingPhysics scopeGuard; - - // remove active - mEnvironment.mMechanicsManager->removeActor (mPlayer->getPlayer()); - - CellRenderCollection::iterator active = mActiveCells.begin(); - - while (active!=mActiveCells.end()) - { - if (!(active->first->cell->data.flags & ESM::Cell::Interior)) - { - if (std::abs (X-active->first->cell->data.gridX)<=1 && - std::abs (Y-active->first->cell->data.gridY)<=1) - { - // keep cells within the new 3x3 grid - ++active; - continue; - } - } - - unloadCell (active++); - } - - // Load cells - for (int x=X-1; x<=X+1; ++x) - for (int y=Y-1; y<=Y+1; ++y) - { - CellRenderCollection::iterator iter = mActiveCells.begin(); - - while (iter!=mActiveCells.end()) - { - assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); - - if (x==iter->first->cell->data.gridX && - y==iter->first->cell->data.gridY) - break; - - ++iter; - } - - if (iter==mActiveCells.end()) - { - mExteriors[std::make_pair (x, y)].loadExt (x, y, mStore, mEsm); - Ptr::CellStore *cell = &mExteriors[std::make_pair (x, y)]; - - loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene)); - } - } - - // find current cell - CellRenderCollection::iterator iter = mActiveCells.begin(); - - while (iter!=mActiveCells.end()) - { - assert (!(iter->first->cell->data.flags & ESM::Cell::Interior)); - - if (X==iter->first->cell->data.gridX && - Y==iter->first->cell->data.gridY) - break; - - ++iter; - } - - assert (iter!=mActiveCells.end()); - - mCurrentCell = iter->first; - - // adjust player - playerCellChange (&mExteriors[std::make_pair (X, Y)], position, adjustPlayerPos); - - // Sky system - adjustSky(); - - mCellChanged = true; - } - World::World (OEngine::Render::OgreRenderer& renderer, OEngine::Physic::PhysicEngine* physEng, const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, bool newGame, Environment& environment, const std::string& encoding) - : mSkyManager (0), mScene (renderer,physEng), mPlayer (0), mCurrentCell (0), mGlobalVariables (0), - mSky (false), mCellChanged (false), mEnvironment (environment), mNextDynamicRecord (0) + : mSkyManager (0), mScene (renderer,physEng), mPlayer (0), mGlobalVariables (0), + mSky (false), mEnvironment (environment), mNextDynamicRecord (0) { mPhysEngine = physEng; + + mPhysics = new PhysicsSystem(renderer, physEng); boost::filesystem::path masterPath (fileCollections.getCollection (".esm").getPath (master)); @@ -425,7 +296,7 @@ namespace MWWorld mStore.load (mEsm); mPlayer = new MWWorld::Player (mScene.getPlayer(), mStore.npcs.find ("player"), *this); - mScene.addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0)); + mPhysics->addActor (mPlayer->getPlayer().getRefData().getHandle(), "", Ogre::Vector3 (0, 0, 0)); // global variables mGlobalVariables = new Globals (mStore); @@ -440,21 +311,51 @@ namespace MWWorld MWRender::SkyManager::create(renderer.getWindow(), mScene.getCamera(), resDir); mPhysEngine = physEng; + + mWorldScene = new Scene(environment, this, mScene, mPhysics); } World::~World() { - for (CellRenderCollection::iterator iter (mActiveCells.begin()); - iter!=mActiveCells.end(); ++iter) - delete iter->second; - - for (CellRenderCollection::iterator iter (mBufferedCells.begin()); - iter!=mBufferedCells.end(); ++iter) - delete iter->second; - delete mPlayer; delete mSkyManager; delete mGlobalVariables; + //delete mWorldScene; + delete mPhysics; + } + + const ESM::Cell *World::getExterior (const std::string& cellName) const + { + // first try named cells + if (const ESM::Cell *cell = mStore.cells.searchExtByName (cellName)) + return cell; + + // didn't work -> now check for regions + std::string cellName2 = ESMS::RecListT::toLower (cellName); + + for (ESMS::RecListT::MapType::const_iterator iter (mStore.regions.list.begin()); + iter!=mStore.regions.list.end(); ++iter) + { + if (ESMS::RecListT::toLower (iter->second.name)==cellName2) + { + if (const ESM::Cell *cell = mStore.cells.searchExtByRegion (iter->first)) + return cell; + + break; + } + } + + return 0; + } + + Ptr::CellStore *World::getExterior (int x, int y) + { + return &mExteriors[std::make_pair (x, y)]; + } + + Ptr::CellStore *World::getInterior (std::string name) + { + return &mInteriors[name]; } MWWorld::Player& World::getPlayer() @@ -466,6 +367,11 @@ namespace MWWorld { return mStore; } + + ESM::ESMReader& World::getEsmReader() + { + return mEsm; + } const World::ScriptList& World::getLocalScripts() const { @@ -474,7 +380,7 @@ namespace MWWorld bool World::hasCellChanged() const { - return mCellChanged; + return mWorldScene->hasCellChanged(); } Globals::Data& World::getGlobalVariable (const std::string& name) @@ -501,8 +407,8 @@ namespace MWWorld } // active cells - for (CellRenderCollection::iterator iter (mActiveCells.begin()); - iter!=mActiveCells.end(); ++iter) + for (CellRenderCollection::iterator iter (mWorldScene->getActiveCells().begin()); + iter!=mWorldScene->getActiveCells().end(); ++iter) { Ptr ptr = getPtr (name, *iter->first); @@ -523,8 +429,8 @@ namespace MWWorld if (mPlayer->getPlayer().getRefData().getHandle()==handle) return mPlayer->getPlayer(); - for (CellRenderCollection::iterator iter (mActiveCells.begin()); - iter!=mActiveCells.end(); ++iter) + for (CellRenderCollection::iterator iter (mWorldScene->getActiveCells().begin()); + iter!=mWorldScene->getActiveCells().end(); ++iter) { Ptr ptr = getPtrViaHandle (handle, *iter->first); @@ -545,7 +451,7 @@ namespace MWWorld { render->enable (reference.getRefData().getHandle()); - if (mActiveCells.find (reference.getCell())!=mActiveCells.end()) + if (mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end()) Class::get (reference).enable (reference, mEnvironment); } } @@ -561,7 +467,7 @@ namespace MWWorld { render->disable (reference.getRefData().getHandle()); - if (mActiveCells.find (reference.getCell())!=mActiveCells.end()) + if (mWorldScene->getActiveCells().find (reference.getCell())!=mWorldScene->getActiveCells().end()) { Class::get (reference).disable (reference, mEnvironment); mEnvironment.mSoundManager->stopSound3D (reference); @@ -694,70 +600,17 @@ namespace MWWorld void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position) { - SuppressDoingPhysics scopeGuard; - - // remove active - CellRenderCollection::iterator active = mActiveCells.begin(); - - while (active!=mActiveCells.end()) - { - unloadCell (active++); - } - - // Load cell. - mInteriors[cellName].loadInt (cellName, mStore, mEsm); - Ptr::CellStore *cell = &mInteriors[cellName]; - - loadCell (cell, new MWRender::InteriorCellRender (*cell, mEnvironment, mScene)); - - // adjust player - mCurrentCell = cell; - playerCellChange (cell, position); - - // Sky system - adjustSky(); - - mCellChanged = true; - //currentRegion->name = ""; + return mWorldScene->changeToInteriorCell(cellName, position); } void World::changeToExteriorCell (const ESM::Position& position) { - int x = 0; - int y = 0; - - positionToIndex (position.pos[0], position.pos[1], x, y); - - changeCell (x, y, position, true); - } - - const ESM::Cell *World::getExterior (const std::string& cellName) const - { - // first try named cells - if (const ESM::Cell *cell = mStore.cells.searchExtByName (cellName)) - return cell; - - // didn't work -> now check for regions - std::string cellName2 = ESMS::RecListT::toLower (cellName); - - for (ESMS::RecListT::MapType::const_iterator iter (mStore.regions.list.begin()); - iter!=mStore.regions.list.end(); ++iter) - { - if (ESMS::RecListT::toLower (iter->second.name)==cellName2) - { - if (const ESM::Cell *cell = mStore.cells.searchExtByRegion (iter->first)) - return cell; - - break; - } - } - - return 0; + return mWorldScene->changeToExteriorCell(position); } void World::markCellAsUnchanged() { - mCellChanged = false; + return mWorldScene->markCellAsUnchanged(); } std::string World::getFacedHandle() @@ -779,13 +632,13 @@ namespace MWWorld if (MWRender::CellRender *render = searchRender (ptr.getCell())) { - if (mActiveCells.find (ptr.getCell())!=mActiveCells.end()) + if (mWorldScene->getActiveCells().find (ptr.getCell())!=mWorldScene->getActiveCells().end()) { Class::get (ptr).disable (ptr, mEnvironment); mEnvironment.mSoundManager->stopSound3D (ptr); if (!DoingPhysics::isDoingPhysics()) - mScene.removeObject (ptr.getRefData().getHandle()); + mPhysics->removeObject (ptr.getRefData().getHandle()); } render->deleteObject (ptr.getRefData().getHandle()); @@ -794,7 +647,7 @@ namespace MWWorld } } - void World::moveObject (Ptr ptr, float x, float y, float z) + void World::moveObjectImp (Ptr ptr, float x, float y, float z) { ptr.getCellRef().pos.pos[0] = x; ptr.getCellRef().pos.pos[1] = y; @@ -802,9 +655,10 @@ namespace MWWorld if (ptr==mPlayer->getPlayer()) { - if (mCurrentCell) + Ptr::CellStore *currentCell = mWorldScene->getCurrentCell(); + if (currentCell) { - if (!(mCurrentCell->cell->data.flags & ESM::Cell::Interior)) + if (!(currentCell->cell->data.flags & ESM::Cell::Interior)) { // exterior -> adjust loaded cells int cellX = 0; @@ -812,16 +666,21 @@ namespace MWWorld positionToIndex (x, y, cellX, cellY); - if (mCurrentCell->cell->data.gridX!=cellX || mCurrentCell->cell->data.gridY!=cellY) + if (currentCell->cell->data.gridX!=cellX || currentCell->cell->data.gridY!=cellY) { - changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos, false); + mWorldScene->changeCell (cellX, cellY, mPlayer->getPlayer().getCellRef().pos, false); } } } } + } - mScene.moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z), + void World::moveObject (Ptr ptr, float x, float y, float z) + { + moveObjectImp(ptr, x, y, z); + + mPhysics->moveObject (ptr.getRefData().getHandle(), Ogre::Vector3 (x, y, z), !DoingPhysics::isDoingPhysics()); // TODO cell change for non-player ref @@ -859,7 +718,12 @@ namespace MWWorld void World::doPhysics (const std::vector >& actors, float duration) { - mScene.doPhysics (duration, *this, actors); + std::vector< std::pair > vectors = mPhysics->doPhysics (duration, actors); + std::vector< std::pair >::iterator it; + for(it = vectors.begin(); it != vectors.end(); it++) { + MWWorld::Ptr ptr = getPtrViaHandle (it->first); + moveObject (ptr, it->second.x, it->second.y, it->second.z); + } } bool World::toggleCollisionMode() @@ -904,3 +768,4 @@ namespace MWWorld return std::make_pair (stream.str(), created); } } + diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index cccd8816d..d59474295 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -13,6 +13,8 @@ #include "refdata.hpp" #include "ptr.hpp" #include "globals.hpp" +#include "scene.hpp" +#include "physicssystem.hpp" #include @@ -66,20 +68,19 @@ namespace MWWorld MWRender::SkyManager* mSkyManager; MWRender::MWScene mScene; + MWWorld::Scene *mWorldScene; MWWorld::Player *mPlayer; - Ptr::CellStore *mCurrentCell; // the cell, the player is in - CellRenderCollection mActiveCells; - CellRenderCollection mBufferedCells; // loaded, but not active (buffering not implementd yet) ESM::ESMReader mEsm; ESMS::ESMStore mStore; - std::map mInteriors; - std::map, Ptr::CellStore> mExteriors; ScriptList mLocalScripts; MWWorld::Globals *mGlobalVariables; + MWWorld::PhysicsSystem *mPhysics; bool mSky; - bool mCellChanged; Environment& mEnvironment; int mNextDynamicRecord; + + std::map mInteriors; + std::map, Ptr::CellStore> mExteriors; OEngine::Physic::PhysicEngine* mPhysEngine; @@ -87,8 +88,6 @@ namespace MWWorld World (const World&); World& operator= (const World&); - void insertInteriorScripts (ESMS::CellStore& cell); - Ptr getPtr (const std::string& name, Ptr::CellStore& cellStore); Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore); @@ -96,21 +95,9 @@ namespace MWWorld MWRender::CellRender *searchRender (Ptr::CellStore *store); int getDaysPerMonth (int month) const; - - void removeScripts (Ptr::CellStore *cell); - - void unloadCell (CellRenderCollection::iterator iter); - - void loadCell (Ptr::CellStore *cell, MWRender::CellRender *render); - - void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position, - bool adjustPlayerPos = true); - - void adjustSky(); - - void changeCell (int X, int Y, const ESM::Position& position, bool adjustPlayerPos); - ///< Move from exterior to interior or from interior cell to a different - /// interior cell. + + void moveObjectImp (Ptr ptr, float x, float y, float z); + public: World (OEngine::Render::OgreRenderer& renderer, OEngine::Physic::PhysicEngine* physEng, @@ -119,10 +106,22 @@ namespace MWWorld Environment& environment, const std::string& encoding); ~World(); + + Ptr::CellStore *getExterior (int x, int y); + + Ptr::CellStore *getInterior (std::string name); + + void removeScripts (Ptr::CellStore *cell); + + void insertInteriorScripts (ESMS::CellStore& cell); + + void adjustSky(); MWWorld::Player& getPlayer(); const ESMS::ESMStore& getStore() const; + + ESM::ESMReader& getEsmReader(); const ScriptList& getLocalScripts() const; ///< Names and local variable state of all local scripts in active cells.