From 86f691d3d59023d9c3fdef0550bd2a08282f0df6 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Mon, 7 Jan 2013 22:48:24 -0800 Subject: [PATCH 1/6] split MWWord::World::update into multiple functions --- apps/openmw/mwworld/worldimp.cpp | 258 +++++++++++++++++-------------- apps/openmw/mwworld/worldimp.hpp | 7 + 2 files changed, 152 insertions(+), 113 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 4f60f6ef42..26614f3e13 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -884,8 +884,6 @@ namespace MWWorld void World::update (float duration, bool paused) { - /// \todo split this function up into subfunctions - mWorldScene->update (duration, paused); float pitch, yaw; @@ -895,6 +893,13 @@ namespace MWWorld mWeatherManager->update (duration); + performUpdateSceneQueries (); + + updateWindowManager (); + } + + void World::updateWindowManager () + { // inform the GUI about focused object MWWorld::Ptr object = searchPtrViaHandle(mFacedHandle); @@ -918,7 +923,10 @@ namespace MWWorld screenCoords[0], screenCoords[1], screenCoords[2], screenCoords[3]); } } + } + void World::performUpdateSceneQueries () + { if (!mRendering->occlusionQuerySupported()) { // cast a ray from player to sun to detect if the sun is visible @@ -937,121 +945,145 @@ namespace MWWorld MWRender::OcclusionQuery* query = mRendering->getOcclusionQuery(); if (!query->occlusionTestPending()) { - // get result of last query - if (mNumFacing == 0) mFacedHandle = ""; - else if (mNumFacing == 1) - { - bool result = query->getTestResult(); - mFacedHandle = result ? mFaced1Name : ""; - } - else if (mNumFacing == 2) - { - bool result = query->getTestResult(); - mFacedHandle = result ? mFaced2Name : mFaced1Name; - } - - // send new query - // figure out which object we want to test against - std::vector < std::pair < float, std::string > > results; - if (MWBase::Environment::get().getWindowManager()->isGuiMode()) - { - float x, y; - MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); - results = mPhysics->getFacedObjects(x, y); - } - else - results = mPhysics->getFacedObjects(); - - // ignore the player and other things we're not interested in - std::vector < std::pair < float, std::string > >::iterator it = results.begin(); - while (it != results.end()) - { - if ( (*it).second.find("HeightField") != std::string::npos // not interested in terrain - || getPtrViaHandle((*it).second) == mPlayer->getPlayer() ) // not interested in player (unless you want to talk to yourself) - { - it = results.erase(it); - } - else - ++it; - } - - if (results.size() == 0) - { - mNumFacing = 0; - } - else if (results.size() == 1) - { - mFaced1 = getPtrViaHandle(results.front().second); - mFaced1Name = results.front().second; - mNumFacing = 1; - - btVector3 p; - if (MWBase::Environment::get().getWindowManager()->isGuiMode()) - { - float x, y; - MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); - p = mPhysics->getRayPoint(results.front().first, x, y); - } - else - p = mPhysics->getRayPoint(results.front().first); - Ogre::Vector3 pos(p.x(), p.z(), -p.y()); - Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode(); - - //std::cout << "Num facing 1 : " << mFaced1Name << std::endl; - //std::cout << "Type 1 " << mFaced1.getTypeName() << std::endl; - - query->occlusionTest(pos, node); - } - else - { - mFaced1Name = results.front().second; - mFaced2Name = results[1].second; - mFaced1 = getPtrViaHandle(results.front().second); - mFaced2 = getPtrViaHandle(results[1].second); - mNumFacing = 2; - - btVector3 p; - if (MWBase::Environment::get().getWindowManager()->isGuiMode()) - { - float x, y; - MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); - p = mPhysics->getRayPoint(results[1].first, x, y); - } - else - p = mPhysics->getRayPoint(results[1].first); - Ogre::Vector3 pos(p.x(), p.z(), -p.y()); - Ogre::SceneNode* node1 = mFaced1.getRefData().getBaseNode(); - Ogre::SceneNode* node2 = mFaced2.getRefData().getBaseNode(); - - // no need to test if the first node is not occluder - if (!query->isPotentialOccluder(node1) && (mFaced1.getTypeName().find("Static") == std::string::npos)) - { - mFacedHandle = mFaced1Name; - //std::cout << "node1 Not an occluder" << std::endl; - return; - } - - // no need to test if the second object is static (thus cannot be activated) - if (mFaced2.getTypeName().find("Static") != std::string::npos) - { - mFacedHandle = mFaced1Name; - return; - } - - // work around door problems - if (mFaced1.getTypeName().find("Static") != std::string::npos - && mFaced2.getTypeName().find("Door") != std::string::npos) - { - mFacedHandle = mFaced2Name; - return; - } - - query->occlusionTest(pos, node2); - } + processFacedQueryResults (query); + beginFacedQueryProcess (query); } } } + void World::processFacedQueryResults (MWRender::OcclusionQuery* query) + { + // get result of last query + if (mNumFacing == 0) + { + mFacedHandle = ""; + } + else if (mNumFacing == 1) + { + bool result = query->getTestResult(); + mFacedHandle = result ? mFaced1Name : ""; + } + else if (mNumFacing == 2) + { + bool result = query->getTestResult(); + mFacedHandle = result ? mFaced2Name : mFaced1Name; + } + } + + void World::beginFacedQueryProcess (MWRender::OcclusionQuery* query) + { + // send new query + // figure out which object we want to test against + std::vector < std::pair < float, std::string > > results; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + results = mPhysics->getFacedObjects(x, y); + } + else + { + results = mPhysics->getFacedObjects(); + } + + // ignore the player and other things we're not interested in + std::vector < std::pair < float, std::string > >::iterator it = results.begin(); + while (it != results.end()) + { + if ( (*it).second.find("HeightField") != std::string::npos // not interested in terrain + || getPtrViaHandle((*it).second) == mPlayer->getPlayer() ) // not interested in player (unless you want to talk to yourself) + { + it = results.erase(it); + } + else + ++it; + } + + if (results.size() == 0) + { + mNumFacing = 0; + } + else if (results.size() == 1) + { + beginSingleFacedQueryProcess (query, results); + } + else + { + beginDoubleFacedQueryProcess (query, results); + } + } + + void World::beginSingleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results) + { + mFaced1 = getPtrViaHandle(results.front().second); + mFaced1Name = results.front().second; + mNumFacing = 1; + + btVector3 p; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + p = mPhysics->getRayPoint(results.front().first, x, y); + } + else + p = mPhysics->getRayPoint(results.front().first); + Ogre::Vector3 pos(p.x(), p.z(), -p.y()); + Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode(); + + //std::cout << "Num facing 1 : " << mFaced1Name << std::endl; + //std::cout << "Type 1 " << mFaced1.getTypeName() << std::endl; + + query->occlusionTest(pos, node); + } + + void World::beginDoubleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results) + { + mFaced1Name = results.at (0).second; + mFaced2Name = results.at (1).second; + mFaced1 = getPtrViaHandle(results.at (0).second); + mFaced2 = getPtrViaHandle(results.at (1).second); + mNumFacing = 2; + + btVector3 p; + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + { + float x, y; + MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); + p = mPhysics->getRayPoint(results.at (1).first, x, y); + } + else + p = mPhysics->getRayPoint(results.at (1).first); + Ogre::Vector3 pos(p.x(), p.z(), -p.y()); + Ogre::SceneNode* node1 = mFaced1.getRefData().getBaseNode(); + Ogre::SceneNode* node2 = mFaced2.getRefData().getBaseNode(); + + // no need to test if the first node is not occluder + if (!query->isPotentialOccluder(node1) && (mFaced1.getTypeName().find("Static") == std::string::npos)) + { + mFacedHandle = mFaced1Name; + //std::cout << "node1 Not an occluder" << std::endl; + return; + } + + // no need to test if the second object is static (thus cannot be activated) + if (mFaced2.getTypeName().find("Static") != std::string::npos) + { + mFacedHandle = mFaced1Name; + return; + } + + // work around door problems + if (mFaced1.getTypeName().find("Static") != std::string::npos + && mFaced2.getTypeName().find("Door") != std::string::npos) + { + mFacedHandle = mFaced2Name; + return; + } + + query->occlusionTest(pos, node2); + } + bool World::isCellExterior() const { Ptr::CellStore *currentCell = mWorldScene->getCurrentCell(); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index d29adebf44..a60332e265 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -90,6 +90,13 @@ namespace MWWorld virtual void copyObjectToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos); + void updateWindowManager (); + void performUpdateSceneQueries (); + void processFacedQueryResults (MWRender::OcclusionQuery* query); + void beginFacedQueryProcess (MWRender::OcclusionQuery* query); + void beginSingleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results); + void beginDoubleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results); + public: World (OEngine::Render::OgreRenderer& renderer, From 0108be2e4f4e2e9257622667d3ecbf1666a29e1e Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Mon, 7 Jan 2013 23:00:00 -0800 Subject: [PATCH 2/6] updated MWWorld::PhysicsSystem::getFacedXXX functions * changed the names and return values to be consistent * made the distance to search a parameter * change the distance returned to world units instead of percentage of query distance --- apps/openmw/mwworld/physicssystem.cpp | 35 ++++++++++++++++++--------- apps/openmw/mwworld/physicssystem.hpp | 7 +++--- apps/openmw/mwworld/worldimp.cpp | 12 ++++----- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 5359c4eb27..9e2e94143f 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -43,7 +43,7 @@ namespace MWWorld return mEngine; } - std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world) + std::pair PhysicsSystem::getFacedHandle (MWWorld::World& world, float queryDistance) { btVector3 dir(0, 1, 0); dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch); @@ -56,11 +56,14 @@ namespace MWWorld mPlayerData.eyepos.z); origin += dir * 5; - btVector3 dest = origin + dir * 500; - return mEngine->rayTest(origin, dest); + btVector3 dest = origin + dir * queryDistance; + std::pair result; + /*auto*/ result = mEngine->rayTest(origin, dest); + result.second *= queryDistance; + return std::make_pair (result.second, result.first); } - std::vector < std::pair > PhysicsSystem::getFacedObjects () + std::vector < std::pair > PhysicsSystem::getFacedHandles (float queryDistance) { btVector3 dir(0, 1, 0); dir = dir.rotate(btVector3(1, 0, 0), mPlayerData.pitch); @@ -73,22 +76,32 @@ namespace MWWorld mPlayerData.eyepos.z); origin += dir * 5; - btVector3 dest = origin + dir * 500; - return mEngine->rayTest2(origin, dest); + btVector3 dest = origin + dir * queryDistance; + std::vector < std::pair > results; + /* auto */ results = mEngine->rayTest2(origin, dest); + std::vector < std::pair >::iterator i; + for (/* auto */ i = results.begin (); i != results.end (); ++i) + i->first *= queryDistance; + return results; } - std::vector < std::pair > PhysicsSystem::getFacedObjects (float mouseX, float mouseY) + std::vector < std::pair > PhysicsSystem::getFacedHandles (float mouseX, float mouseY, float queryDistance) { Ray ray = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); Ogre::Vector3 from = ray.getOrigin(); - Ogre::Vector3 to = ray.getPoint(500); /// \todo make this distance (ray length) configurable + Ogre::Vector3 to = ray.getPoint(queryDistance); btVector3 _from, _to; // OGRE to MW coordinates _from = btVector3(from.x, -from.z, from.y); _to = btVector3(to.x, -to.z, to.y); - return mEngine->rayTest2(_from,_to); + std::vector < std::pair > results; + /* auto */ results = mEngine->rayTest2(_from,_to); + std::vector < std::pair >::iterator i; + for (/* auto */ i = results.begin (); i != results.end (); ++i) + i->first *= queryDistance; + return results; } void PhysicsSystem::setCurrentWater(bool hasWater, int waterHeight) @@ -110,7 +123,7 @@ namespace MWWorld Ray centerRay = mRender.getCamera()->getCameraToViewportRay( mRender.getViewport()->getWidth()/2, mRender.getViewport()->getHeight()/2); - btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); /// \todo make this distance (ray length) configurable + btVector3 result(centerRay.getPoint(extent).x,-centerRay.getPoint(extent).z,centerRay.getPoint(extent).y); return result; } @@ -118,7 +131,7 @@ namespace MWWorld { //get a ray pointing to the center of the viewport Ray centerRay = mRender.getCamera()->getCameraToViewportRay(mouseX, mouseY); - btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); /// \todo make this distance (ray length) configurable + btVector3 result(centerRay.getPoint(extent).x,-centerRay.getPoint(extent).z,centerRay.getPoint(extent).y); return result; } diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 8bd73fd6cb..81715c31e9 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -41,14 +41,13 @@ namespace MWWorld bool toggleCollisionMode(); - std::pair getFacedHandle (MWWorld::World& world); + std::pair getFacedHandle (MWWorld::World& world, float queryDistance); + std::vector < std::pair > getFacedHandles (float queryDistance); + std::vector < std::pair > getFacedHandles (float mouseX, float mouseY, float queryDistance); btVector3 getRayPoint(float extent); btVector3 getRayPoint(float extent, float mouseX, float mouseY); - std::vector < std::pair > getFacedObjects (); - - std::vector < std::pair > getFacedObjects (float mouseX, float mouseY); // cast ray, return true if it hit something bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 26614f3e13..09c48bd137 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -577,13 +577,13 @@ namespace MWWorld { if (!mRendering->occlusionQuerySupported()) { - std::pair result = mPhysics->getFacedHandle (*this); + std::pair result = mPhysics->getFacedHandle (*this, 500); - if (result.first.empty() || - result.second>getStore().get().find ("iMaxActivateDist")->getInt()) + if (result.second.empty() || + result.first>getStore().get().find ("iMaxActivateDist")->getInt()) return ""; - return result.first; + return result.second; } else { @@ -979,11 +979,11 @@ namespace MWWorld { float x, y; MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); - results = mPhysics->getFacedObjects(x, y); + results = mPhysics->getFacedHandles(x, y, 500); } else { - results = mPhysics->getFacedObjects(); + results = mPhysics->getFacedHandles(500); } // ignore the player and other things we're not interested in From 05dad29005c9651829c7695cc3da8a6bf4b2ee68 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Mon, 7 Jan 2013 23:11:15 -0800 Subject: [PATCH 3/6] update MWWord::World to track distances while performing occlusion queries. This allows checking the activation distance against what is stored in GameSettings. Experimentation suggests that a second distance is required for NPCs. --- apps/openmw/mwworld/worldimp.cpp | 12 ++++++++++++ apps/openmw/mwworld/worldimp.hpp | 3 +++ 2 files changed, 15 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 09c48bd137..002ffcd935 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -587,6 +587,9 @@ namespace MWWorld } else { + if (mFacedDistance > result.first>getStore().get().find ("iMaxActivateDist")->getInt()) + return ""; + // updated every few frames in update() return mFacedHandle; } @@ -957,16 +960,19 @@ namespace MWWorld if (mNumFacing == 0) { mFacedHandle = ""; + mFacedDistance = FLT_MAX; } else if (mNumFacing == 1) { bool result = query->getTestResult(); mFacedHandle = result ? mFaced1Name : ""; + mFacedDistance = result ? mFaced1Distance : FLT_MAX; } else if (mNumFacing == 2) { bool result = query->getTestResult(); mFacedHandle = result ? mFaced2Name : mFaced1Name; + mFacedDistance = result ? mFaced1Distance : mFaced1Distance; } } @@ -1017,6 +1023,7 @@ namespace MWWorld { mFaced1 = getPtrViaHandle(results.front().second); mFaced1Name = results.front().second; + mFaced1Distance = results.front().first; mNumFacing = 1; btVector3 p; @@ -1041,6 +1048,8 @@ namespace MWWorld { mFaced1Name = results.at (0).second; mFaced2Name = results.at (1).second; + mFaced1Distance = results.at (0).first; + mFaced2Distance = results.at (1).first; mFaced1 = getPtrViaHandle(results.at (0).second); mFaced2 = getPtrViaHandle(results.at (1).second); mNumFacing = 2; @@ -1062,6 +1071,7 @@ namespace MWWorld if (!query->isPotentialOccluder(node1) && (mFaced1.getTypeName().find("Static") == std::string::npos)) { mFacedHandle = mFaced1Name; + mFacedDistance = mFaced1Distance; //std::cout << "node1 Not an occluder" << std::endl; return; } @@ -1070,6 +1080,7 @@ namespace MWWorld if (mFaced2.getTypeName().find("Static") != std::string::npos) { mFacedHandle = mFaced1Name; + mFacedDistance = mFaced1Distance; return; } @@ -1078,6 +1089,7 @@ namespace MWWorld && mFaced2.getTypeName().find("Door") != std::string::npos) { mFacedHandle = mFaced2Name; + mFacedDistance = mFaced2Distance; return; } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index a60332e265..de6689debc 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -72,10 +72,13 @@ namespace MWWorld Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore); std::string mFacedHandle; + float mFacedDistance; Ptr mFaced1; Ptr mFaced2; std::string mFaced1Name; std::string mFaced2Name; + float mFaced1Distance; + float mFaced2Distance; int mNumFacing; std::map mFallback; From b9fbd6ae4b4be8319eb31596a6aa77e598cd90ae Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Mon, 7 Jan 2013 23:27:37 -0800 Subject: [PATCH 4/6] Factored faced object lookups into MWRender::World * Renamed MWWorld::World::getFacedHandle to getFacedObject. * Changed it to return an object pointer * Updated clients to use return object directly. --- apps/openmw/engine.cpp | 7 +------ apps/openmw/mwbase/world.hpp | 4 ++-- apps/openmw/mwgui/hud.cpp | 3 +-- apps/openmw/mwgui/tooltips.cpp | 3 +-- apps/openmw/mwworld/worldimp.cpp | 32 +++++++++++++++----------------- apps/openmw/mwworld/worldimp.hpp | 4 ++-- 6 files changed, 22 insertions(+), 31 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index aadeb7f3a2..fcfaed47dd 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -427,12 +427,7 @@ void OMW::Engine::activate() if (MWBase::Environment::get().getWindowManager()->isGuiMode()) return; - std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); - - if (handle.empty()) - return; - - MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaHandle (handle); + MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getFacedObject(); if (ptr.isEmpty()) return; diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index cc625b3067..6f7b6e61a9 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -199,8 +199,8 @@ namespace MWBase virtual void markCellAsUnchanged() = 0; - virtual std::string getFacedHandle() = 0; - ///< Return handle of the object the player is looking at + virtual MWWorld::Ptr getFacedObject() = 0; + ///< Return pointer to the object the player is looking at, if it is within activation range virtual void deleteObject (const MWWorld::Ptr& ptr) = 0; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 689baf488f..5ea1d13388 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -244,8 +244,7 @@ void HUD::onWorldClicked(MyGUI::Widget* _sender) if ( (mode != GM_Console) && (mode != GM_Container) && (mode != GM_Inventory) ) return; - std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); - MWWorld::Ptr object = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle); + MWWorld::Ptr object = MWBase::Environment::get().getWorld()->getFacedObject(); if (mode == GM_Console) MWBase::Environment::get().getWindowManager()->getConsole()->setSelectedObject(object); diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 97df211acc..c7acf568d1 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -80,9 +80,8 @@ void ToolTips::onFrame(float frameDuration) || (mWindowManager->getMode() == GM_Container) || (mWindowManager->getMode() == GM_Inventory))) { - std::string handle = MWBase::Environment::get().getWorld()->getFacedHandle(); + mFocusObject = MWBase::Environment::get().getWorld()->getFacedObject(); - mFocusObject = MWBase::Environment::get().getWorld()->searchPtrViaHandle(handle); if (mFocusObject.isEmpty ()) return; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 002ffcd935..a893a6776c 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -573,26 +573,24 @@ namespace MWWorld return mWorldScene->markCellAsUnchanged(); } - std::string World::getFacedHandle() + MWWorld::Ptr World::getFacedObject() { + std::pair result; + if (!mRendering->occlusionQuerySupported()) - { - std::pair result = mPhysics->getFacedHandle (*this, 500); - - if (result.second.empty() || - result.first>getStore().get().find ("iMaxActivateDist")->getInt()) - return ""; - - return result.second; - } + result = mPhysics->getFacedHandle (*this, 500); else - { - if (mFacedDistance > result.first>getStore().get().find ("iMaxActivateDist")->getInt()) - return ""; + result = std::make_pair (mFacedDistance, mFacedHandle); - // updated every few frames in update() - return mFacedHandle; - } + if (result.second.empty()) + return MWWorld::Ptr (); + + float ActivationDistance = getStore().get().find ("iMaxActivateDist")->getInt(); + + if (result.first > ActivationDistance) + return MWWorld::Ptr (); + + return searchPtrViaHandle (result.second); } void World::deleteObject (const Ptr& ptr) @@ -904,7 +902,7 @@ namespace MWWorld void World::updateWindowManager () { // inform the GUI about focused object - MWWorld::Ptr object = searchPtrViaHandle(mFacedHandle); + MWWorld::Ptr object = getFacedObject (); MWBase::Environment::get().getWindowManager()->setFocusObject(object); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index de6689debc..62fb1d89af 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -227,8 +227,8 @@ namespace MWWorld virtual void markCellAsUnchanged(); - virtual std::string getFacedHandle(); - ///< Return handle of the object the player is looking at + virtual MWWorld::Ptr getFacedObject(); + ///< Return pointer to the object the player is looking at, if it is within activation range virtual void deleteObject (const Ptr& ptr); From b3932e3deae509f5d82647e308cc313ac17817e5 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Mon, 7 Jan 2013 23:40:17 -0800 Subject: [PATCH 5/6] added a separate activation distance for NPCs --- apps/openmw/mwworld/worldimp.cpp | 32 +++++++++++++++++++++++++++----- apps/openmw/mwworld/worldimp.hpp | 4 ++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index a893a6776c..739d0daab3 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -573,24 +573,46 @@ namespace MWWorld return mWorldScene->markCellAsUnchanged(); } + float World::getMaxActivationDistance () + { + return (std::max) (getNpcActivationDistance (), getObjectActivationDistance ()); + } + + float World::getNpcActivationDistance () + { + return getStore().get().find ("iMaxActivateDist")->getInt()*5/4; + } + + float World::getObjectActivationDistance () + { + return getStore().get().find ("iMaxActivateDist")->getInt(); + } + MWWorld::Ptr World::getFacedObject() { std::pair result; if (!mRendering->occlusionQuerySupported()) - result = mPhysics->getFacedHandle (*this, 500); + result = mPhysics->getFacedHandle (*this, getMaxActivationDistance ()); else result = std::make_pair (mFacedDistance, mFacedHandle); if (result.second.empty()) return MWWorld::Ptr (); - float ActivationDistance = getStore().get().find ("iMaxActivateDist")->getInt(); + MWWorld::Ptr object = searchPtrViaHandle (result.second); + + float ActivationDistance; + + if (object.getTypeName ().find("NPC") != std::string::npos) + ActivationDistance = getNpcActivationDistance (); + else + ActivationDistance = getObjectActivationDistance (); if (result.first > ActivationDistance) return MWWorld::Ptr (); - return searchPtrViaHandle (result.second); + return object; } void World::deleteObject (const Ptr& ptr) @@ -983,11 +1005,11 @@ namespace MWWorld { float x, y; MWBase::Environment::get().getWindowManager()->getMousePosition(x, y); - results = mPhysics->getFacedHandles(x, y, 500); + results = mPhysics->getFacedHandles(x, y, getMaxActivationDistance ()); } else { - results = mPhysics->getFacedHandles(500); + results = mPhysics->getFacedHandles(getMaxActivationDistance ()); } // ignore the player and other things we're not interested in diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 62fb1d89af..a1ba6fcdeb 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -100,6 +100,10 @@ namespace MWWorld void beginSingleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results); void beginDoubleFacedQueryProcess (MWRender::OcclusionQuery* query, std::vector < std::pair < float, std::string > > const & results); + float getMaxActivationDistance (); + float getNpcActivationDistance (); + float getObjectActivationDistance (); + public: World (OEngine::Render::OgreRenderer& renderer, From 719663d86eeedd77cce0f576126dd139356e97e7 Mon Sep 17 00:00:00 2001 From: Nathan Jeffords Date: Tue, 8 Jan 2013 19:52:18 -0800 Subject: [PATCH 6/6] added option to override the activation distance The command line option '--activate-dist ' can be used to override the in game activation distance. --- apps/openmw/engine.cpp | 9 ++++++++- apps/openmw/engine.hpp | 4 ++++ apps/openmw/main.cpp | 3 +++ apps/openmw/mwworld/worldimp.cpp | 13 +++++++++++-- apps/openmw/mwworld/worldimp.hpp | 3 ++- 5 files changed, 28 insertions(+), 4 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index fcfaed47dd..8c288a2ee2 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -336,7 +336,8 @@ void OMW::Engine::go() // Create the world mEnvironment.setWorld (new MWWorld::World (*mOgre, mFileCollections, mMaster, - mResDir, mCfgMgr.getCachePath(), mNewGame, &encoder, mFallbackMap)); + mResDir, mCfgMgr.getCachePath(), mNewGame, &encoder, mFallbackMap, + mActivationDistanceOverride)); //Load translation data mTranslationDataStorage.setEncoder(&encoder); @@ -509,3 +510,9 @@ void OMW::Engine::setStartupScript (const std::string& path) { mStartupScript = path; } + + +void OMW::Engine::setActivationDistanceOverride (int distance) +{ + mActivationDistanceOverride = distance; +} diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 00889197e8..601cc7765c 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -76,6 +76,7 @@ namespace OMW std::map mFallbackMap; bool mScriptConsoleMode; std::string mStartupScript; + int mActivationDistanceOverride; Compiler::Extensions mExtensions; Compiler::Context *mScriptContext; @@ -167,6 +168,9 @@ namespace OMW /// Set path for a script that is run on startup in the console. void setStartupScript (const std::string& path); + /// Override the game setting specified activation distance. + void setActivationDistanceOverride (int distance); + private: Files::ConfigurationManager& mCfgMgr; }; diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 96dbf89877..d1a498610f 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -149,6 +149,8 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat ("fallback", bpo::value()->default_value(FallbackMap(), "") ->multitoken()->composing(), "fallback values") + ("activate-dist", bpo::value ()->default_value (-1), "activation distance override"); + ; bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv) @@ -236,6 +238,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat engine.setFallbackValues(variables["fallback"].as().mMap); engine.setScriptConsoleMode (variables["script-console"].as()); engine.setStartupScript (variables["script-run"].as()); + engine.setActivationDistanceOverride (variables["activate-dist"].as()); return true; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 739d0daab3..766fdafa86 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -170,10 +170,10 @@ namespace MWWorld World::World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, - ToUTF8::Utf8Encoder* encoder, std::map fallbackMap) + ToUTF8::Utf8Encoder* encoder, std::map fallbackMap, int mActivationDistanceOverride) : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), mSky (true), mCells (mStore, mEsm), - mNumFacing(0) + mNumFacing(0), mActivationDistanceOverride (mActivationDistanceOverride) { mPhysics = new PhysicsSystem(renderer); mPhysEngine = mPhysics->getEngine(); @@ -575,16 +575,25 @@ namespace MWWorld float World::getMaxActivationDistance () { + if (mActivationDistanceOverride >= 0) + return mActivationDistanceOverride; + return (std::max) (getNpcActivationDistance (), getObjectActivationDistance ()); } float World::getNpcActivationDistance () { + if (mActivationDistanceOverride >= 0) + return mActivationDistanceOverride; + return getStore().get().find ("iMaxActivateDist")->getInt()*5/4; } float World::getObjectActivationDistance () { + if (mActivationDistanceOverride >= 0) + return mActivationDistanceOverride; + return getStore().get().find ("iMaxActivateDist")->getInt(); } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index a1ba6fcdeb..6f8bacf72a 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -71,6 +71,7 @@ namespace MWWorld Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore); + int mActivationDistanceOverride; std::string mFacedHandle; float mFacedDistance; Ptr mFaced1; @@ -109,7 +110,7 @@ namespace MWWorld World (OEngine::Render::OgreRenderer& renderer, const Files::Collections& fileCollections, const std::string& master, const boost::filesystem::path& resDir, const boost::filesystem::path& cacheDir, bool newGame, - ToUTF8::Utf8Encoder* encoder, std::map fallbackMap); + ToUTF8::Utf8Encoder* encoder, std::map fallbackMap, int mActivationDistanceOverride); virtual ~World();