From 4e63f89829fbd0d64f6b782c60849f0776987ed8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 1 Apr 2012 13:09:30 +0200 Subject: [PATCH 1/3] silence an error regarding faced handle --- apps/openmw/engine.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index 441c22769..2da5456e6 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -82,12 +82,20 @@ void OMW::Engine::updateFocusReport (float duration) if (!handle.empty()) { - MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); + // the faced handle is not updated immediately, so on a cell change it might + // point to an object that doesn't exist anymore + // therefore, we are catching the "Unknown Ogre handle" exception that occurs in this case + try + { + MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); - if (!ptr.isEmpty()){ - name = MWWorld::Class::get (ptr).getName (ptr); + if (!ptr.isEmpty()){ + name = MWWorld::Class::get (ptr).getName (ptr); + } } + catch (std::runtime_error& e) + {} } if (name!=mFocusName) @@ -415,10 +423,21 @@ void OMW::Engine::activate() if (handle.empty()) return; - MWWorld::Ptr ptr = mEnvironment.mWorld->getPtrViaHandle (handle); + // the faced handle is not updated immediately, so on a cell change it might + // point to an object that doesn't exist anymore + // therefore, we are catching the "Unknown Ogre handle" exception that occurs in this case + MWWorld::Ptr ptr; + try + { + ptr = mEnvironment.mWorld->getPtrViaHandle (handle); - if (ptr.isEmpty()) + if (ptr.isEmpty()) + return; + } + catch (std::runtime_error&) + { return; + } MWScript::InterpreterContext interpreterContext (mEnvironment, &ptr.getRefData().getLocals(), ptr); From 80456778be3e51e177626e1e28da2fa907251658 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 1 Apr 2012 14:22:04 +0200 Subject: [PATCH 2/3] fix for pickup up transparent objects, workaround for doors --- apps/openmw/mwrender/occlusionquery.cpp | 42 ++++++++++++++++++++-- apps/openmw/mwrender/occlusionquery.hpp | 8 +++++ apps/openmw/mwworld/world.cpp | 46 ++++++++++++++++++++----- 3 files changed, 85 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index cc3464c64..6215a6f19 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -5,6 +5,7 @@ #include #include #include +#include using namespace MWRender; using namespace Ogre; @@ -12,7 +13,7 @@ using namespace Ogre; OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNode* sunNode) : mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mSingleObjectQuery(0), mActiveQuery(0), mDoQuery(0), mSunVisibility(0), mQuerySingleObjectStarted(false), mTestResult(false), - mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false), mDoQuery2(false) + mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false) { mRendering = renderer; mSunNode = sunNode; @@ -82,7 +83,6 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mRendering->getScene()->addRenderObjectListener(this); mRendering->getScene()->addRenderQueueListener(this); mDoQuery = true; - mDoQuery2 = true; } OcclusionQuery::~OcclusionQuery() @@ -190,7 +190,6 @@ void OcclusionQuery::update(float duration) // Stop occlusion queries until we get their information // (may not happen on the same frame they are requested in) mDoQuery = false; - mDoQuery2 = false; if (!mSunTotalAreaQuery->isStillOutstanding() && !mSunVisibleAreaQuery->isStillOutstanding() @@ -252,3 +251,40 @@ bool OcclusionQuery::getTestResult() return mTestResult; } + +bool OcclusionQuery::isPotentialOccluder(Ogre::SceneNode* node) +{ + bool result = false; + for (unsigned int i=0; i < node->numAttachedObjects(); ++i) + { + MovableObject* ob = node->getAttachedObject(i); + std::string type = ob->getMovableType(); + if (type == "Entity") + { + Entity* ent = static_cast(ob); + for (unsigned int j=0; j < ent->getNumSubEntities(); ++j) + { + // if any sub entity has a material with depth write off, + // consider the object as not an occluder + MaterialPtr mat = ent->getSubEntity(j)->getMaterial(); + + Material::TechniqueIterator techIt = mat->getTechniqueIterator(); + while (techIt.hasMoreElements()) + { + Technique* tech = techIt.getNext(); + Technique::PassIterator passIt = tech->getPassIterator(); + while (passIt.hasMoreElements()) + { + Pass* pass = passIt.getNext(); + + if (pass->getDepthWriteEnabled() == false) + return false; + else + result = true; + } + } + } + } + } + return result; +} diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index ebdc51311..934d963ac 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -46,6 +46,14 @@ namespace MWRender */ bool occlusionTestPending(); + /** + * Checks if the objects held by this scenenode + * can be considered as potential occluders + * (which might not be the case when transparency is involved) + * @param Scene node + */ + bool isPotentialOccluder(Ogre::SceneNode* node); + /** * @return true if the object tested in the last request was occluded */ diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 6f03fa37f..47e608624 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -750,15 +750,16 @@ namespace MWWorld // figure out which object we want to test against std::vector < std::pair < float, std::string > > results = mPhysics->getFacedObjects(); - // ignore the player - for (std::vector < std::pair < float, std::string > >::iterator it = results.begin(); - it != results.end(); ++it) + // 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 == mPlayer->getPlayer().getRefData().getHandle() ) + if ( (*it).second == mPlayer->getPlayer().getRefData().getHandle()) { - results.erase(it); - break; + it = results.erase(it); } + else + ++it; } if (results.size() == 0) @@ -774,6 +775,7 @@ namespace MWWorld btVector3 p = mPhysics->getRayPoint(results.front().first); Ogre::Vector3 pos(p.x(), p.z(), -p.y()); Ogre::SceneNode* node = mFaced1.getRefData().getBaseNode(); + query->occlusionTest(pos, node); } else @@ -784,10 +786,38 @@ namespace MWWorld mFaced2 = getPtrViaHandle(results[1].second); mNumFacing = 2; + //std::cout << "Num facing 2 : " << mFaced1Name << " " << mFaced2Name << std::endl; + //std::cout << "Type 1 " << mFaced1.getTypeName() << " " << mFaced2.getTypeName() << std::endl; + btVector3 p = mPhysics->getRayPoint(results[1].first); Ogre::Vector3 pos(p.x(), p.z(), -p.y()); - Ogre::SceneNode* node = mFaced2.getRefData().getBaseNode(); - query->occlusionTest(pos, node); + 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); } } } From df8e0bbff2533a5d9b9c1ef11ca2f4589663b1ed Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 1 Apr 2012 14:53:41 +0200 Subject: [PATCH 3/3] player check --- apps/openmw/mwworld/world.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 47e608624..9ca31b5d3 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -754,7 +754,7 @@ namespace MWWorld std::vector < std::pair < float, std::string > >::iterator it = results.begin(); while (it != results.end()) { - if ( (*it).second == mPlayer->getPlayer().getRefData().getHandle()) + if ( getPtrViaHandle((*it).second) == mPlayer->getPlayer() ) { it = results.erase(it); } @@ -776,6 +776,9 @@ namespace MWWorld 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 @@ -786,8 +789,8 @@ namespace MWWorld mFaced2 = getPtrViaHandle(results[1].second); mNumFacing = 2; - //std::cout << "Num facing 2 : " << mFaced1Name << " " << mFaced2Name << std::endl; - //std::cout << "Type 1 " << mFaced1.getTypeName() << " " << mFaced2.getTypeName() << std::endl; + std::cout << "Num facing 2 : " << mFaced1Name << " " << mFaced2Name << std::endl; + std::cout << "Type 1 " << mFaced1.getTypeName() << " " << mFaced2.getTypeName() << std::endl; btVector3 p = mPhysics->getRayPoint(results[1].first); Ogre::Vector3 pos(p.x(), p.z(), -p.y());