From d52e2f68cdd8c14a740d8174dac77a3f2e376146 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 20 Aug 2010 12:52:51 +0200 Subject: [PATCH 01/16] added searchExt function to cell RecList --- components/esm_store/reclists.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index 3cdb7f7b2..3711a20b1 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -194,6 +194,21 @@ namespace ESMS return it->second; } + const Cell *searchExt (int x, int y) const + { + ExtCells::const_iterator it = extCells.find (x); + + if (it==extCells.end()) + return 0; + + ExtCellsCol::const_iterator it2 = it->second.find (y); + + if (it2 == it->second.end()) + return 0; + + return it2->second; + } + void load(ESMReader &esm, const std::string &id) { using namespace std; From 6583b66e823d0c72b2c372b7515198d886395167 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 20 Aug 2010 13:06:01 +0200 Subject: [PATCH 02/16] added load function for exteriors to cell sstore --- components/esm_store/cell_store.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/components/esm_store/cell_store.hpp b/components/esm_store/cell_store.hpp index d4d7cc2f8..2f0dfc407 100644 --- a/components/esm_store/cell_store.hpp +++ b/components/esm_store/cell_store.hpp @@ -124,7 +124,14 @@ namespace ESMS /** Ditto for exterior cell. */ void loadExt(int X, int Y, const ESMStore &store, ESMReader &esm) { + std::cout << "loading exterior cell '" << X << ", " << Y << "'\n"; + cell = store.cells.searchExt (X, Y); + + if(cell == NULL) + throw str_exception("Exterior cell not found"); + + loadRefs(store, esm); } private: From 0111631ee98122144053f8d3bbab72c4779c019e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 20 Aug 2010 13:33:03 +0200 Subject: [PATCH 03/16] very early implementation of exterior rendering --- apps/openmw/CMakeLists.txt | 2 + apps/openmw/mwrender/exterior.cpp | 241 ++++++++++++++++++++++++ apps/openmw/mwrender/exterior.hpp | 114 +++++++++++ apps/openmw/mwrender/interior.hpp | 2 - apps/openmw/mwscript/cellextensions.cpp | 53 ++++-- apps/openmw/mwscript/docs/vmformat.txt | 3 +- apps/openmw/mwworld/world.cpp | 64 +++++++ apps/openmw/mwworld/world.hpp | 5 + 8 files changed, 469 insertions(+), 15 deletions(-) create mode 100644 apps/openmw/mwrender/exterior.cpp create mode 100644 apps/openmw/mwrender/exterior.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index b5948aaea..95cc4179e 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -13,12 +13,14 @@ set(GAMEREND mwrender/mwscene.cpp mwrender/cellimp.cpp mwrender/interior.cpp + mwrender/exterior.cpp mwrender/sky.cpp) set(GAMEREND_HEADER mwrender/cell.hpp mwrender/cellimp.hpp mwrender/mwscene.hpp mwrender/interior.hpp + mwrender/exterior.hpp mwrender/playerpos.hpp mwrender/sky.hpp) source_group(apps\\openmw\\mwrender FILES ${GAMEREND} ${GAMEREND_HEADER}) diff --git a/apps/openmw/mwrender/exterior.cpp b/apps/openmw/mwrender/exterior.cpp new file mode 100644 index 000000000..58c783d72 --- /dev/null +++ b/apps/openmw/mwrender/exterior.cpp @@ -0,0 +1,241 @@ +#include "exterior.hpp" + +#include +#include +#include +#include +#include + +#include +#include "mwscene.hpp" + +using namespace MWRender; +using namespace Ogre; +using namespace ESMS; + +bool ExteriorCellRender::lightConst = false; +float ExteriorCellRender::lightConstValue = 0.0f; + +bool ExteriorCellRender::lightLinear = true; +int ExteriorCellRender::lightLinearMethod = 1; +float ExteriorCellRender::lightLinearValue = 3; +float ExteriorCellRender::lightLinearRadiusMult = 1; + +bool ExteriorCellRender::lightQuadratic = false; +int ExteriorCellRender::lightQuadraticMethod = 2; +float ExteriorCellRender::lightQuadraticValue = 16; +float ExteriorCellRender::lightQuadraticRadiusMult = 1; + +bool ExteriorCellRender::lightOutQuadInLin = false; + +// start inserting a new reference. + +void ExteriorCellRender::insertBegin (ESM::CellRef &ref) +{ + assert (!insert); + + // Create and place scene node for this object + insert = base->createChildSceneNode(); + + const float *f = ref.pos.pos; + insert->setPosition(f[0], f[1], f[2]); + insert->setScale(ref.scale, ref.scale, ref.scale); + + // Convert MW rotation to a quaternion: + f = ref.pos.rot; + + // Rotate around X axis + Quaternion xr(Radian(-f[0]), Vector3::UNIT_X); + + // Rotate around Y axis + Quaternion yr(Radian(-f[1]), Vector3::UNIT_Y); + + // Rotate around Z axis + Quaternion zr(Radian(-f[2]), Vector3::UNIT_Z); + + // Rotates first around z, then y, then x + insert->setOrientation(xr*yr*zr); +} + +// insert a mesh related to the most recent insertBegin call. + +void ExteriorCellRender::insertMesh(const std::string &mesh) +{ + assert (insert); + + NIFLoader::load(mesh); + MovableObject *ent = scene.getMgr()->createEntity(mesh); + insert->attachObject(ent); +} + +// insert a light related to the most recent insertBegin call. +void ExteriorCellRender::insertLight(float r, float g, float b, float radius) +{ + assert (insert); + + Ogre::Light *light = scene.getMgr()->createLight(); + light->setDiffuseColour (r, g, b); + + float cval=0.0f, lval=0.0f, qval=0.0f; + + if(lightConst) + cval = lightConstValue; + if(!lightOutQuadInLin) + { + if(lightLinear) + radius *= lightLinearRadiusMult; + if(lightQuadratic) + radius *= lightQuadraticRadiusMult; + + if(lightLinear) + lval = lightLinearValue / pow(radius, lightLinearMethod); + if(lightQuadratic) + qval = lightQuadraticValue / pow(radius, lightQuadraticMethod); + } + else + { + // FIXME: + // Do quadratic or linear, depending if we're in an exterior or interior + // cell, respectively. Ignore lightLinear and lightQuadratic. + } + + light->setAttenuation(10*radius, cval, lval, qval); + + insert->attachObject(light); +} + +// finish inserting a new reference and return a handle to it. + +std::string ExteriorCellRender::insertEnd (bool enable) +{ + assert (insert); + + std::string handle = insert->getName(); + + if (!enable) + insert->setVisible (false); + + insert = 0; + + return handle; +} + +// configure lighting according to cell + +void ExteriorCellRender::configureAmbient() +{ + ambientColor.setAsABGR (cell.cell->ambi.ambient); + setAmbientMode(); + + // Create a "sun" that shines light downwards. It doesn't look + // completely right, but leave it for now. + Ogre::Light *light = scene.getMgr()->createLight(); + Ogre::ColourValue colour; + colour.setAsABGR (cell.cell->ambi.sunlight); + light->setDiffuseColour (colour); + light->setType(Ogre::Light::LT_DIRECTIONAL); + light->setDirection(0,-1,0); +} + +// configure fog according to cell +void ExteriorCellRender::configureFog() +{ + Ogre::ColourValue color; + color.setAsABGR (cell.cell->ambi.fog); + + float high = 4500 + 9000 * (1-cell.cell->ambi.fogDensity); + float low = 200; + + scene.getMgr()->setFog (FOG_LINEAR, color, 0, low, high); + scene.getCamera()->setFarClipDistance (high + 10); + scene.getViewport()->setBackgroundColour (color); +} + +void ExteriorCellRender::setAmbientMode() +{ + switch (ambientMode) + { + case 0: + + scene.getMgr()->setAmbientLight(ambientColor); + break; + + case 1: + + scene.getMgr()->setAmbientLight(0.7f*ambientColor + 0.3f*ColourValue(1,1,1)); + break; + + case 2: + + scene.getMgr()->setAmbientLight(ColourValue(1,1,1)); + break; + } +} + +void ExteriorCellRender::show() +{ + base = scene.getRoot()->createChildSceneNode(); + + configureAmbient(); + configureFog(); + + insertCell(cell, mEnvironment); +} + +void ExteriorCellRender::hide() +{ + if(base) + base->setVisible(false); +} + +void ExteriorCellRender::destroy() +{ + if(base) + { + base->removeAndDestroyAllChildren(); + scene.getMgr()->destroySceneNode(base); + } + + base = NULL; +} + +// Switch through lighting modes. + +void ExteriorCellRender::toggleLight() +{ + if (ambientMode==2) + ambientMode = 0; + else + ++ambientMode; + + switch (ambientMode) + { + case 0: std::cout << "Setting lights to normal\n"; break; + case 1: std::cout << "Turning the lights up\n"; break; + case 2: std::cout << "Turning the lights to full\n"; break; + } + + setAmbientMode(); +} + +void ExteriorCellRender::enable (const std::string& handle) +{ + if (!handle.empty()) + scene.getMgr()->getSceneNode (handle)->setVisible (true); +} + +void ExteriorCellRender::disable (const std::string& handle) +{ + if (!handle.empty()) + scene.getMgr()->getSceneNode (handle)->setVisible (false); +} + +void ExteriorCellRender::deleteObject (const std::string& handle) +{ + if (!handle.empty()) + { + Ogre::SceneNode *node = scene.getMgr()->getSceneNode (handle); + node->removeAndDestroyAllChildren(); + scene.getMgr()->destroySceneNode (node); + } +} diff --git a/apps/openmw/mwrender/exterior.hpp b/apps/openmw/mwrender/exterior.hpp new file mode 100644 index 000000000..7de027672 --- /dev/null +++ b/apps/openmw/mwrender/exterior.hpp @@ -0,0 +1,114 @@ +#ifndef _GAME_RENDER_EXTERIOR_H +#define _GAME_RENDER_EXTERIOR_H + +#include "cell.hpp" +#include "cellimp.hpp" + +#include "OgreColourValue.h" + +namespace Ogre +{ + class SceneNode; +} + +namespace MWWorld +{ + class Environment; +} + +namespace MWRender +{ + class MWScene; + + /** + This class is responsible for inserting meshes and other + rendering objects from the given cell into the given rendering + scene. + */ + + class ExteriorCellRender : public CellRender, private CellRenderImp + { + + static bool lightConst; + static float lightConstValue; + + static bool lightLinear; + static int lightLinearMethod; + static float lightLinearValue; + static float lightLinearRadiusMult; + + static bool lightQuadratic; + static int lightQuadraticMethod; + static float lightQuadraticValue; + static float lightQuadraticRadiusMult; + + static bool lightOutQuadInLin; + + ESMS::CellStore &cell; + MWWorld::Environment &mEnvironment; + MWScene &scene; + + /// The scene node that contains all objects belonging to this + /// cell. + Ogre::SceneNode *base; + + Ogre::SceneNode *insert; + + // 0 normal, 1 more bright, 2 max + int ambientMode; + + Ogre::ColourValue ambientColor; + + /// start inserting a new reference. + virtual void insertBegin (ESM::CellRef &ref); + + /// insert a mesh related to the most recent insertBegin call. + virtual void insertMesh(const std::string &mesh); + + /// insert a light related to the most recent insertBegin call. + virtual void insertLight(float r, float g, float b, float radius); + + /// finish inserting a new reference and return a handle to it. + virtual std::string insertEnd (bool Enable); + + /// configure lighting according to cell + void configureAmbient(); + + /// configure fog according to cell + void configureFog(); + + void setAmbientMode(); + + public: + + ExteriorCellRender(ESMS::CellStore &_cell, MWWorld::Environment& environment, + MWScene &_scene) + : cell(_cell), mEnvironment (environment), scene(_scene), base(NULL), insert(NULL), ambientMode (0) {} + + virtual ~ExteriorCellRender() { destroy(); } + + /// Make the cell visible. Load the cell if necessary. + virtual void show(); + + /// Remove the cell from rendering, but don't remove it from + /// memory. + virtual void hide(); + + /// Destroy all rendering objects connected with this cell. + virtual void destroy(); // comment by Zini: shouldn't this go into the destructor? + + /// Switch through lighting modes. + void toggleLight(); + + /// Make the reference with the given handle visible. + virtual void enable (const std::string& handle); + + /// Make the reference with the given handle invisible. + virtual void disable (const std::string& handle); + + /// Remove the reference with the given handle permanently from the scene. + virtual void deleteObject (const std::string& handle); + }; +} + +#endif diff --git a/apps/openmw/mwrender/interior.hpp b/apps/openmw/mwrender/interior.hpp index 8d69ca061..ba5089eb5 100644 --- a/apps/openmw/mwrender/interior.hpp +++ b/apps/openmw/mwrender/interior.hpp @@ -24,8 +24,6 @@ namespace MWRender This class is responsible for inserting meshes and other rendering objects from the given cell into the given rendering scene. - - TODO FIXME: Doesn't do full cleanup yet. */ class InteriorCellRender : public CellRender, private CellRenderImp diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 963cb5af8..6171a82d9 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -18,50 +18,79 @@ namespace MWScript class OpCellChanged : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { InterpreterContext& context = static_cast (runtime.getContext()); - + runtime.push (context.getWorld().hasCellChanged() ? 1 : 0); - } + } }; class OpCOC : public Interpreter::Opcode0 { public: - + virtual void execute (Interpreter::Runtime& runtime) { InterpreterContext& context = static_cast (runtime.getContext()); - + std::string cell = runtime.getStringLiteral (runtime[0].mInteger); - runtime.pop(); - + runtime.pop(); + ESM::Position pos; pos.pos[0] = pos.pos[1] = pos.pos[2] = 0; pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; context.getWorld().changeCell (cell, pos); - } + } + }; + + class OpCOE : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + InterpreterContext& context + = static_cast (runtime.getContext()); + + Interpreter::Type_Integer x = runtime[0].mInteger; + runtime.pop(); + + Interpreter::Type_Integer y = runtime[0].mInteger; + runtime.pop(); + + const int cellSize = 8192; + + ESM::Position pos; + pos.pos[0] = cellSize * x; + pos.pos[1] = cellSize * y; + pos.pos[2] = 0; + pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; + context.getWorld().changeToExteriorCell (pos); + } }; - + const int opcodeCellChanged = 0x2000000; const int opcodeCOC = 0x2000026; - + const int opcodeCOE = 0x200007c; + void registerExtensions (Compiler::Extensions& extensions) { extensions.registerFunction ("cellchanged", 'l', "", opcodeCellChanged); extensions.registerInstruction ("coc", "S", opcodeCOC); extensions.registerInstruction ("centeroncell", "S", opcodeCOC); + extensions.registerInstruction ("coe", "ll", opcodeCOE); + extensions.registerInstruction ("centeronexterior", "ll", opcodeCOE); } - + void installOpcodes (Interpreter::Interpreter& interpreter) { interpreter.installSegment5 (opcodeCellChanged, new OpCellChanged); interpreter.installSegment5 (opcodeCOC, new OpCOC); + interpreter.installSegment5 (opcodeCOE, new OpCOE); } } } - diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 70e5fe8c2..c8a23b5bd 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -83,4 +83,5 @@ op 0x2000078: GetItemCount op 0x2000079: GetItemCount, explicit reference op 0x200007a: RemoveItem op 0x200007b: RemoveItem, explicit reference -opcodes 0x200007c-0x3ffffff unused +op 0x200007c: COC +opcodes 0x200007d-0x3ffffff unused diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 4ef20c7ff..38f21d9bc 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -8,6 +8,7 @@ #include "../mwrender/sky.hpp" #include "../mwrender/interior.hpp" +#include "../mwrender/exterior.hpp" #include "../mwmechanics/mechanicsmanager.hpp" @@ -573,6 +574,69 @@ namespace MWWorld mCellChanged = true; } + void World::changeCell (int X, int Y, const ESM::Position& position) + { + // Load cell. + mExteriors[std::make_pair (X, Y)].loadExt (X, Y, mStore, mEsm); + Ptr::CellStore *cell = &mExteriors[std::make_pair (X, Y)]; + + // remove active + CellRenderCollection::iterator active = mActiveCells.begin(); + + if (active!=mActiveCells.end()) + { + mEnvironment.mMechanicsManager->dropActors (active->first); + active->second->destroy(); + mEnvironment.mSoundManager->stopSound (active->first); + delete active->second; + mActiveCells.erase (active); + } + + // register local scripts + mLocalScripts.clear(); // FIXME won't work with exteriors + insertInteriorScripts (*cell); + + // adjust player + mPlayerPos->setPos (position.pos[0], position.pos[1], position.pos[2], true); + mPlayerPos->setCell (cell); + // TODO orientation + + // This connects the cell data with the rendering scene. + std::pair result = + mActiveCells.insert (std::make_pair (cell, + new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene))); + + if (result.second) + { + // Load the cell and insert it into the renderer + result.first->second->show(); + } + + // Actors + mEnvironment.mMechanicsManager->addActor (mPlayerPos->getPlayer()); + mEnvironment.mMechanicsManager->watchActor (mPlayerPos->getPlayer()); + + // Sky system + if (mSky) + { + toggleSky(); + // TODO set weather + toggleSky(); + } + + mCellChanged = true; + } + + void World::changeToExteriorCell (const ESM::Position& position) + { + const int cellSize = 8192; + + int x = static_cast (position.pos[0] / cellSize); + int y = static_cast (position.pos[1] / cellSize); + + changeCell (x, y, position); + } + void World::markCellAsUnchanged() { mCellChanged = false; diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 2a7b8009a..1839ef271 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -56,6 +56,7 @@ namespace MWWorld ESM::ESMReader mEsm; ESMS::ESMStore mStore; std::map mInteriors; + std::map, Ptr::CellStore> mExteriors; ScriptList mLocalScripts; MWWorld::Globals *mGlobalVariables; bool mSky; @@ -130,6 +131,10 @@ namespace MWWorld void changeCell (const std::string& cellName, const ESM::Position& position); ///< works only for interior cells currently. + void changeCell (int X, int Y, const ESM::Position& position); + + void changeToExteriorCell (const ESM::Position& position); + void markCellAsUnchanged(); std::string getFacedHandle(); From bdd5e2f0645760594bff7e64961bdb1bf8c62574 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 20 Aug 2010 14:56:26 +0200 Subject: [PATCH 04/16] modified teleport action to support exteriors; coordinates are wrong here too --- apps/openmw/mwworld/actionteleport.cpp | 5 ++++- apps/openmw/mwworld/actionteleport.hpp | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/actionteleport.cpp b/apps/openmw/mwworld/actionteleport.cpp index 4edc02c30..b9b48f18f 100644 --- a/apps/openmw/mwworld/actionteleport.cpp +++ b/apps/openmw/mwworld/actionteleport.cpp @@ -13,6 +13,9 @@ namespace MWWorld void ActionTeleportPlayer::ActionTeleportPlayer::execute (Environment& environment) { - environment.mWorld->changeCell (mCellName, mPosition); + if (mCellName.empty()) + environment.mWorld->changeToExteriorCell (mPosition); + else + environment.mWorld->changeCell (mCellName, mPosition); } } diff --git a/apps/openmw/mwworld/actionteleport.hpp b/apps/openmw/mwworld/actionteleport.hpp index 78a55fba2..e4c972a9e 100644 --- a/apps/openmw/mwworld/actionteleport.hpp +++ b/apps/openmw/mwworld/actionteleport.hpp @@ -17,6 +17,7 @@ namespace MWWorld public: ActionTeleportPlayer (const std::string& cellName, const ESM::Position& position); + ///< If cellName is empty, an exterior cell is asumed. virtual void execute (Environment& environment); }; From 1f077a5d5ff03a4d183271d8932f78b6ce7e92ab Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 20 Aug 2010 17:14:07 +0200 Subject: [PATCH 05/16] partial coordinates fix (slightly better results when changing cells, but still not completely correct) --- apps/openmw/mwrender/playerpos.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/playerpos.hpp b/apps/openmw/mwrender/playerpos.hpp index 48a4fd8d5..7a1f571ce 100644 --- a/apps/openmw/mwrender/playerpos.hpp +++ b/apps/openmw/mwrender/playerpos.hpp @@ -37,12 +37,12 @@ namespace MWRender if (updateCamera) camera->setPosition (Ogre::Vector3 ( mPlayer.ref.pos.pos[0], - mPlayer.ref.pos.pos[2], + -mPlayer.ref.pos.pos[2], mPlayer.ref.pos.pos[1])); // TODO: Update sound listener } - + void setCell (MWWorld::Ptr::CellStore *cellStore) { mCellStore = cellStore; @@ -54,7 +54,6 @@ namespace MWRender // orientation. After the call, the new position is returned. void moveRel(float &relX, float &relY, float &relZ) { - // TODO: Update mPlayer state using namespace Ogre; // Move camera relative to its own direction @@ -75,7 +74,7 @@ namespace MWRender // Set the position setPos(relX, relY, relZ); } - + MWWorld::Ptr getPlayer() { MWWorld::Ptr ptr (&mPlayer, mCellStore); From c6f4bcbf68416498eafa6e6e0db8f46be29b1f3c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 21 Aug 2010 09:48:56 +0200 Subject: [PATCH 06/16] another coordinate system fix; still not working properly --- apps/openmw/mwrender/playerpos.hpp | 10 +++++----- apps/openmw/mwscript/cellextensions.cpp | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwrender/playerpos.hpp b/apps/openmw/mwrender/playerpos.hpp index 7a1f571ce..7c66c8b4c 100644 --- a/apps/openmw/mwrender/playerpos.hpp +++ b/apps/openmw/mwrender/playerpos.hpp @@ -37,9 +37,9 @@ namespace MWRender if (updateCamera) camera->setPosition (Ogre::Vector3 ( mPlayer.ref.pos.pos[0], - -mPlayer.ref.pos.pos[2], - mPlayer.ref.pos.pos[1])); - + mPlayer.ref.pos.pos[2], + -mPlayer.ref.pos.pos[1])); +std::cout<<"camera: "<getPosition()<getPosition(); relX = pos[0]; - relY = -pos[2]; - relZ = pos[1]; + relY = pos[2]; + relZ = -pos[1]; // TODO: Collision detection must be used to find the REAL new // position. diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 6171a82d9..27251a728 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -65,8 +65,8 @@ namespace MWScript const int cellSize = 8192; ESM::Position pos; - pos.pos[0] = cellSize * x; - pos.pos[1] = cellSize * y; + pos.pos[0] = cellSize * (x+0.5); + pos.pos[1] = cellSize * (y+0.5); pos.pos[2] = 0; pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; context.getWorld().changeToExteriorCell (pos); From b8fee8f1ee0a735d6828ac70e2466d408f5fafad Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 21 Aug 2010 09:58:47 +0200 Subject: [PATCH 07/16] removed stray debugging output --- apps/openmw/mwrender/playerpos.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwrender/playerpos.hpp b/apps/openmw/mwrender/playerpos.hpp index 7c66c8b4c..31c085cc0 100644 --- a/apps/openmw/mwrender/playerpos.hpp +++ b/apps/openmw/mwrender/playerpos.hpp @@ -39,7 +39,6 @@ namespace MWRender mPlayer.ref.pos.pos[0], mPlayer.ref.pos.pos[2], -mPlayer.ref.pos.pos[1])); -std::cout<<"camera: "<getPosition()< Date: Sat, 21 Aug 2010 11:43:07 +0200 Subject: [PATCH 08/16] refactored cell unloading --- apps/openmw/mwworld/world.cpp | 37 +++++++++++++++++++++++------------ apps/openmw/mwworld/world.hpp | 6 +++++- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 38f21d9bc..f6476799f 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -250,6 +250,29 @@ namespace MWWorld throw std::runtime_error ("month out of range"); } + void World::removeScripts (Ptr::CellStore *cell) + { + ScriptList::iterator iter = mLocalScripts.begin(); + + while (iter!=mLocalScripts.end()) + { + if (iter->second.getCell()==cell) + mLocalScripts.erase (iter++); + else + ++iter; + } + } + + void World::unloadCell (CellRenderCollection::iterator iter) + { + removeScripts (iter->first); + mEnvironment.mMechanicsManager->dropActors (iter->first); + iter->second->destroy(); + mEnvironment.mSoundManager->stopSound (iter->first); + delete iter->second; + mActiveCells.erase (iter); + } + World::World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, const std::string& master, bool newGame, Environment& environment) : mSkyManager (0), mScene (renderer), mPlayerPos (0), mCurrentCell (0), mGlobalVariables (0), @@ -532,15 +555,10 @@ namespace MWWorld if (active!=mActiveCells.end()) { - mEnvironment.mMechanicsManager->dropActors (active->first); - active->second->destroy(); - mEnvironment.mSoundManager->stopSound (active->first); - delete active->second; - mActiveCells.erase (active); + unloadCell (active); } // register local scripts - mLocalScripts.clear(); // FIXME won't work with exteriors insertInteriorScripts (*cell); // adjust player @@ -585,15 +603,10 @@ namespace MWWorld if (active!=mActiveCells.end()) { - mEnvironment.mMechanicsManager->dropActors (active->first); - active->second->destroy(); - mEnvironment.mSoundManager->stopSound (active->first); - delete active->second; - mActiveCells.erase (active); + unloadCell (active); } // register local scripts - mLocalScripts.clear(); // FIXME won't work with exteriors insertInteriorScripts (*cell); // adjust player diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 1839ef271..c61ea12ad 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -41,7 +41,7 @@ namespace MWWorld { public: - typedef std::vector > ScriptList; + typedef std::list > ScriptList; private: @@ -77,6 +77,10 @@ namespace MWWorld int getDaysPerMonth (int month) const; + void removeScripts (Ptr::CellStore *cell); + + void unloadCell (CellRenderCollection::iterator iter); + public: World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& master, From 0d2071915896b0dafb8348f07ee867b161736544 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 21 Aug 2010 12:31:04 +0200 Subject: [PATCH 09/16] re-routed player movement through MWWorld::World --- apps/openmw/CMakeLists.txt | 1 + apps/openmw/mwrender/playerpos.hpp | 24 +++++++++--------------- apps/openmw/mwworld/world.cpp | 12 +++++++++++- apps/openmw/mwworld/world.hpp | 2 ++ 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 95cc4179e..48acf94d0 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -14,6 +14,7 @@ set(GAMEREND mwrender/cellimp.cpp mwrender/interior.cpp mwrender/exterior.cpp + mwrender/playerpos.cpp mwrender/sky.cpp) set(GAMEREND_HEADER mwrender/cell.hpp diff --git a/apps/openmw/mwrender/playerpos.hpp b/apps/openmw/mwrender/playerpos.hpp index 31c085cc0..e83ee216d 100644 --- a/apps/openmw/mwrender/playerpos.hpp +++ b/apps/openmw/mwrender/playerpos.hpp @@ -8,6 +8,11 @@ #include "../mwworld/refdata.hpp" #include "../mwworld/ptr.hpp" +namespace MWWorld +{ + class World; +} + namespace MWRender { // This class keeps track of the player position. It takes care of @@ -18,29 +23,18 @@ namespace MWRender ESMS::LiveCellRef mPlayer; MWWorld::Ptr::CellStore *mCellStore; Ogre::Camera *camera; + MWWorld::World& mWorld; public: - PlayerPos(Ogre::Camera *cam, const ESM::NPC *player) : - mCellStore (0), camera(cam) + PlayerPos(Ogre::Camera *cam, const ESM::NPC *player, MWWorld::World& world) : + mCellStore (0), camera(cam), mWorld (world) { mPlayer.base = player; mPlayer.ref.pos.pos[0] = mPlayer.ref.pos.pos[1] = mPlayer.ref.pos.pos[2] = 0; } // Set the player position. Uses Morrowind coordinates. - void setPos(float _x, float _y, float _z, bool updateCamera = false) - { - mPlayer.ref.pos.pos[0] = _x; - mPlayer.ref.pos.pos[1] = _y; - mPlayer.ref.pos.pos[2] = _z; - - if (updateCamera) - camera->setPosition (Ogre::Vector3 ( - mPlayer.ref.pos.pos[0], - mPlayer.ref.pos.pos[2], - -mPlayer.ref.pos.pos[1])); - // TODO: Update sound listener - } + void setPos(float _x, float _y, float _z, bool updateCamera = false); void setCell (MWWorld::Ptr::CellStore *cellStore) { diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index f6476799f..c8c661dd8 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -287,7 +287,7 @@ namespace MWWorld mEsm.open (masterPath.file_string()); mStore.load (mEsm); - mPlayerPos = new MWRender::PlayerPos (mScene.getCamera(), mStore.npcs.find ("player")); + mPlayerPos = new MWRender::PlayerPos (mScene.getCamera(), mStore.npcs.find ("player"), *this); // global variables mGlobalVariables = new Globals (mStore); @@ -685,4 +685,14 @@ namespace MWWorld } } } + + void World::moveObject (Ptr ptr, float x, float y, float z) + { + ptr.getCellRef().pos.pos[0] = x; + ptr.getCellRef().pos.pos[1] = y; + ptr.getCellRef().pos.pos[2] = z; + + // TODO cell change for non-player ref + // TODO cell change for player ref + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index c61ea12ad..608f8fb91 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -145,6 +145,8 @@ namespace MWWorld ///< Return handle of the object the player is looking at void deleteObject (Ptr ptr); + + void moveObject (Ptr ptr, float x, float y, float z); }; } From 033c771be88d4ce30842e2cd35cf75e605e8132b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 21 Aug 2010 12:41:59 +0200 Subject: [PATCH 10/16] load/unload cells while player is moving around in the exteriors --- apps/openmw/mwrender/playerpos.cpp | 18 ++++++++++++++++++ apps/openmw/mwworld/world.cpp | 23 ++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 apps/openmw/mwrender/playerpos.cpp diff --git a/apps/openmw/mwrender/playerpos.cpp b/apps/openmw/mwrender/playerpos.cpp new file mode 100644 index 000000000..4a5e6628f --- /dev/null +++ b/apps/openmw/mwrender/playerpos.cpp @@ -0,0 +1,18 @@ + +#include "playerpos.hpp" + +#include "../mwworld/world.hpp" + +namespace MWRender +{ + void PlayerPos::setPos(float x, float y, float z, bool updateCamera) + { + mWorld.moveObject (getPlayer(), x, y, z); + + if (updateCamera) + camera->setPosition (Ogre::Vector3 ( + mPlayer.ref.pos.pos[0], + mPlayer.ref.pos.pos[2], + -mPlayer.ref.pos.pos[1])); + } +} diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index c8c661dd8..e3a2e6a2a 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -692,7 +692,28 @@ namespace MWWorld ptr.getCellRef().pos.pos[1] = y; ptr.getCellRef().pos.pos[2] = z; + if (ptr==mPlayerPos->getPlayer()) + { + CellRenderCollection::iterator active = mActiveCells.begin(); + + if (active!=mActiveCells.end()) + { + if (!(active->first->cell->data.flags & ESM::Cell::Interior)) + { + // exterior -> adjust loaded cells + const int cellSize = 8192; + + int cellX = static_cast (x/cellSize); + int cellY = static_cast (y/cellSize); + + if (active->first->cell->data.gridX!=cellX || active->first->cell->data.gridY!=cellY) + { + changeCell (cellX, cellY, mPlayerPos->getPlayer().getCellRef().pos); + } + } + } + } + // TODO cell change for non-player ref - // TODO cell change for player ref } } From 0fce36090839f9755205d57ccadaf5662a1cd6d5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 22 Aug 2010 20:55:22 +0200 Subject: [PATCH 11/16] more refactoring --- apps/openmw/mwworld/world.cpp | 111 ++++++++++++++++------------------ apps/openmw/mwworld/world.hpp | 6 ++ 2 files changed, 57 insertions(+), 60 deletions(-) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index e3a2e6a2a..ff8ca7c52 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -273,6 +273,43 @@ namespace MWWorld 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) + { + mPlayerPos->setPos (position.pos[0], position.pos[1], position.pos[2], true); + mPlayerPos->setCell (cell); + // TODO orientation + + mEnvironment.mMechanicsManager->addActor (mPlayerPos->getPlayer()); + mEnvironment.mMechanicsManager->watchActor (mPlayerPos->getPlayer()); + } + + + void World::adjustSky() + { + if (mSky) + { + toggleSky(); + // TODO set weather + toggleSky(); + } + } + World::World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& dataDir, const std::string& master, bool newGame, Environment& environment) : mSkyManager (0), mScene (renderer), mPlayerPos (0), mCurrentCell (0), mGlobalVariables (0), @@ -546,10 +583,6 @@ namespace MWWorld void World::changeCell (const std::string& cellName, const ESM::Position& position) { - // Load cell. - mInteriors[cellName].loadInt (cellName, mStore, mEsm); - Ptr::CellStore *cell = &mInteriors[cellName]; - // remove active CellRenderCollection::iterator active = mActiveCells.begin(); @@ -558,46 +591,23 @@ namespace MWWorld unloadCell (active); } - // register local scripts - insertInteriorScripts (*cell); - - // adjust player - mPlayerPos->setPos (position.pos[0], position.pos[1], position.pos[2], true); - mPlayerPos->setCell (cell); - // TODO orientation - - // This connects the cell data with the rendering scene. - std::pair result = - mActiveCells.insert (std::make_pair (cell, - new MWRender::InteriorCellRender (*cell, mEnvironment, mScene))); + // Load cell. + mInteriors[cellName].loadInt (cellName, mStore, mEsm); + Ptr::CellStore *cell = &mInteriors[cellName]; - if (result.second) - { - // Load the cell and insert it into the renderer - result.first->second->show(); - } + loadCell (cell, new MWRender::InteriorCellRender (*cell, mEnvironment, mScene)); - // Actors - mEnvironment.mMechanicsManager->addActor (mPlayerPos->getPlayer()); - mEnvironment.mMechanicsManager->watchActor (mPlayerPos->getPlayer()); + // adjust player + playerCellChange (cell, position); // Sky system - if (mSky) - { - toggleSky(); - // TODO set weather - toggleSky(); - } + adjustSky(); mCellChanged = true; } void World::changeCell (int X, int Y, const ESM::Position& position) { - // Load cell. - mExteriors[std::make_pair (X, Y)].loadExt (X, Y, mStore, mEsm); - Ptr::CellStore *cell = &mExteriors[std::make_pair (X, Y)]; - // remove active CellRenderCollection::iterator active = mActiveCells.begin(); @@ -606,36 +616,17 @@ namespace MWWorld unloadCell (active); } - // register local scripts - insertInteriorScripts (*cell); - - // adjust player - mPlayerPos->setPos (position.pos[0], position.pos[1], position.pos[2], true); - mPlayerPos->setCell (cell); - // TODO orientation + // Load cell. + mExteriors[std::make_pair (X, Y)].loadExt (X, Y, mStore, mEsm); + Ptr::CellStore *cell = &mExteriors[std::make_pair (X, Y)]; - // This connects the cell data with the rendering scene. - std::pair result = - mActiveCells.insert (std::make_pair (cell, - new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene))); + loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene)); - if (result.second) - { - // Load the cell and insert it into the renderer - result.first->second->show(); - } - - // Actors - mEnvironment.mMechanicsManager->addActor (mPlayerPos->getPlayer()); - mEnvironment.mMechanicsManager->watchActor (mPlayerPos->getPlayer()); + // adjust player + playerCellChange (cell, position); // Sky system - if (mSky) - { - toggleSky(); - // TODO set weather - toggleSky(); - } + adjustSky(); mCellChanged = true; } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 608f8fb91..000d79037 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -81,6 +81,12 @@ namespace MWWorld void unloadCell (CellRenderCollection::iterator iter); + void loadCell (Ptr::CellStore *cell, MWRender::CellRender *render); + + void playerCellChange (Ptr::CellStore *cell, const ESM::Position& position); + + void adjustSky(); + public: World (OEngine::Render::OgreRenderer& renderer, const boost::filesystem::path& master, From 9e8251e6b4f64b99b6e693c494e0d4629d66c9a7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 22 Aug 2010 21:30:48 +0200 Subject: [PATCH 12/16] finally got rid of the nasty coordinates bug --- apps/openmw/mwrender/playerpos.hpp | 4 +-- apps/openmw/mwscript/cellextensions.cpp | 8 +++--- apps/openmw/mwworld/world.cpp | 35 ++++++++++++++++++++----- apps/openmw/mwworld/world.hpp | 6 +++++ 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwrender/playerpos.hpp b/apps/openmw/mwrender/playerpos.hpp index e83ee216d..59a0e1b41 100644 --- a/apps/openmw/mwrender/playerpos.hpp +++ b/apps/openmw/mwrender/playerpos.hpp @@ -58,8 +58,8 @@ namespace MWRender // Get new camera position, converting back to MW coords. Vector3 pos = camera->getPosition(); relX = pos[0]; - relY = pos[2]; - relZ = -pos[1]; + relY = -pos[2]; + relZ = pos[1]; // TODO: Collision detection must be used to find the REAL new // position. diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 27251a728..7d633b59d 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -62,13 +62,13 @@ namespace MWScript Interpreter::Type_Integer y = runtime[0].mInteger; runtime.pop(); - const int cellSize = 8192; - ESM::Position pos; - pos.pos[0] = cellSize * (x+0.5); - pos.pos[1] = cellSize * (y+0.5); + + context.getWorld().indexToPosition (x, y, pos.pos[0], pos.pos[1]); pos.pos[2] = 0; + pos.rot[0] = pos.rot[1] = pos.rot[2] = 0; + context.getWorld().changeToExteriorCell (pos); } }; diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index ff8ca7c52..2c8c4a542 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -633,10 +633,10 @@ namespace MWWorld void World::changeToExteriorCell (const ESM::Position& position) { - const int cellSize = 8192; + int x = 0; + int y = 0; - int x = static_cast (position.pos[0] / cellSize); - int y = static_cast (position.pos[1] / cellSize); + positionToIndex (position.pos[0], position.pos[1], x, y); changeCell (x, y, position); } @@ -692,10 +692,10 @@ namespace MWWorld if (!(active->first->cell->data.flags & ESM::Cell::Interior)) { // exterior -> adjust loaded cells - const int cellSize = 8192; + int cellX = 0; + int cellY = 0; - int cellX = static_cast (x/cellSize); - int cellY = static_cast (y/cellSize); + positionToIndex (x, y, cellX, cellY); if (active->first->cell->data.gridX!=cellX || active->first->cell->data.gridY!=cellY) { @@ -707,4 +707,27 @@ namespace MWWorld // TODO cell change for non-player ref } + + void World::indexToPosition (int cellX, int cellY, float &x, float &y) const + { + const int cellSize = 8192; + + x = cellSize * cellX; + y = cellSize * cellY; + } + + void World::positionToIndex (float x, float y, int &cellX, int &cellY) const + { + const int cellSize = 8192; + + cellX = static_cast (x/cellSize); + + if (x<0) + --cellX; + + cellY = static_cast (y/cellSize); + + if (y<0) + --cellY; + } } diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 000d79037..2ff2d3ccc 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -153,6 +153,12 @@ namespace MWWorld void deleteObject (Ptr ptr); void moveObject (Ptr ptr, float x, float y, float z); + + void indexToPosition (int cellX, int cellY, float &x, float &y) const; + ///< Convert cell numbers to position. + + void positionToIndex (float x, float y, int &cellX, int &cellY) const; + ///< Convert position to cell numbers }; } From bdb5749b574f078e85e93e2b7d3515bc42b281dd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 25 Aug 2010 09:19:15 +0200 Subject: [PATCH 13/16] temporarily removed statics from raycast test (makes object activation easier by removing inactive obstacles, that overlap the AABB of the object) --- apps/openmw/mwrender/mwscene.cpp | 15 +++++++++++---- apps/openmw/mwrender/mwscene.hpp | 7 ++++++- apps/openmw/mwworld/world.cpp | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/apps/openmw/mwrender/mwscene.cpp b/apps/openmw/mwrender/mwscene.cpp index 15163d7a2..133607797 100644 --- a/apps/openmw/mwrender/mwscene.cpp +++ b/apps/openmw/mwrender/mwscene.cpp @@ -9,6 +9,10 @@ #include "OgreCamera.h" #include "OgreTextureManager.h" +#include "../mwworld/world.hpp" // these includes can be removed once the static-hack is gone +#include "../mwworld/ptr.hpp" +#include + using namespace MWRender; using namespace Ogre; @@ -36,7 +40,7 @@ MWScene::MWScene(OEngine::Render::OgreRenderer &_rend) mRaySceneQuery = rend.getScene()->createRayQuery(Ray()); } -std::pair MWScene::getFacedHandle() +std::pair MWScene::getFacedHandle (MWWorld::World& world) { std::string handle = ""; float distance = -1; @@ -57,10 +61,14 @@ std::pair MWScene::getFacedHandle() { // there seem to be omnipresent objects like the caelum sky dom, // the distance of these objects is always 0 so this if excludes these - // TODO: Check if the object can be focused (ignore walls etc.. - // in this state of openmw not possible) if ( itr->movable && itr->distance >= 0.1) { + // horrible hack to exclude statics. this must be removed as soon as a replacement for the + // AABB raycasting is implemented (we should not ignore statics) + MWWorld::Ptr ptr = world.getPtrViaHandle (itr->movable->getParentSceneNode()->getName()); + if (ptr.getType()==typeid (ESM::Static)) + break; + if ( nearest == result.end() ) //if no object is set { nearest = itr; @@ -80,4 +88,3 @@ std::pair MWScene::getFacedHandle() return std::pair(handle, distance); } - diff --git a/apps/openmw/mwrender/mwscene.hpp b/apps/openmw/mwrender/mwscene.hpp index ce04efc92..9d2a51bae 100644 --- a/apps/openmw/mwrender/mwscene.hpp +++ b/apps/openmw/mwrender/mwscene.hpp @@ -13,6 +13,11 @@ namespace Ogre class RaySceneQuery; } +namespace MWWorld +{ + class World; +} + namespace MWRender { /** Class responsible for Morrowind-specific interfaces to OGRE. @@ -43,7 +48,7 @@ namespace MWRender //pair //name is empty and distance = -1 if there is no object which //can be faced - std::pair getFacedHandle(); + std::pair getFacedHandle (MWWorld::World& world); }; } diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 2c8c4a542..24f01e5a7 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -648,7 +648,7 @@ namespace MWWorld std::string World::getFacedHandle() { - std::pair result = mScene.getFacedHandle(); + std::pair result = mScene.getFacedHandle (*this); if (result.first.empty() || result.second>getStore().gameSettings.find ("iMaxActivateDist")->i) From 7bb20414187210761f31cbc3fb81d28a09bfa804 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 25 Aug 2010 09:43:06 +0200 Subject: [PATCH 14/16] made rendering more robust (no more crashes, even if Ogre throws an exception) --- apps/openmw/mwclass/activator.cpp | 4 ++-- apps/openmw/mwclass/apparatus.cpp | 4 ++-- apps/openmw/mwclass/armor.cpp | 4 ++-- apps/openmw/mwclass/book.cpp | 4 ++-- apps/openmw/mwclass/clothing.cpp | 4 ++-- apps/openmw/mwclass/container.cpp | 4 ++-- apps/openmw/mwclass/creature.cpp | 4 ++-- apps/openmw/mwclass/door.cpp | 4 ++-- apps/openmw/mwclass/ingredient.cpp | 4 ++-- apps/openmw/mwclass/light.cpp | 4 ++-- apps/openmw/mwclass/lockpick.cpp | 4 ++-- apps/openmw/mwclass/misc.cpp | 4 ++-- apps/openmw/mwclass/npc.cpp | 5 +++-- apps/openmw/mwclass/potion.cpp | 4 ++-- apps/openmw/mwclass/probe.cpp | 4 ++-- apps/openmw/mwclass/repair.cpp | 4 ++-- apps/openmw/mwclass/static.cpp | 4 ++-- apps/openmw/mwclass/weapon.cpp | 4 ++-- apps/openmw/mwrender/cellimp.cpp | 14 +++++++++++-- apps/openmw/mwrender/cellimp.hpp | 32 ++++++++++++++++++++++++++++++ 20 files changed, 81 insertions(+), 38 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 69a510803..6c96811d8 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -21,9 +21,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index 007b2ca77..1d4afc096 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 5c06077b2..1217d56a6 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 179a060c6..3679eb7ee 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index c3bbfa9f0..07ded0264 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 9c1ed7a89..ea61508b8 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -21,9 +21,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index fc9515fff..2e16ac6a4 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -33,9 +33,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 12aeb9a5b..e8c41dc75 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -27,9 +27,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 29d66d012..e4ea509f9 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index e57511452..de5c06a73 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -28,7 +28,7 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); @@ -40,7 +40,7 @@ namespace MWClass const float radius = float (ref->base->data.radius); cellRender.insertLight (r, g, b, radius); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index c87d1e128..3b08ff199 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 57dca3148..d4ffdce38 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 0fdc77963..04ae468e4 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -40,7 +40,8 @@ namespace MWClass std::string headModel = "meshes\\" + environment.mWorld->getStore().bodyParts.find(headID)->model; - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); + cellRender.insertMesh (headModel); //TODO: define consts for each bodypart e.g. chest, foot, wrist... and put the parts in the @@ -51,7 +52,7 @@ namespace MWClass if (bodyPart) cellRender.insertMesh("meshes\\" + bodyPart->model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } void Npc::enable (const MWWorld::Ptr& ptr, MWWorld::Environment& environment) const diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 3fe38542b..e163473f7 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index bc6c4ba19..9188ae9ea 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 253569afe..7b42bc95c 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index 211d239c6..33e3e0ed4 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -19,9 +19,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 5a941360a..4c14e58ea 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -24,9 +24,9 @@ namespace MWClass const std::string &model = ref->base->model; if (!model.empty()) { - cellRender.insertBegin (ref->ref); + MWRender::Rendering rendering (cellRender, ref->ref); cellRender.insertMesh ("meshes\\" + model); - ref->mData.setHandle (cellRender.insertEnd (ref->mData.isEnabled())); + ref->mData.setHandle (rendering.end (ref->mData.isEnabled())); } } diff --git a/apps/openmw/mwrender/cellimp.cpp b/apps/openmw/mwrender/cellimp.cpp index a5b4b51c7..887941f05 100644 --- a/apps/openmw/mwrender/cellimp.cpp +++ b/apps/openmw/mwrender/cellimp.cpp @@ -1,6 +1,8 @@ #include "cellimp.hpp" #include +#include +#include #include "../mwworld/class.hpp" #include "../mwworld/ptr.hpp" @@ -23,8 +25,16 @@ void insertCellRefList (CellRenderImp& cellRender, MWWorld::Environment& environ { MWWorld::Ptr ptr (&*it, &cell); - class_.insertObj (ptr, cellRender, environment); - class_.enable (ptr, environment); + try + { + class_.insertObj (ptr, cellRender, environment); + class_.enable (ptr, environment); + } + catch (const std::exception& e) + { + std::string error ("error during rendering: "); + std::cerr << error + e.what() << std::endl; + } } } } diff --git a/apps/openmw/mwrender/cellimp.hpp b/apps/openmw/mwrender/cellimp.hpp index fadba79a5..bc6f2874a 100644 --- a/apps/openmw/mwrender/cellimp.hpp +++ b/apps/openmw/mwrender/cellimp.hpp @@ -43,6 +43,38 @@ namespace MWRender void insertCell(ESMS::CellStore &cell, MWWorld::Environment& environment); }; + + /// Exception-safe rendering + class Rendering + { + CellRenderImp& mCellRender; + bool mEnd; + + // not implemented + Rendering (const Rendering&); + Rendering& operator= (const Rendering&); + + public: + + Rendering (CellRenderImp& cellRender, ESM::CellRef &ref) + : mCellRender (cellRender), mEnd (false) + { + mCellRender.insertBegin (ref); + } + + ~Rendering() + { + if (!mEnd) + mCellRender.insertEnd (false); + } + + std::string end (bool enable) + { + assert (!mEnd); + mEnd = true; + return mCellRender.insertEnd (enable); + } + }; } #endif From 07c06acc08d379a80c30ac56b75e6610d5c23252 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 25 Aug 2010 11:50:13 +0200 Subject: [PATCH 15/16] implemented loading of 3x3 exterior cell grid --- apps/openmw/mwworld/world.cpp | 76 ++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 24f01e5a7..496da44ef 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -586,9 +586,9 @@ namespace MWWorld // remove active CellRenderCollection::iterator active = mActiveCells.begin(); - if (active!=mActiveCells.end()) + while (active!=mActiveCells.end()) { - unloadCell (active); + unloadCell (active++); } // Load cell. @@ -598,6 +598,7 @@ namespace MWWorld loadCell (cell, new MWRender::InteriorCellRender (*cell, mEnvironment, mScene)); // adjust player + mCurrentCell = cell; playerCellChange (cell, position); // Sky system @@ -611,19 +612,68 @@ namespace MWWorld // remove active CellRenderCollection::iterator active = mActiveCells.begin(); - if (active!=mActiveCells.end()) + while (active!=mActiveCells.end()) { - unloadCell (active); + 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 cell. - mExteriors[std::make_pair (X, Y)].loadExt (X, Y, mStore, mEsm); - Ptr::CellStore *cell = &mExteriors[std::make_pair (X, Y)]; + // 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(); - loadCell (cell, new MWRender::ExteriorCellRender (*cell, mEnvironment, mScene)); + 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 (cell, position); + playerCellChange (&mExteriors[std::make_pair (X, Y)], position); // Sky system adjustSky(); @@ -685,11 +735,9 @@ namespace MWWorld if (ptr==mPlayerPos->getPlayer()) { - CellRenderCollection::iterator active = mActiveCells.begin(); - - if (active!=mActiveCells.end()) + if (mCurrentCell) { - if (!(active->first->cell->data.flags & ESM::Cell::Interior)) + if (!(mCurrentCell->cell->data.flags & ESM::Cell::Interior)) { // exterior -> adjust loaded cells int cellX = 0; @@ -697,7 +745,7 @@ namespace MWWorld positionToIndex (x, y, cellX, cellY); - if (active->first->cell->data.gridX!=cellX || active->first->cell->data.gridY!=cellY) + if (mCurrentCell->cell->data.gridX!=cellX || mCurrentCell->cell->data.gridY!=cellY) { changeCell (cellX, cellY, mPlayerPos->getPlayer().getCellRef().pos); } From 058f2d0ccebcf23d4daf7009c98199bff2de3051 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 8 Sep 2010 15:42:49 +0200 Subject: [PATCH 16/16] fixed a problem with previous merge --- components/esm_store/cell_store.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esm_store/cell_store.hpp b/components/esm_store/cell_store.hpp index 4e8749464..6acd81dce 100644 --- a/components/esm_store/cell_store.hpp +++ b/components/esm_store/cell_store.hpp @@ -128,7 +128,7 @@ namespace ESMS cell = store.cells.searchExt (X, Y); if(cell == NULL) - throw str_exception("Exterior cell not found"); + throw std::runtime_error("Exterior cell not found"); loadRefs(store, esm); }