From f4898539e9c99f0f2c4a36c0f47bf0f90dcc0290 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 24 Mar 2012 13:06:01 +0100 Subject: [PATCH 01/40] added some code that doesn't do anything yet, waiting for ogre 1.8 --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwrender/occlusionquery.cpp | 27 +++++++++++++++++++++++ apps/openmw/mwrender/occlusionquery.hpp | 27 +++++++++++++++++++++++ apps/openmw/mwrender/renderingmanager.cpp | 3 +++ apps/openmw/mwrender/renderingmanager.hpp | 7 ++++-- 5 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 apps/openmw/mwrender/occlusionquery.cpp create mode 100644 apps/openmw/mwrender/occlusionquery.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 2630098f5c..7d4836d3b1 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -15,7 +15,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender renderingmanager debugging sky player animation npcanimation creatureanimation actors objects - renderinginterface localmap + renderinginterface localmap occlusionquery ) add_openmw_dir (mwinput diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp new file mode 100644 index 0000000000..395660bb5c --- /dev/null +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -0,0 +1,27 @@ +#include "occlusionquery.hpp" + +#include +#include + +using namespace MWRender; +using namespace Ogre; + +OcclusionQuery::OcclusionQuery() : + mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0) +{ + try { + RenderSystem* renderSystem = Root::getSingleton().getRenderSystem(); + + mSunTotalAreaQuery = renderSystem->createHardwareOcclusionQuery(); + mSunVisibleAreaQuery = renderSystem->createHardwareOcclusionQuery(); + + mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0); + } + catch (Ogre::Exception e) + { + mSupported = false; + } + + if (!mSupported) + std::cout << "Hardware occlusion queries not supported." << std::endl; +} diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp new file mode 100644 index 0000000000..619b072ee0 --- /dev/null +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -0,0 +1,27 @@ +#ifndef _GAME_OCCLUSION_QUERY_H +#define _GAME_OCCLUSION_QUERY_H + +#include + +namespace MWRender +{ + /// + /// \brief Implements hardware occlusion queries on the GPU + /// + class OcclusionQuery + { + public: + OcclusionQuery(); + + bool supported(); + ///< returns true if occlusion queries are supported on the user's hardware + + private: + Ogre::HardwareOcclusionQuery* mSunTotalAreaQuery; + Ogre::HardwareOcclusionQuery* mSunVisibleAreaQuery; + + bool mSupported; + }; +} + +#endif diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index e2aea19c6e..78287dadb5 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -49,6 +49,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode(); Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode(); cameraPitchNode->attachObject(mRendering.getCamera()); + + mOcclusionQuery = new OcclusionQuery(); //mSkyManager = 0; mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment); @@ -65,6 +67,7 @@ RenderingManager::~RenderingManager () delete mPlayer; delete mSkyManager; delete mLocalMap; + delete mOcclusionQuery; } MWRender::SkyManager* RenderingManager::getSkyManager() diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 78a1d2fdb7..996396633c 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -25,6 +25,7 @@ #include "actors.hpp" #include "player.hpp" #include "localmap.hpp" +#include "occlusionquery.hpp" namespace Ogre { @@ -131,9 +132,11 @@ class RenderingManager: private RenderingInterface { private: void setAmbientMode(); - + SkyManager* mSkyManager; - + + OcclusionQuery* mOcclusionQuery; + OEngine::Render::OgreRenderer &mRendering; MWRender::Objects mObjects; From 743ea0c9be16a6864bf861db101dd5901452045a Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 24 Mar 2012 17:59:26 +0100 Subject: [PATCH 02/40] use hardware occlusion query for sun glare effect --- apps/openmw/mwrender/occlusionquery.cpp | 116 +++++++++++++++++++++- apps/openmw/mwrender/occlusionquery.hpp | 28 +++++- apps/openmw/mwrender/renderingmanager.cpp | 12 ++- apps/openmw/mwrender/renderingmanager.hpp | 4 +- apps/openmw/mwrender/sky.cpp | 52 ++++++---- apps/openmw/mwrender/sky.hpp | 48 ++++----- apps/openmw/mwworld/world.cpp | 17 ++-- 7 files changed, 216 insertions(+), 61 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 395660bb5c..6c74561e95 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -2,13 +2,17 @@ #include #include +#include using namespace MWRender; using namespace Ogre; -OcclusionQuery::OcclusionQuery() : - mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0) +OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNode* sunNode) : + mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mActiveQuery(0), mDoQuery(0), mSunVisibility(0) { + mRendering = renderer; + mSunNode = sunNode; + try { RenderSystem* renderSystem = Root::getSingleton().getRenderSystem(); @@ -23,5 +27,113 @@ OcclusionQuery::OcclusionQuery() : } if (!mSupported) + { std::cout << "Hardware occlusion queries not supported." << std::endl; + return; + } + + // This means that everything up to RENDER_QUEUE_MAIN can occlude the objects that are tested + const int queue = RENDER_QUEUE_MAIN+1; + + MaterialPtr matBase = MaterialManager::getSingleton().getByName("BaseWhiteNoLighting"); + MaterialPtr matQueryArea = matBase->clone("QueryTotalPixels"); + matQueryArea->setDepthWriteEnabled(false); + matQueryArea->setColourWriteEnabled(false); + matQueryArea->setDepthCheckEnabled(false); // Not occluded by objects + MaterialPtr matQueryVisible = matBase->clone("QueryVisiblePixels"); + matQueryVisible->setDepthWriteEnabled(false); + matQueryVisible->setColourWriteEnabled(false); + matQueryVisible->setDepthCheckEnabled(true); // Occluded by objects + + mBBQueryTotal = mRendering->getScene()->createBillboardSet(1); + mBBQueryTotal->setDefaultDimensions(150, 150); + mBBQueryTotal->createBillboard(Vector3::ZERO); + mBBQueryTotal->setMaterialName("QueryTotalPixels"); + mBBQueryTotal->setRenderQueueGroup(queue); + mSunNode->attachObject(mBBQueryTotal); + + mBBQueryVisible = mRendering->getScene()->createBillboardSet(1); + mBBQueryVisible->setDefaultDimensions(150, 150); + mBBQueryVisible->createBillboard(Vector3::ZERO); + mBBQueryVisible->setMaterialName("QueryVisiblePixels"); + mBBQueryVisible->setRenderQueueGroup(queue); + mSunNode->attachObject(mBBQueryVisible); + + mRendering->getScene()->addRenderObjectListener(this); + mDoQuery = true; } + +OcclusionQuery::~OcclusionQuery() +{ + RenderSystem* renderSystem = Root::getSingleton().getRenderSystem(); + if (mSunTotalAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunTotalAreaQuery); + if (mSunVisibleAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunVisibleAreaQuery); +} + +bool OcclusionQuery::supported() +{ + return mSupported; +} + +void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source, + const LightList* pLightList, bool suppressRenderStateChanges) +{ + if (!mSupported) return; + + // The following code activates and deactivates the occlusion queries + // so that the queries only include the rendering of their intended targets + + // Close the last occlusion query + // Each occlusion query should only last a single rendering + if (mActiveQuery != NULL) + { + mActiveQuery->endOcclusionQuery(); + mActiveQuery = NULL; + } + + // Open a new occlusion query + if (mDoQuery == true) + { + if (rend == mBBQueryTotal) + mActiveQuery = mSunTotalAreaQuery; + else if (rend == mBBQueryVisible) + mActiveQuery = mSunVisibleAreaQuery; + + if (mActiveQuery != NULL) + { + mActiveQuery->beginOcclusionQuery(); + } + } +} + +void OcclusionQuery::update() +{ + if (!mSupported) return; + + // Stop occlusion queries until we get their information + // (may not happen on the same frame they are requested in) + mDoQuery = false; + + if (!mSunTotalAreaQuery->isStillOutstanding() && !mSunVisibleAreaQuery->isStillOutstanding()) + { + unsigned int totalPixels; + unsigned int visiblePixels; + + mSunTotalAreaQuery->pullOcclusionQuery(&totalPixels); + mSunVisibleAreaQuery->pullOcclusionQuery(&visiblePixels); + + if (totalPixels == 0) + { + // probably outside of the view frustum + mSunVisibility = 0; + } + else + { + mSunVisibility = float(visiblePixels) / float(totalPixels); + if (mSunVisibility > 1) mSunVisibility = 1; + } + + mDoQuery = true; + } +} + diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index 619b072ee0..e6adc0d4b3 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -2,25 +2,49 @@ #define _GAME_OCCLUSION_QUERY_H #include +#include + +#include namespace MWRender { /// /// \brief Implements hardware occlusion queries on the GPU /// - class OcclusionQuery + class OcclusionQuery : public Ogre::RenderObjectListener { public: - OcclusionQuery(); + OcclusionQuery(OEngine::Render::OgreRenderer*, Ogre::SceneNode* sunNode); + ~OcclusionQuery(); bool supported(); ///< returns true if occlusion queries are supported on the user's hardware + void update(); + ///< per-frame update + + float getSunVisibility() const {return mSunVisibility;}; + private: Ogre::HardwareOcclusionQuery* mSunTotalAreaQuery; Ogre::HardwareOcclusionQuery* mSunVisibleAreaQuery; + Ogre::HardwareOcclusionQuery* mActiveQuery; + + Ogre::BillboardSet* mBBQueryVisible; + Ogre::BillboardSet* mBBQueryTotal; + + Ogre::SceneNode* mSunNode; + + float mSunVisibility; bool mSupported; + bool mDoQuery; + + OEngine::Render::OgreRenderer* mRendering; + + protected: + virtual void notifyRenderSingleObject(Ogre::Renderable* rend, const Ogre::Pass* pass, const Ogre::AutoParamDataSource* source, + const Ogre::LightList* pLightList, bool suppressRenderStateChanges); }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 7aa623879e..b4711e8df7 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -54,12 +54,12 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const Ogre::SceneNode *cameraYawNode = playerNode->createChildSceneNode(); Ogre::SceneNode *cameraPitchNode = cameraYawNode->createChildSceneNode(); cameraPitchNode->attachObject(mRendering.getCamera()); - - mOcclusionQuery = new OcclusionQuery(); //mSkyManager = 0; mSkyManager = new SkyManager(mMwRoot, mRendering.getCamera(), &environment); + mOcclusionQuery = new OcclusionQuery(&mRendering, mSkyManager->getSunNode()); + mPlayer = new MWRender::Player (mRendering.getCamera(), playerNode); mSun = 0; @@ -149,9 +149,13 @@ void RenderingManager::moveObjectToCell (const MWWorld::Ptr& ptr, const Ogre::Ve void RenderingManager::update (float duration){ mActors.update (duration); - + + mOcclusionQuery->update(); + mSkyManager->update(duration); - + + mSkyManager->setGlare(mOcclusionQuery->getSunVisibility()); + mRendering.update(duration); mLocalMap->updatePlayer( mRendering.getCamera()->getRealPosition(), mRendering.getCamera()->getRealDirection() ); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index acaf8565bb..450e461730 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -98,7 +98,9 @@ class RenderingManager: private RenderingInterface { void setSunDirection(const Ogre::Vector3& direction); void sunEnable(); void sunDisable(); - + + bool occlusionQuerySupported() { return mOcclusionQuery->supported(); }; + void setGlare(bool glare); void skyEnable (); void skyDisable (); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 5e85780022..a70913b239 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -12,6 +12,7 @@ #include "../mwworld/environment.hpp" #include "../mwworld/world.hpp" +#include "occlusionquery.hpp" using namespace MWRender; using namespace Ogre; @@ -30,7 +31,7 @@ BillboardObject::BillboardObject() void BillboardObject::setVisible(const bool visible) { - mNode->setVisible(visible); + mBBSet->setVisible(visible); } void BillboardObject::setSize(const float size) @@ -88,7 +89,7 @@ void BillboardObject::init(const String& textureName, /// \todo These billboards are not 100% correct, might want to revisit them later mBBSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1); mBBSet->setDefaultDimensions(550.f*initialSize, 550.f*initialSize); - mBBSet->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+2); + mBBSet->setRenderQueueGroup(RENDER_QUEUE_MAIN+2); mBBSet->setBillboardType(BBT_PERPENDICULAR_COMMON); mBBSet->setCommonDirection( -position.normalisedCopy() ); mNode = rootNode->createChildSceneNode(); @@ -293,7 +294,7 @@ void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType) } SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environment* env) : - mGlareFade(0), mGlareEnabled(false) + mGlare(0), mGlareFade(0) { mEnvironment = env; mViewport = pCamera->getViewport(); @@ -562,10 +563,23 @@ void SkyManager::update(float duration) mMasser->setPhase( static_cast( (int) ((mDay % 32)/4.f)) ); mSecunda->setPhase ( static_cast( (int) ((mDay % 32)/4.f)) ); - // increase the strength of the sun glare effect depending - // on how directly the player is looking at the sun + if (mSunEnabled) { + // take 1/5 sec for fading the glare effect from invisible to full + if (mGlareFade > mGlare) + { + mGlareFade -= duration*5; + if (mGlareFade < mGlare) mGlareFade = mGlare; + } + else if (mGlareFade < mGlare) + { + mGlareFade += duration*5; + if (mGlareFade > mGlare) mGlareFade = mGlare; + } + + // increase the strength of the sun glare effect depending + // on how directly the player is looking at the sun Vector3 sun = mSunGlare->getPosition(); sun = Vector3(sun.x, sun.z, -sun.y); Vector3 cam = mViewport->getCamera()->getRealDirection(); @@ -573,21 +587,10 @@ void SkyManager::update(float duration) float val = 1- (angle.valueDegrees() / 180.f); val = (val*val*val*val)*2; - if (mGlareEnabled) - { - mGlareFade += duration*3; - if (mGlareFade > 1) mGlareFade = 1; - } - else - { - mGlareFade -= duration*3; - if (mGlareFade < 0.3) mGlareFade = 0; - } - - mSunGlare->setSize(val * (mGlareFade)); + mSunGlare->setSize(val * mGlareFade); } - mSunGlare->setVisible(mGlareFade>0 && mSunEnabled); + mSunGlare->setVisible(mSunEnabled); mSun->setVisible(mSunEnabled); mMasser->setVisible(mMasserEnabled); mSecunda->setVisible(mSecundaEnabled); @@ -689,15 +692,15 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather) else strength = 1.f; - mSunGlare->setVisibility(weather.mGlareView * strength); - mSun->setVisibility(strength); + mSunGlare->setVisibility(weather.mGlareView * mGlareFade * strength); + mSun->setVisibility(mGlareFade >= 0.5 ? weather.mGlareView * mGlareFade * strength : 0); mAtmosphereNight->setVisible(weather.mNight && mEnabled); } -void SkyManager::setGlare(bool glare) +void SkyManager::setGlare(const float glare) { - mGlareEnabled = glare; + mGlare = glare; } Vector3 SkyManager::getRealSunPos() @@ -782,3 +785,8 @@ void SkyManager::setDate(int day, int month) mDay = day; mMonth = month; } + +Ogre::SceneNode* SkyManager::getSunNode() +{ + return mSun->getNode(); +} diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index bf52afd8dd..508af76732 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -109,58 +109,60 @@ namespace MWRender public: SkyManager(Ogre::SceneNode* pMwRoot, Ogre::Camera* pCamera, MWWorld::Environment* env); ~SkyManager(); - + void update(float duration); - + void enable(); - + void disable(); - + void setHour (double hour); ///< will be called even when sky is disabled. - + void setDate (int day, int month); ///< will be called even when sky is disabled. - + int getMasserPhase() const; ///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half, /// 3 waxing or waning gibbous, 4 full moon - + int getSecundaPhase() const; ///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half, /// 3 waxing or waning gibbous, 4 full moon - + void setMoonColour (bool red); ///< change Secunda colour to red - + void setCloudsOpacity(float opacity); ///< change opacity of the clouds - + void setWeather(const MWWorld::WeatherResult& weather); - + + Ogre::SceneNode* getSunNode(); + void sunEnable(); - + void sunDisable(); - + void setSunDirection(const Ogre::Vector3& direction); - + void setMasserDirection(const Ogre::Vector3& direction); - + void setSecundaDirection(const Ogre::Vector3& direction); - + void setMasserFade(const float fade); - + void setSecundaFade(const float fade); - + void masserEnable(); void masserDisable(); void secundaEnable(); void secundaDisable(); - + void setThunder(const float factor); - - void setGlare(bool glare); + + void setGlare(const float glare); Ogre::Vector3 getRealSunPos(); private: @@ -203,12 +205,12 @@ namespace MWRender float mRemainingTransitionTime; - float mGlareFade; + float mGlare; // target + float mGlareFade; // actual void ModVertexAlpha(Ogre::Entity* ent, unsigned int meshType); bool mEnabled; - bool mGlareEnabled; bool mSunEnabled; bool mMasserEnabled; bool mSecundaEnabled; diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index a636ce2887..261f66ff4f 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -705,13 +705,16 @@ namespace MWWorld mWeatherManager->update (duration); - // cast a ray from player to sun to detect if the sun is visible - // this is temporary until we find a better place to put this code - // currently its here because we need to access the physics system - float* p = mPlayer->getPlayer().getRefData().getPosition().pos; - Vector3 sun = mRendering->getSkyManager()->getRealSunPos(); - sun = Vector3(sun.x, -sun.z, sun.y); - mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun)); + if (!mRendering->occlusionQuerySupported()) + { + // cast a ray from player to sun to detect if the sun is visible + // this is temporary until we find a better place to put this code + // currently its here because we need to access the physics system + float* p = mPlayer->getPlayer().getRefData().getPosition().pos; + Vector3 sun = mRendering->getSkyManager()->getRealSunPos(); + sun = Vector3(sun.x, -sun.z, sun.y); + mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun)); + } } bool World::isCellExterior() const From e212a3235011986ad9fda7f58ac354c79e971f21 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 24 Mar 2012 18:38:58 +0100 Subject: [PATCH 03/40] bugfix --- apps/openmw/mwrender/occlusionquery.cpp | 15 +++++++++++-- apps/openmw/mwrender/occlusionquery.hpp | 29 +++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 6c74561e95..baf55b0249 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -45,19 +45,21 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod matQueryVisible->setColourWriteEnabled(false); matQueryVisible->setDepthCheckEnabled(true); // Occluded by objects + mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode(); + mBBQueryTotal = mRendering->getScene()->createBillboardSet(1); mBBQueryTotal->setDefaultDimensions(150, 150); mBBQueryTotal->createBillboard(Vector3::ZERO); mBBQueryTotal->setMaterialName("QueryTotalPixels"); mBBQueryTotal->setRenderQueueGroup(queue); - mSunNode->attachObject(mBBQueryTotal); + mBBNode->attachObject(mBBQueryTotal); mBBQueryVisible = mRendering->getScene()->createBillboardSet(1); mBBQueryVisible->setDefaultDimensions(150, 150); mBBQueryVisible->createBillboard(Vector3::ZERO); mBBQueryVisible->setMaterialName("QueryVisiblePixels"); mBBQueryVisible->setRenderQueueGroup(queue); - mSunNode->attachObject(mBBQueryVisible); + mBBNode->attachObject(mBBQueryVisible); mRendering->getScene()->addRenderObjectListener(this); mDoQuery = true; @@ -110,6 +112,15 @@ void OcclusionQuery::update() { if (!mSupported) return; + // Adjust the position of the sun billboards according to camera viewing distance + // we need to do this to make sure that _everything_ can occlude the sun + float dist = mRendering->getCamera()->getFarClipDistance(); + if (dist==0) dist = 10000000; + dist -= 1000; // bias + dist /= 1000.f; + mBBNode->setPosition(mSunNode->getPosition() * dist); + mBBNode->setScale(dist, dist, dist); + // Stop occlusion queries until we get their information // (may not happen on the same frame they are requested in) mDoQuery = false; diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index e6adc0d4b3..2545e590e9 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -17,11 +17,32 @@ namespace MWRender OcclusionQuery(OEngine::Render::OgreRenderer*, Ogre::SceneNode* sunNode); ~OcclusionQuery(); + /** + * @return true if occlusion queries are supported on the user's hardware + */ bool supported(); - ///< returns true if occlusion queries are supported on the user's hardware + /** + * per-frame update + */ void update(); - ///< per-frame update + + /** + * request occlusion test for a billboard at the given position, omitting an entity + * @param position of the billboard in ogre coordinates + * @param entity to exclude from the occluders + */ + void occlusionTest(const Ogre::Vector3& position, Ogre::Entity* entity); + + /** + * @return true if a request is still outstanding + */ + bool occlusionTestPending(); + + /** + * @return true if the object tested in the last request was occluded + */ + bool getTestResult(); float getSunVisibility() const {return mSunVisibility;}; @@ -35,8 +56,12 @@ namespace MWRender Ogre::SceneNode* mSunNode; + Ogre::SceneNode* mBBNode; + float mSunVisibility; + bool mTestResult; + bool mSupported; bool mDoQuery; From 9d30a139cc416a078c6f63871e7d584f982fc2a1 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 24 Mar 2012 20:41:23 +0100 Subject: [PATCH 04/40] added api --- apps/openmw/mwrender/occlusionquery.cpp | 73 +++++++++++++++++++++++-- apps/openmw/mwrender/occlusionquery.hpp | 20 ++++++- 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index baf55b0249..8dd30394c9 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -3,12 +3,16 @@ #include #include #include +#include +#include using namespace MWRender; using namespace Ogre; OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNode* sunNode) : - mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mActiveQuery(0), mDoQuery(0), mSunVisibility(0) + mSunTotalAreaQuery(0), mSunVisibleAreaQuery(0), mSingleObjectQuery(0), mActiveQuery(0), + mDoQuery(0), mSunVisibility(0), mQuerySingleObjectStarted(false), + mQuerySingleObjectRequested(false) { mRendering = renderer; mSunNode = sunNode; @@ -18,8 +22,9 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mSunTotalAreaQuery = renderSystem->createHardwareOcclusionQuery(); mSunVisibleAreaQuery = renderSystem->createHardwareOcclusionQuery(); + mSingleObjectQuery = renderSystem->createHardwareOcclusionQuery(); - mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0); + mSupported = (mSunTotalAreaQuery != 0) && (mSunVisibleAreaQuery != 0) && (mSingleObjectQuery != 0); } catch (Ogre::Exception e) { @@ -47,6 +52,8 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode(); + mObjectNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode(); + mBBQueryTotal = mRendering->getScene()->createBillboardSet(1); mBBQueryTotal->setDefaultDimensions(150, 150); mBBQueryTotal->createBillboard(Vector3::ZERO); @@ -61,6 +68,13 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBQueryVisible->setRenderQueueGroup(queue); mBBNode->attachObject(mBBQueryVisible); + mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1); + mBBQuerySingleObject->setDefaultDimensions(10, 10); + mBBQuerySingleObject->createBillboard(Vector3::ZERO); + mBBQuerySingleObject->setMaterialName("QueryVisiblePixels"); + mBBQuerySingleObject->setRenderQueueGroup(queue); + mObjectNode->attachObject(mBBQuerySingleObject); + mRendering->getScene()->addRenderObjectListener(this); mDoQuery = true; } @@ -70,6 +84,7 @@ OcclusionQuery::~OcclusionQuery() RenderSystem* renderSystem = Root::getSingleton().getRenderSystem(); if (mSunTotalAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunTotalAreaQuery); if (mSunVisibleAreaQuery) renderSystem->destroyHardwareOcclusionQuery(mSunVisibleAreaQuery); + if (mSingleObjectQuery) renderSystem->destroyHardwareOcclusionQuery(mSingleObjectQuery); } bool OcclusionQuery::supported() @@ -100,11 +115,15 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass mActiveQuery = mSunTotalAreaQuery; else if (rend == mBBQueryVisible) mActiveQuery = mSunVisibleAreaQuery; + else if (rend == mBBQuerySingleObject && mQuerySingleObjectRequested) + { + mQuerySingleObjectStarted = true; + mQuerySingleObjectRequested = false; + mActiveQuery = mSingleObjectQuery; + } if (mActiveQuery != NULL) - { mActiveQuery->beginOcclusionQuery(); - } } } @@ -125,7 +144,9 @@ void OcclusionQuery::update() // (may not happen on the same frame they are requested in) mDoQuery = false; - if (!mSunTotalAreaQuery->isStillOutstanding() && !mSunVisibleAreaQuery->isStillOutstanding()) + if (!mSunTotalAreaQuery->isStillOutstanding() + && !mSunVisibleAreaQuery->isStillOutstanding() + && !mSingleObjectQuery->isStillOutstanding()) { unsigned int totalPixels; unsigned int visiblePixels; @@ -144,7 +165,49 @@ void OcclusionQuery::update() if (mSunVisibility > 1) mSunVisibility = 1; } + if (mQuerySingleObjectStarted) + { + unsigned int visiblePixels; + + mSingleObjectQuery->pullOcclusionQuery(&visiblePixels); + + mBBQuerySingleObject->setVisible(false); + mObject->setRenderQueueGroup(mObjectOldRenderQueue); + + mQuerySingleObjectStarted = false; + mQuerySingleObjectRequested = false; + } + mDoQuery = true; } } +void OcclusionQuery::occlusionTest(const Ogre::Vector3& position, Ogre::Entity* entity) +{ + assert( !occlusionTestPending() + && "Occlusion test still pending"); + + mBBQuerySingleObject->setVisible(true); + + // we don't want the object to occlude itself + mObjectOldRenderQueue = entity->getRenderQueueGroup(); + if (mObjectOldRenderQueue < RENDER_QUEUE_MAIN+2) + entity->setRenderQueueGroup(RENDER_QUEUE_MAIN+2); + + mObjectNode->setPosition(position); + + mQuerySingleObjectRequested = true; +} + +bool OcclusionQuery::occlusionTestPending() +{ + return (mQuerySingleObjectRequested || mQuerySingleObjectStarted); +} + +bool OcclusionQuery::getTestResult() +{ + assert( !occlusionTestPending() + && "Occlusion test still pending"); + + return mTestResult; +} diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index 2545e590e9..bcc45d96c6 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -1,9 +1,15 @@ #ifndef _GAME_OCCLUSION_QUERY_H #define _GAME_OCCLUSION_QUERY_H -#include #include +namespace Ogre +{ + class HardwareOcclusionQuery; + class Entity; + class SceneNode; +} + #include namespace MWRender @@ -49,22 +55,30 @@ namespace MWRender private: Ogre::HardwareOcclusionQuery* mSunTotalAreaQuery; Ogre::HardwareOcclusionQuery* mSunVisibleAreaQuery; + Ogre::HardwareOcclusionQuery* mSingleObjectQuery; Ogre::HardwareOcclusionQuery* mActiveQuery; Ogre::BillboardSet* mBBQueryVisible; Ogre::BillboardSet* mBBQueryTotal; + Ogre::BillboardSet* mBBQuerySingleObject; Ogre::SceneNode* mSunNode; - Ogre::SceneNode* mBBNode; - float mSunVisibility; + Ogre::Entity* mObject; + + Ogre::SceneNode* mObjectNode; + int mObjectOldRenderQueue; + bool mTestResult; bool mSupported; bool mDoQuery; + bool mQuerySingleObjectRequested; + bool mQuerySingleObjectStarted; + OEngine::Render::OgreRenderer* mRendering; protected: From 17a4adfe88aded63fd21fe5d3ab658aa62c354c8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 25 Mar 2012 12:26:44 +0200 Subject: [PATCH 05/40] add raycast method that returns _all_ objects that were hit --- libs/openengine/bullet/physic.cpp | 31 +++++++++++++++++++++++++++++++ libs/openengine/bullet/physic.hpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index 07bad30535..e6a7393cca 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -372,4 +372,35 @@ namespace Physic return std::pair(name,d); } + + std::vector< std::pair > PhysicEngine::rayTest2(btVector3& from, btVector3& to) + { + MyRayResultCallback resultCallback1; + resultCallback1.m_collisionFilterMask = COL_WORLD; + dynamicsWorld->rayTest(from, to, resultCallback1); + resultCallback1.sort(); + std::vector< std::pair > results = resultCallback1.results; + + MyRayResultCallback resultCallback2; + resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL; + dynamicsWorld->rayTest(from, to, resultCallback2); + resultCallback2.sort(); + std::vector< std::pair > actorResults = resultCallback2.results; + + std::vector< std::pair > results2; + + for (std::vector< std::pair >::iterator it=results.begin(); + it != results.end(); ++it) + { + results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); + } + + for (std::vector< std::pair >::iterator it=actorResults.begin(); + it != actorResults.end(); ++it) + { + results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); + } + + return results2; + } }}; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 88e3699aee..97d2c004d1 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -201,6 +201,11 @@ namespace Physic */ std::pair rayTest(btVector3& from,btVector3& to); + /** + * Return all objects hit by a ray. + */ + std::vector< std::pair > rayTest2(btVector3& from, btVector3& to); + //event list of non player object std::list NPEventList; @@ -225,6 +230,30 @@ namespace Physic bool isDebugCreated; }; + + struct MyRayResultCallback : public btCollisionWorld::RayResultCallback + { + virtual btScalar addSingleResult( btCollisionWorld::LocalRayResult& rayResult, bool bNormalInWorldSpace) + { + results.push_back( std::make_pair(rayResult.m_hitFraction, rayResult.m_collisionObject) ); + return rayResult.m_hitFraction; + } + + static bool cmp( const std::pair& i, const std::pair& j ) + { + if( i.first < j.first ) return false; + if( j.first < i.first ) return true; + return false; + } + + void sort() + { + std::sort(results.begin(), results.end(), cmp); + } + + std::vector < std::pair > results; + }; + }} #endif From 53d4be5cf650edfb0730aa3424d19e70ebfcec40 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 25 Mar 2012 20:52:56 +0200 Subject: [PATCH 06/40] object pickup should work everywhere --- apps/openmw/mwrender/occlusionquery.cpp | 105 +++++++++++++++------- apps/openmw/mwrender/occlusionquery.hpp | 22 +++-- apps/openmw/mwrender/renderingmanager.hpp | 1 + apps/openmw/mwworld/physicssystem.cpp | 27 ++++++ apps/openmw/mwworld/physicssystem.hpp | 6 +- apps/openmw/mwworld/world.cpp | 73 +++++++++++++-- apps/openmw/mwworld/world.hpp | 6 ++ libs/openengine/bullet/physic.hpp | 4 +- 8 files changed, 198 insertions(+), 46 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 8dd30394c9..66086a90b8 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -47,7 +47,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod matQueryArea->setDepthCheckEnabled(false); // Not occluded by objects MaterialPtr matQueryVisible = matBase->clone("QueryVisiblePixels"); matQueryVisible->setDepthWriteEnabled(false); - matQueryVisible->setColourWriteEnabled(false); + matQueryVisible->setColourWriteEnabled(false); // Uncomment this to visualize the occlusion query matQueryVisible->setDepthCheckEnabled(true); // Occluded by objects mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode(); @@ -69,13 +69,14 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBNode->attachObject(mBBQueryVisible); mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1); - mBBQuerySingleObject->setDefaultDimensions(10, 10); + mBBQuerySingleObject->setDefaultDimensions(0.01, 0.01); mBBQuerySingleObject->createBillboard(Vector3::ZERO); mBBQuerySingleObject->setMaterialName("QueryVisiblePixels"); mBBQuerySingleObject->setRenderQueueGroup(queue); mObjectNode->attachObject(mBBQuerySingleObject); mRendering->getScene()->addRenderObjectListener(this); + mRendering->getScene()->addRenderQueueListener(this); mDoQuery = true; } @@ -95,8 +96,6 @@ bool OcclusionQuery::supported() void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source, const LightList* pLightList, bool suppressRenderStateChanges) { - if (!mSupported) return; - // The following code activates and deactivates the occlusion queries // so that the queries only include the rendering of their intended targets @@ -111,26 +110,47 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass // Open a new occlusion query if (mDoQuery == true) { - if (rend == mBBQueryTotal) - mActiveQuery = mSunTotalAreaQuery; - else if (rend == mBBQueryVisible) - mActiveQuery = mSunVisibleAreaQuery; - else if (rend == mBBQuerySingleObject && mQuerySingleObjectRequested) + if (rend == mBBQueryTotal) { - mQuerySingleObjectStarted = true; - mQuerySingleObjectRequested = false; - mActiveQuery = mSingleObjectQuery; + mActiveQuery = mSunTotalAreaQuery; + mWasVisible = true; + } + else if (rend == mBBQueryVisible) + { + mActiveQuery = mSunVisibleAreaQuery; } - - if (mActiveQuery != NULL) - mActiveQuery->beginOcclusionQuery(); } + if (rend == mBBQuerySingleObject && mQuerySingleObjectRequested) + { + mQuerySingleObjectStarted = true; + mQuerySingleObjectRequested = false; + mActiveQuery = mSingleObjectQuery; + } + + if (mActiveQuery != NULL) + mActiveQuery->beginOcclusionQuery(); +} + +void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocation, bool& repeatThisInvocation) +{ + if (queueGroupId == RENDER_QUEUE_SKIES_LATE && mWasVisible == false) + { + // for some reason our single object query returns wrong results when the sun query was never executed + // (which can happen when we are in interiors, or when the sun is outside of the view frustum and gets culled) + // so we force it here once everything has been rendered + mSunTotalAreaQuery->beginOcclusionQuery(); + mSunTotalAreaQuery->endOcclusionQuery(); + mSunVisibleAreaQuery->beginOcclusionQuery(); + mSunVisibleAreaQuery->endOcclusionQuery(); + } } void OcclusionQuery::update() { if (!mSupported) return; + mWasVisible = false; + // Adjust the position of the sun billboards according to camera viewing distance // we need to do this to make sure that _everything_ can occlude the sun float dist = mRendering->getCamera()->getFarClipDistance(); @@ -145,8 +165,7 @@ void OcclusionQuery::update() mDoQuery = false; if (!mSunTotalAreaQuery->isStillOutstanding() - && !mSunVisibleAreaQuery->isStillOutstanding() - && !mSingleObjectQuery->isStillOutstanding()) + && !mSunVisibleAreaQuery->isStillOutstanding()) { unsigned int totalPixels; unsigned int visiblePixels; @@ -165,24 +184,33 @@ void OcclusionQuery::update() if (mSunVisibility > 1) mSunVisibility = 1; } - if (mQuerySingleObjectStarted) + mDoQuery = true; + } + if (!mSingleObjectQuery->isStillOutstanding() && mQuerySingleObjectStarted) + { + unsigned int result; + + mSingleObjectQuery->pullOcclusionQuery(&result); + + //std::cout << "Single object query result: " << result << " pixels " << std::endl; + mTestResult = (result != 0); + + mBBQuerySingleObject->setVisible(false); + + // restore old render queues + for (std::vector::iterator it=mObjectsInfo.begin(); + it!=mObjectsInfo.end(); ++it) { - unsigned int visiblePixels; - - mSingleObjectQuery->pullOcclusionQuery(&visiblePixels); - - mBBQuerySingleObject->setVisible(false); - mObject->setRenderQueueGroup(mObjectOldRenderQueue); - - mQuerySingleObjectStarted = false; - mQuerySingleObjectRequested = false; + if (!mRendering->getScene()->hasMovableObject((*it).name, (*it).typeName)) return; + mRendering->getScene()->getMovableObject((*it).name, (*it).typeName)->setRenderQueueGroup( (*it).oldRenderqueue ); } - mDoQuery = true; + mQuerySingleObjectStarted = false; + mQuerySingleObjectRequested = false; } } -void OcclusionQuery::occlusionTest(const Ogre::Vector3& position, Ogre::Entity* entity) +void OcclusionQuery::occlusionTest(const Ogre::Vector3& position, Ogre::SceneNode* object) { assert( !occlusionTestPending() && "Occlusion test still pending"); @@ -190,11 +218,24 @@ void OcclusionQuery::occlusionTest(const Ogre::Vector3& position, Ogre::Entity* mBBQuerySingleObject->setVisible(true); // we don't want the object to occlude itself - mObjectOldRenderQueue = entity->getRenderQueueGroup(); - if (mObjectOldRenderQueue < RENDER_QUEUE_MAIN+2) - entity->setRenderQueueGroup(RENDER_QUEUE_MAIN+2); + // put it in a render queue _after_ the occlusion query + mObjectsInfo.clear(); + for (int i=0; inumAttachedObjects(); ++i) + { + ObjectInfo info; + MovableObject* obj = object->getAttachedObject(i); + info.name = obj->getName(); + info.typeName = obj->getMovableType(); + info.oldRenderqueue = obj->getRenderQueueGroup(); + + mObjectsInfo.push_back(info); + + object->getAttachedObject(i)->setRenderQueueGroup(RENDER_QUEUE_MAIN+5); + } mObjectNode->setPosition(position); + // scale proportional to camera distance, in order to always give the billboard the same size in screen-space + mObjectNode->setScale( Vector3(1,1,1)*(position - mRendering->getCamera()->getRealPosition()).length() ); mQuerySingleObjectRequested = true; } diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index bcc45d96c6..987087e278 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -2,6 +2,7 @@ #define _GAME_OCCLUSION_QUERY_H #include +#include namespace Ogre { @@ -17,7 +18,14 @@ namespace MWRender /// /// \brief Implements hardware occlusion queries on the GPU /// - class OcclusionQuery : public Ogre::RenderObjectListener + struct ObjectInfo + { + int oldRenderqueue; + std::string name; + std::string typeName; + }; + + class OcclusionQuery : public Ogre::RenderObjectListener, public Ogre::RenderQueueListener { public: OcclusionQuery(OEngine::Render::OgreRenderer*, Ogre::SceneNode* sunNode); @@ -36,9 +44,9 @@ namespace MWRender /** * request occlusion test for a billboard at the given position, omitting an entity * @param position of the billboard in ogre coordinates - * @param entity to exclude from the occluders + * @param object to exclude from the occluders */ - void occlusionTest(const Ogre::Vector3& position, Ogre::Entity* entity); + void occlusionTest(const Ogre::Vector3& position, Ogre::SceneNode* object); /** * @return true if a request is still outstanding @@ -66,10 +74,10 @@ namespace MWRender Ogre::SceneNode* mBBNode; float mSunVisibility; - Ogre::Entity* mObject; - Ogre::SceneNode* mObjectNode; - int mObjectOldRenderQueue; + std::vector mObjectsInfo; + + bool mWasVisible; bool mTestResult; @@ -84,6 +92,8 @@ namespace MWRender protected: virtual void notifyRenderSingleObject(Ogre::Renderable* rend, const Ogre::Pass* pass, const Ogre::AutoParamDataSource* source, const Ogre::LightList* pLightList, bool suppressRenderStateChanges); + + virtual void renderQueueEnded(Ogre::uint8 queueGroupId, const Ogre::String& invocation, bool& repeatThisInvocation); }; } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 450e461730..569447bca3 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -100,6 +100,7 @@ class RenderingManager: private RenderingInterface { void sunDisable(); bool occlusionQuerySupported() { return mOcclusionQuery->supported(); }; + OcclusionQuery* getOcclusionQuery() { return mOcclusionQuery; }; void setGlare(bool glare); void skyEnable (); diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index bb2f9f8a92..1d8f14cc42 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -50,6 +50,33 @@ namespace MWWorld return mEngine->rayTest(from,to); } + + std::vector < std::pair > PhysicsSystem::getFacedObjects () + { + //get a ray pointing to the center of the viewport + Ray centerRay = mRender.getCamera()->getCameraToViewportRay( + mRender.getViewport()->getWidth()/2, + mRender.getViewport()->getHeight()/2); + //let's avoid the capsule shape of the player. + centerRay.setOrigin(centerRay.getOrigin() + 20*centerRay.getDirection()); + btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); + btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); + + return mEngine->rayTest2(from,to); + } + + btVector3 PhysicsSystem::getRayPoint(float extent) + { + //get a ray pointing to the center of the viewport + Ray centerRay = mRender.getCamera()->getCameraToViewportRay( + mRender.getViewport()->getWidth()/2, + mRender.getViewport()->getHeight()/2); + //let's avoid the capsule shape of the player. + centerRay.setOrigin(centerRay.getOrigin() + 20*centerRay.getDirection()); + btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); + btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); + return from * (1-extent) + to * extent; + } bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to) { diff --git a/apps/openmw/mwworld/physicssystem.hpp b/apps/openmw/mwworld/physicssystem.hpp index 78cbde0837..7b2d77325e 100644 --- a/apps/openmw/mwworld/physicssystem.hpp +++ b/apps/openmw/mwworld/physicssystem.hpp @@ -35,7 +35,11 @@ namespace MWWorld bool toggleCollisionMode(); std::pair getFacedHandle (MWWorld::World& world); - + + btVector3 getRayPoint(float extent); + + std::vector < std::pair > getFacedObjects (); + // cast ray, return true if it hit something bool castRay(const Ogre::Vector3& from, const Ogre::Vector3& to); diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 261f66ff4f..f185e411f8 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -498,13 +498,21 @@ namespace MWWorld std::string World::getFacedHandle() { - std::pair result = mPhysics->getFacedHandle (*this); + if (!mRendering->occlusionQuerySupported()) + { + std::pair result = mPhysics->getFacedHandle (*this); - if (result.first.empty() || - result.second>getStore().gameSettings.find ("iMaxActivateDist")->i) - return ""; + if (result.first.empty() || + result.second>getStore().gameSettings.find ("iMaxActivateDist")->i) + return ""; - return result.first; + return result.first; + } + else + { + // updated every few frames in update() + return mFacedHandle; + } } void World::deleteObject (Ptr ptr) @@ -715,6 +723,61 @@ namespace MWWorld sun = Vector3(sun.x, -sun.z, sun.y); mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun)); } + + // update faced handle (object the player is looking at) + // this uses a mixture of raycasts and occlusion queries. + else // if (mRendering->occlusionQuerySupported()) + { + 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 = mPhysics->getFacedObjects(); + + if (results.size() == 0) + { + mNumFacing = 0; + } + else if (results.size() == 1) + { + mFaced1 = getPtrViaHandle(results.front().second); + mFaced1Name = results.front().second; + mNumFacing = 1; + + 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 + { + mFaced1Name = results.front().second; + mFaced2Name = results[1].second; + mFaced1 = getPtrViaHandle(results.front().second); + mFaced2 = getPtrViaHandle(results[1].second); + mNumFacing = 2; + + 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); + } + } + } } bool World::isCellExterior() const diff --git a/apps/openmw/mwworld/world.hpp b/apps/openmw/mwworld/world.hpp index 71cca3545d..7d8a1b9a0a 100644 --- a/apps/openmw/mwworld/world.hpp +++ b/apps/openmw/mwworld/world.hpp @@ -93,6 +93,12 @@ namespace MWWorld Ptr getPtrViaHandle (const std::string& handle, Ptr::CellStore& cellStore); + std::string mFacedHandle; + Ptr mFaced1; + Ptr mFaced2; + std::string mFaced1Name; + std::string mFaced2Name; + int mNumFacing; int getDaysPerMonth (int month) const; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 97d2c004d1..3ecae7c0cc 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -241,8 +241,8 @@ namespace Physic static bool cmp( const std::pair& i, const std::pair& j ) { - if( i.first < j.first ) return false; - if( j.first < i.first ) return true; + if( i.first > j.first ) return false; + if( j.first > i.first ) return true; return false; } From 382fa6ac688097eb2980067255f4b8fe9395f3cd Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 25 Mar 2012 22:53:00 +0200 Subject: [PATCH 07/40] fixes --- apps/openmw/mwrender/occlusionquery.cpp | 10 +++++++--- libs/openengine/bullet/physic.cpp | 4 ++-- libs/openengine/bullet/physic.hpp | 7 +------ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 66086a90b8..b5f3f9c102 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -49,6 +49,8 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod matQueryVisible->setDepthWriteEnabled(false); matQueryVisible->setColourWriteEnabled(false); // Uncomment this to visualize the occlusion query matQueryVisible->setDepthCheckEnabled(true); // Occluded by objects + matQueryVisible->setCullingMode(CULL_NONE); + matQueryVisible->setManualCullingMode(MANUAL_CULL_NONE); mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode(); @@ -133,16 +135,18 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocation, bool& repeatThisInvocation) { - if (queueGroupId == RENDER_QUEUE_SKIES_LATE && mWasVisible == false) + if (queueGroupId == RENDER_QUEUE_SKIES_LATE && mWasVisible == false && mDoQuery) { // for some reason our single object query returns wrong results when the sun query was never executed // (which can happen when we are in interiors, or when the sun is outside of the view frustum and gets culled) // so we force it here once everything has been rendered + mSunTotalAreaQuery->beginOcclusionQuery(); mSunTotalAreaQuery->endOcclusionQuery(); mSunVisibleAreaQuery->beginOcclusionQuery(); mSunVisibleAreaQuery->endOcclusionQuery(); - } + + } } void OcclusionQuery::update() @@ -201,7 +205,7 @@ void OcclusionQuery::update() for (std::vector::iterator it=mObjectsInfo.begin(); it!=mObjectsInfo.end(); ++it) { - if (!mRendering->getScene()->hasMovableObject((*it).name, (*it).typeName)) return; + if (!mRendering->getScene()->hasMovableObject((*it).name, (*it).typeName)) break; mRendering->getScene()->getMovableObject((*it).name, (*it).typeName)->setRenderQueueGroup( (*it).oldRenderqueue ); } diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index e6a7393cca..b1cd9eadee 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -378,13 +378,11 @@ namespace Physic MyRayResultCallback resultCallback1; resultCallback1.m_collisionFilterMask = COL_WORLD; dynamicsWorld->rayTest(from, to, resultCallback1); - resultCallback1.sort(); std::vector< std::pair > results = resultCallback1.results; MyRayResultCallback resultCallback2; resultCallback2.m_collisionFilterMask = COL_ACTOR_INTERNAL|COL_ACTOR_EXTERNAL; dynamicsWorld->rayTest(from, to, resultCallback2); - resultCallback2.sort(); std::vector< std::pair > actorResults = resultCallback2.results; std::vector< std::pair > results2; @@ -401,6 +399,8 @@ namespace Physic results2.push_back( std::make_pair( (*it).first, static_cast(*(*it).second).mName ) ); } + std::sort(results2.begin(), results2.end(), MyRayResultCallback::cmp); + return results2; } }}; diff --git a/libs/openengine/bullet/physic.hpp b/libs/openengine/bullet/physic.hpp index 3ecae7c0cc..f6c52cbf95 100644 --- a/libs/openengine/bullet/physic.hpp +++ b/libs/openengine/bullet/physic.hpp @@ -239,18 +239,13 @@ namespace Physic return rayResult.m_hitFraction; } - static bool cmp( const std::pair& i, const std::pair& j ) + static bool cmp( const std::pair& i, const std::pair& j ) { if( i.first > j.first ) return false; if( j.first > i.first ) return true; return false; } - void sort() - { - std::sort(results.begin(), results.end(), cmp); - } - std::vector < std::pair > results; }; From 98a33a7fc6c7f9e3f75f8ccbd93e7625a330eb1f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 25 Mar 2012 23:28:51 +0200 Subject: [PATCH 08/40] fix --- apps/openmw/mwrender/occlusionquery.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index b5f3f9c102..971815f9bf 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -71,7 +71,8 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBNode->attachObject(mBBQueryVisible); mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1); - mBBQuerySingleObject->setDefaultDimensions(0.01, 0.01); + /// \todo ideally this should occupy exactly 1 pixel on the screen + mBBQuerySingleObject->setDefaultDimensions(0.003, 0.003); mBBQuerySingleObject->createBillboard(Vector3::ZERO); mBBQuerySingleObject->setMaterialName("QueryVisiblePixels"); mBBQuerySingleObject->setRenderQueueGroup(queue); From 4ee03cd61fef8d71e0a4614ef512e34ce30fa278 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 Mar 2012 00:31:03 +0200 Subject: [PATCH 09/40] handle timeout --- apps/openmw/mwrender/occlusionquery.cpp | 16 +++++++++++++--- apps/openmw/mwrender/occlusionquery.hpp | 6 +++++- apps/openmw/mwrender/renderingmanager.cpp | 2 +- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 971815f9bf..6718a588bc 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -12,7 +12,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), - mQuerySingleObjectRequested(false) + mQuerySingleObjectRequested(false), mResponding(true), mDelay(0) { mRendering = renderer; mSunNode = sunNode; @@ -93,7 +93,8 @@ OcclusionQuery::~OcclusionQuery() bool OcclusionQuery::supported() { - return mSupported; + if (!mResponding) std::cout << "Occlusion query timed out" << std::endl; + return mSupported && mResponding; } void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source, @@ -150,10 +151,13 @@ void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocati } } -void OcclusionQuery::update() +void OcclusionQuery::update(float duration) { if (!mSupported) return; + mDelay += duration; + if (mDelay >= 2) mResponding = false; + mWasVisible = false; // Adjust the position of the sun billboards according to camera viewing distance @@ -172,6 +176,9 @@ void OcclusionQuery::update() if (!mSunTotalAreaQuery->isStillOutstanding() && !mSunVisibleAreaQuery->isStillOutstanding()) { + mDelay = 0; + mResponding = true; + unsigned int totalPixels; unsigned int visiblePixels; @@ -193,6 +200,9 @@ void OcclusionQuery::update() } if (!mSingleObjectQuery->isStillOutstanding() && mQuerySingleObjectStarted) { + mDelay = 0; + mResponding = true; + unsigned int result; mSingleObjectQuery->pullOcclusionQuery(&result); diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index 987087e278..004190cd90 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -39,7 +39,7 @@ namespace MWRender /** * per-frame update */ - void update(); + void update(float duration); /** * request occlusion test for a billboard at the given position, omitting an entity @@ -79,6 +79,10 @@ namespace MWRender bool mWasVisible; + bool mResponding; + + float mDelay; + bool mTestResult; bool mSupported; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index b4711e8df7..2aec95e813 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -150,7 +150,7 @@ void RenderingManager::update (float duration){ mActors.update (duration); - mOcclusionQuery->update(); + mOcclusionQuery->update(duration); mSkyManager->update(duration); From bb3f3ce1db69ab935320bd9ddff0d540ccc25bc0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Mon, 26 Mar 2012 21:52:38 +0200 Subject: [PATCH 10/40] bugfix --- apps/openmw/mwrender/occlusionquery.cpp | 39 ++++++++++++++++--------- apps/openmw/mwrender/occlusionquery.hpp | 1 + apps/openmw/mwrender/sky.cpp | 3 +- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 6718a588bc..c3285a3359 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -12,7 +12,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), - mQuerySingleObjectRequested(false), mResponding(true), mDelay(0) + mQuerySingleObjectRequested(false), mResponding(true), mDelay(0), mWasVisible(false), mObjectWasVisible(false) { mRendering = renderer; mSunNode = sunNode; @@ -93,7 +93,7 @@ OcclusionQuery::~OcclusionQuery() bool OcclusionQuery::supported() { - if (!mResponding) std::cout << "Occlusion query timed out" << std::endl; + //if (!mResponding) std::cout << "Occlusion query timed out" << std::endl; return mSupported && mResponding; } @@ -129,6 +129,7 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass mQuerySingleObjectStarted = true; mQuerySingleObjectRequested = false; mActiveQuery = mSingleObjectQuery; + mObjectWasVisible = true; } if (mActiveQuery != NULL) @@ -136,18 +137,29 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass } void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocation, bool& repeatThisInvocation) -{ - if (queueGroupId == RENDER_QUEUE_SKIES_LATE && mWasVisible == false && mDoQuery) +{ + /** + * for every beginOcclusionQuery(), we want a respective pullOcclusionQuery() and vice versa + * this also means that results can be wrong at other places if we pull, but beginOcclusionQuery() was never called + * this can happen for example if the object that is tested is outside of the view frustum + * to prevent this, check if the queries have been performed after everything has been rendered and if not, start them manually + */ + if (queueGroupId == RENDER_QUEUE_SKIES_LATE) { - // for some reason our single object query returns wrong results when the sun query was never executed - // (which can happen when we are in interiors, or when the sun is outside of the view frustum and gets culled) - // so we force it here once everything has been rendered - - mSunTotalAreaQuery->beginOcclusionQuery(); - mSunTotalAreaQuery->endOcclusionQuery(); - mSunVisibleAreaQuery->beginOcclusionQuery(); - mSunVisibleAreaQuery->endOcclusionQuery(); - + if (mWasVisible == false && mDoQuery) + { + mSunTotalAreaQuery->beginOcclusionQuery(); + mSunTotalAreaQuery->endOcclusionQuery(); + mSunVisibleAreaQuery->beginOcclusionQuery(); + mSunVisibleAreaQuery->endOcclusionQuery(); + } + if (mObjectWasVisible == false && mQuerySingleObjectRequested) + { + mSingleObjectQuery->beginOcclusionQuery(); + mSingleObjectQuery->endOcclusionQuery(); + mQuerySingleObjectStarted = true; + mQuerySingleObjectRequested = false; + } } } @@ -159,6 +171,7 @@ void OcclusionQuery::update(float duration) if (mDelay >= 2) mResponding = false; mWasVisible = false; + mObjectWasVisible = false; // Adjust the position of the sun billboards according to camera viewing distance // we need to do this to make sure that _everything_ can occlude the sun diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index 004190cd90..a9fa0b5e4a 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -78,6 +78,7 @@ namespace MWRender std::vector mObjectsInfo; bool mWasVisible; + bool mObjectWasVisible; bool mResponding; diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index a70913b239..954b462095 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -294,7 +294,8 @@ void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType) } SkyManager::SkyManager (SceneNode* pMwRoot, Camera* pCamera, MWWorld::Environment* env) : - mGlare(0), mGlareFade(0) + mGlare(0), mGlareFade(0), mCloudBlendFactor(0), + mCloudOpacity(0), mCloudColour(1,1,1), mSkyColour(1,1,1), mCloudSpeed(0), mStarsOpacity(0) { mEnvironment = env; mViewport = pCamera->getViewport(); From e398c51f8a9b641b43658d14639f67301f8d0e11 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 Mar 2012 13:13:28 +0200 Subject: [PATCH 11/40] remove unneeded render queue workaround --- apps/openmw/mwrender/occlusionquery.cpp | 24 ------------------------ apps/openmw/mwrender/occlusionquery.hpp | 8 -------- 2 files changed, 32 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index c3285a3359..43a742a548 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -225,14 +225,6 @@ void OcclusionQuery::update(float duration) mBBQuerySingleObject->setVisible(false); - // restore old render queues - for (std::vector::iterator it=mObjectsInfo.begin(); - it!=mObjectsInfo.end(); ++it) - { - if (!mRendering->getScene()->hasMovableObject((*it).name, (*it).typeName)) break; - mRendering->getScene()->getMovableObject((*it).name, (*it).typeName)->setRenderQueueGroup( (*it).oldRenderqueue ); - } - mQuerySingleObjectStarted = false; mQuerySingleObjectRequested = false; } @@ -245,22 +237,6 @@ void OcclusionQuery::occlusionTest(const Ogre::Vector3& position, Ogre::SceneNod mBBQuerySingleObject->setVisible(true); - // we don't want the object to occlude itself - // put it in a render queue _after_ the occlusion query - mObjectsInfo.clear(); - for (int i=0; inumAttachedObjects(); ++i) - { - ObjectInfo info; - MovableObject* obj = object->getAttachedObject(i); - info.name = obj->getName(); - info.typeName = obj->getMovableType(); - info.oldRenderqueue = obj->getRenderQueueGroup(); - - mObjectsInfo.push_back(info); - - object->getAttachedObject(i)->setRenderQueueGroup(RENDER_QUEUE_MAIN+5); - } - mObjectNode->setPosition(position); // scale proportional to camera distance, in order to always give the billboard the same size in screen-space mObjectNode->setScale( Vector3(1,1,1)*(position - mRendering->getCamera()->getRealPosition()).length() ); diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index a9fa0b5e4a..b3e5442cfe 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -18,13 +18,6 @@ namespace MWRender /// /// \brief Implements hardware occlusion queries on the GPU /// - struct ObjectInfo - { - int oldRenderqueue; - std::string name; - std::string typeName; - }; - class OcclusionQuery : public Ogre::RenderObjectListener, public Ogre::RenderQueueListener { public: @@ -75,7 +68,6 @@ namespace MWRender float mSunVisibility; Ogre::SceneNode* mObjectNode; - std::vector mObjectsInfo; bool mWasVisible; bool mObjectWasVisible; From 8f6d10f229a45bfa2c01364a4a0e9d1a2a78200e Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 Mar 2012 20:59:58 +0200 Subject: [PATCH 12/40] fix uninitalised stuff --- apps/openmw/mwrender/occlusionquery.cpp | 4 ++-- apps/openmw/mwworld/world.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 43a742a548..2c184c3451 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -11,7 +11,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), + mDoQuery(0), mSunVisibility(0), mQuerySingleObjectStarted(false), mTestResult(false), mQuerySingleObjectRequested(false), mResponding(true), mDelay(0), mWasVisible(false), mObjectWasVisible(false) { mRendering = renderer; @@ -211,7 +211,7 @@ void OcclusionQuery::update(float duration) mDoQuery = true; } - if (!mSingleObjectQuery->isStillOutstanding() && mQuerySingleObjectStarted) + if (mQuerySingleObjectStarted && !mSingleObjectQuery->isStillOutstanding()) { mDelay = 0; mResponding = true; diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index f185e411f8..567ed8f90b 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -157,7 +157,8 @@ namespace MWWorld const std::string& master, const boost::filesystem::path& resDir, bool newGame, Environment& environment, const std::string& encoding) : mPlayer (0), mLocalScripts (mStore), mGlobalVariables (0), - mSky (true), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this) + mSky (true), mEnvironment (environment), mNextDynamicRecord (0), mCells (mStore, mEsm, *this), + mNumFacing(0) { mPhysics = new PhysicsSystem(renderer); mPhysEngine = mPhysics->getEngine(); From 43b1f896f42f986c6c19daaa3f3f78e6215e0953 Mon Sep 17 00:00:00 2001 From: scrawl Date: Tue, 27 Mar 2012 22:36:02 +0200 Subject: [PATCH 13/40] fix object pickup when player is very close to object --- apps/openmw/mwworld/physicssystem.cpp | 9 ++------- apps/openmw/mwworld/world.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 1d8f14cc42..83c3ef2bab 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -57,8 +57,6 @@ namespace MWWorld Ray centerRay = mRender.getCamera()->getCameraToViewportRay( mRender.getViewport()->getWidth()/2, mRender.getViewport()->getHeight()/2); - //let's avoid the capsule shape of the player. - centerRay.setOrigin(centerRay.getOrigin() + 20*centerRay.getDirection()); btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); @@ -71,11 +69,8 @@ namespace MWWorld Ray centerRay = mRender.getCamera()->getCameraToViewportRay( mRender.getViewport()->getWidth()/2, mRender.getViewport()->getHeight()/2); - //let's avoid the capsule shape of the player. - centerRay.setOrigin(centerRay.getOrigin() + 20*centerRay.getDirection()); - btVector3 from(centerRay.getOrigin().x,-centerRay.getOrigin().z,centerRay.getOrigin().y); - btVector3 to(centerRay.getPoint(500).x,-centerRay.getPoint(500).z,centerRay.getPoint(500).y); - return from * (1-extent) + to * extent; + btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); + return result; } bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to) diff --git a/apps/openmw/mwworld/world.cpp b/apps/openmw/mwworld/world.cpp index 567ed8f90b..dd30447338 100644 --- a/apps/openmw/mwworld/world.cpp +++ b/apps/openmw/mwworld/world.cpp @@ -749,6 +749,17 @@ 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) + { + if ( (*it).second == mPlayer->getPlayer().getRefData().getHandle() ) + { + results.erase(it); + break; + } + } + if (results.size() == 0) { mNumFacing = 0; From 47c3e92db1b3264112657ea6f10178091fe0cf37 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 28 Mar 2012 21:42:41 +0200 Subject: [PATCH 14/40] removed the unused ray scene query --- apps/openmw/mwrender/renderingmanager.cpp | 3 --- apps/openmw/mwrender/renderingmanager.hpp | 1 - 2 files changed, 4 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 2dc35d8c84..00b43cf9fe 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -46,9 +46,6 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const mMwRoot->pitch(Degree(-90)); mObjects.setMwRoot(mMwRoot); mActors.setMwRoot(mMwRoot); - - //used to obtain ingame information of ogre objects (which are faced or selected) - mRaySceneQuery = mRendering.getScene()->createRayQuery(Ray()); Ogre::SceneNode *playerNode = mMwRoot->createChildSceneNode ("player"); playerNode->pitch(Degree(90)); diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 569447bca3..edbc9aff27 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -158,7 +158,6 @@ class RenderingManager: private RenderingInterface { /// that the OGRE coordinate system matches that used internally in /// Morrowind. Ogre::SceneNode *mMwRoot; - Ogre::RaySceneQuery *mRaySceneQuery; OEngine::Physic::PhysicEngine* mPhysicsEngine; From e5a19209a4a8580dba93ca9560617e7dccf2306b Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 29 Mar 2012 00:05:48 +0200 Subject: [PATCH 15/40] remove the timeout stuff --- apps/openmw/mwrender/occlusionquery.cpp | 13 ++----------- apps/openmw/mwrender/occlusionquery.hpp | 4 ---- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 2c184c3451..228d8a4990 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -12,7 +12,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), mResponding(true), mDelay(0), mWasVisible(false), mObjectWasVisible(false) + mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false) { mRendering = renderer; mSunNode = sunNode; @@ -94,7 +94,7 @@ OcclusionQuery::~OcclusionQuery() bool OcclusionQuery::supported() { //if (!mResponding) std::cout << "Occlusion query timed out" << std::endl; - return mSupported && mResponding; + return mSupported; } void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass, const AutoParamDataSource* source, @@ -167,9 +167,6 @@ void OcclusionQuery::update(float duration) { if (!mSupported) return; - mDelay += duration; - if (mDelay >= 2) mResponding = false; - mWasVisible = false; mObjectWasVisible = false; @@ -189,9 +186,6 @@ void OcclusionQuery::update(float duration) if (!mSunTotalAreaQuery->isStillOutstanding() && !mSunVisibleAreaQuery->isStillOutstanding()) { - mDelay = 0; - mResponding = true; - unsigned int totalPixels; unsigned int visiblePixels; @@ -213,9 +207,6 @@ void OcclusionQuery::update(float duration) } if (mQuerySingleObjectStarted && !mSingleObjectQuery->isStillOutstanding()) { - mDelay = 0; - mResponding = true; - unsigned int result; mSingleObjectQuery->pullOcclusionQuery(&result); diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index b3e5442cfe..e81358eb6c 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -72,10 +72,6 @@ namespace MWRender bool mWasVisible; bool mObjectWasVisible; - bool mResponding; - - float mDelay; - bool mTestResult; bool mSupported; From fbd626baf69da248f64e0545d635799469a7a09e Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Fri, 30 Mar 2012 20:59:44 +0200 Subject: [PATCH 16/40] mwiniimporter --- CMakeLists.txt | 7 +++++- apps/mwiniimporter/CMakeLists.txt | 21 +++++++++++++++++ apps/mwiniimporter/importer.cpp | 6 +++++ apps/mwiniimporter/importer.hpp | 17 ++++++++++++++ apps/mwiniimporter/main.cpp | 39 +++++++++++++++++++++++++++++++ apps/mwiniimporter/main.hpp | 11 +++++++++ 6 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 apps/mwiniimporter/CMakeLists.txt create mode 100644 apps/mwiniimporter/importer.cpp create mode 100644 apps/mwiniimporter/importer.hpp create mode 100644 apps/mwiniimporter/main.cpp create mode 100644 apps/mwiniimporter/main.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f007dbccf..552a6997a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -305,7 +305,7 @@ if(DPKG_PROGRAM) Data files from the original game is required to run it.") SET(CPACK_DEBIAN_PACKAGE_NAME "openmw") SET(CPACK_DEBIAN_PACKAGE_VERSION "${VERSION_STRING}") - SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher") + SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW esmtool;Esmtool omwlauncher;OMWLauncher mwiniimporter;MWiniImporter") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "nvidia-cg-toolkit (>= 2.1), libboost-filesystem1.46.1 (>= 1.46.1), libboost-program-options1.46.1 (>= 1.46.1), libboost-system1.46.1 (>= 1.46.1), libboost-thread1.46.1 (>= 1.46.1), libc6 (>= 2.11.2), libfreetype6 (>= 2.2.1), libgcc1 (>= 1:4.1.1), libmpg123-0 (>= 1.12.1), libois-1.3.0 (>= 1.3.0), libopenal1 (>= 1:1.12.854), libsndfile1 (>= 1.0.23), libstdc++6 (>= 4.4.5), libuuid1 (>= 2.17.2), libqtgui4 (>= 4.7.0)") SET(CPACK_DEBIAN_PACKAGE_SECTION "Games") @@ -391,6 +391,11 @@ if (BUILD_LAUNCHER) add_subdirectory( apps/launcher ) endif() +option(BUILD_MWINIIMPORTER "build MWiniImporter inspector" ON) +if (BUILD_MWINIIMPORTER) + add_subdirectory( apps/mwiniimporter ) +endif() + if (WIN32) if (MSVC) if (USE_DEBUG_CONSOLE) diff --git a/apps/mwiniimporter/CMakeLists.txt b/apps/mwiniimporter/CMakeLists.txt new file mode 100644 index 0000000000..1d7b7b624c --- /dev/null +++ b/apps/mwiniimporter/CMakeLists.txt @@ -0,0 +1,21 @@ +set(MWINIIMPORT + main.cpp + importer.cpp +) + +set(MWINIIMPORT_HEADER + main.hpp + importer.hpp +) + +source_group(launcher FILES ${MWINIIMPORT} ${MWINIIMPORT_HEADER}) + +add_executable(mwiniimport + ${MWINIIMPORT} +) + +target_link_libraries(mwiniimport + ${Boost_LIBRARIES} + components +) + diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp new file mode 100644 index 0000000000..225b1667c4 --- /dev/null +++ b/apps/mwiniimporter/importer.cpp @@ -0,0 +1,6 @@ +#include "importer.hpp" + +void MwIniImporter::test() { + +} + diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp new file mode 100644 index 0000000000..026ed55bf9 --- /dev/null +++ b/apps/mwiniimporter/importer.hpp @@ -0,0 +1,17 @@ +#ifndef MWINIIMPORTER_IMPORTER +#define MWINIIMPORTER_IMPORTER 1 + +#include + +class MwIniImporter { + + public: + void test(); + + private: + + +}; + + +#endif diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp new file mode 100644 index 0000000000..46cb37e7f4 --- /dev/null +++ b/apps/mwiniimporter/main.cpp @@ -0,0 +1,39 @@ +#include "main.hpp" +#include "importer.hpp" + +int main(int argc, char *argv[]) { + + bpo::options_description desc("Syntax: mwiniimporter \nAllowed options"); + desc.add_options() + ("help,h", "produce help message") + ("in,i", bpo::value()->required(), "morrowind.ini input file") + ("out,o", bpo::value()->required(), "openmw.cfg output file") + ; + + bpo::variables_map vm; + try { + bpo::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + bpo::notify(vm); + + } + catch(std::exception& e) { + std::cout << "Error:" << e.what() << std::endl; + return -1; + } + catch(...) { + std::cout << "Error" << std::endl; + return -1; + } + + if(vm.count("help")) { + std::cout << desc; + return 0; + } + + std::cout << "in:" << vm["in"].as() << std::endl; + + MwIniImporter importer; + importer.test(); + + return 0; +} diff --git a/apps/mwiniimporter/main.hpp b/apps/mwiniimporter/main.hpp new file mode 100644 index 0000000000..f93de7b078 --- /dev/null +++ b/apps/mwiniimporter/main.hpp @@ -0,0 +1,11 @@ +#ifndef MWINIIMPORTER_MAIN +#define MWINIIMPORTER_MAIN 1 + +#include +#include +#include + +namespace bpo = boost::program_options; + + +#endif From c160bc708091039cccdea53bc584704713193852 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Fri, 30 Mar 2012 22:58:54 +0200 Subject: [PATCH 17/40] works, sort of --- apps/mwiniimporter/CMakeLists.txt | 1 - apps/mwiniimporter/importer.cpp | 94 ++++++++++++++++++++++++++++++- apps/mwiniimporter/importer.hpp | 18 +++++- apps/mwiniimporter/main.cpp | 58 +++++++++++++++---- apps/mwiniimporter/main.hpp | 11 ---- 5 files changed, 155 insertions(+), 27 deletions(-) delete mode 100644 apps/mwiniimporter/main.hpp diff --git a/apps/mwiniimporter/CMakeLists.txt b/apps/mwiniimporter/CMakeLists.txt index 1d7b7b624c..2a8c0f5fea 100644 --- a/apps/mwiniimporter/CMakeLists.txt +++ b/apps/mwiniimporter/CMakeLists.txt @@ -4,7 +4,6 @@ set(MWINIIMPORT ) set(MWINIIMPORT_HEADER - main.hpp importer.hpp ) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 225b1667c4..d0cfe4a04e 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -1,6 +1,96 @@ #include "importer.hpp" +#include +#include +#include -void MwIniImporter::test() { - +void MwIniImporter::setVerbose(bool verbose) { + mVerbose = verbose; } +strmap MwIniImporter::loadIniFile(std::string filename) { + std::cout << "load ini file: " << filename << std::endl; + + std::map map; + boost::iostreams::streamfile(filename.c_str()); + + std::string line; + while (std::getline(file, line)) { + + // ignore sections for now + if(line.empty() || line[0] == ';' || line[0] == '[') { + continue; + } + + int pos = line.find("="); + if(pos < 1) { + throw IniParseException(); + } + + map.insert(std::pair( + line.substr(0,pos), line.substr(pos+1) + )); + } + + return map; +} + +strmap MwIniImporter::loadCfgFile(std::string filename) { + std::cout << "load cfg file: " << filename << std::endl; + + std::map map; + boost::iostreams::streamfile(filename.c_str()); + + std::string line; + while (std::getline(file, line)) { + + if(line[0] == '[') { // section + continue; // ignore for now + } + + // we cant say comment by only looking at first char anymore + int comment_pos = line.find("#"); + if(comment_pos > 0) { + line = line.substr(0,comment_pos); + } + + if(line.empty()) { + continue; + } + + int pos = line.find("="); + if(pos < 1) { + throw IniParseException(); + } + + map.insert(std::pair( + line.substr(0,pos), line.substr(pos+1) + )); + } + + return map; +} + +void MwIniImporter::merge(strmap &cfg, strmap &ini) { + strmap::iterator ini_it; + for(strmap::iterator it=cfg.begin(); it != cfg.end(); it++) { + ini_it = ini.find(it->first); + + // found a key in both files + if(ini_it != ini.end()) { + cfg.erase(it); + cfg.insert(std::pair( + ini_it->first, ini_it->second + )); + } + } +} + +void MwIniImporter::writeToFile(std::string file, strmap &cfg) { + boost::iostreams::stream out(file); + + for(strmap::iterator it=cfg.begin(); it != cfg.end(); it++) { + out << (it->first) << "=" << (it->second) << std::endl; + } +} + + diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index 026ed55bf9..1933830f21 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -2,14 +2,28 @@ #define MWINIIMPORTER_IMPORTER 1 #include +#include +#include + +typedef std::map strmap; + +class IniParseException : public std::exception { + virtual const char* what() const throw() { + return "unexpected end of line"; + } +}; class MwIniImporter { public: - void test(); + void setVerbose(bool verbose); + strmap loadIniFile(std::string filename); + strmap loadCfgFile(std::string filename); + void merge(strmap &cfg, strmap &ini); + void writeToFile(std::string file, strmap &cfg); private: - + bool mVerbose; }; diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 46cb37e7f4..fa7a5c512f 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -1,39 +1,75 @@ -#include "main.hpp" #include "importer.hpp" +#include +#include +#include +#include + +namespace bpo = boost::program_options; + int main(int argc, char *argv[]) { bpo::options_description desc("Syntax: mwiniimporter \nAllowed options"); desc.add_options() ("help,h", "produce help message") - ("in,i", bpo::value()->required(), "morrowind.ini input file") - ("out,o", bpo::value()->required(), "openmw.cfg output file") + ("verbose,v", "verbose output") + ("ini,i", bpo::value()->required(), "morrowind.ini file") + ("cfg,c", bpo::value()->required(), "openmw.cfg file") + ("output,o", bpo::value()->default_value(""), "openmw.cfg file") ; bpo::variables_map vm; try { bpo::store(boost::program_options::parse_command_line(argc, argv, desc), vm); + + // parse help before calling notify because we dont want it to throw an error if help is set + if(vm.count("help")) { + std::cout << desc; + return 0; + } + bpo::notify(vm); } catch(std::exception& e) { - std::cout << "Error:" << e.what() << std::endl; + std::cerr << "Error:" << e.what() << std::endl; return -1; } catch(...) { - std::cout << "Error" << std::endl; - return -1; + std::cerr << "Error" << std::endl; + return -2; } - if(vm.count("help")) { - std::cout << desc; - return 0; + std::string iniFile = vm["ini"].as(); + std::string cfgFile = vm["cfg"].as(); + + // if no output is given, write back to cfg file + std::string outputFile(vm["output"].as()); + if(vm["output"].defaulted()) { + outputFile = vm["cfg"].as(); } - std::cout << "in:" << vm["in"].as() << std::endl; + if(!boost::filesystem::exists(iniFile)) { + std::cerr << "ini file does not exist" << std::endl; + return -3; + } + if(!boost::filesystem::exists(cfgFile)) { + std::cerr << "cfg file does not exist" << std::endl; + return -4; + } MwIniImporter importer; - importer.test(); + importer.setVerbose(vm.count("verbose")); + + std::mapini = importer.loadIniFile(iniFile); + std::mapcfg = importer.loadCfgFile(cfgFile); + + importer.merge(cfg, ini); + + std::cout << "write to: " << outputFile << std::endl; + importer.writeToFile(outputFile, cfg); return 0; } + + diff --git a/apps/mwiniimporter/main.hpp b/apps/mwiniimporter/main.hpp deleted file mode 100644 index f93de7b078..0000000000 --- a/apps/mwiniimporter/main.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef MWINIIMPORTER_MAIN -#define MWINIIMPORTER_MAIN 1 - -#include -#include -#include - -namespace bpo = boost::program_options; - - -#endif From 849c3a9bececfdeba8495f09dc057f62236027e8 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Fri, 30 Mar 2012 23:12:52 +0200 Subject: [PATCH 18/40] add the section to the ini-keys --- apps/mwiniimporter/importer.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index d0cfe4a04e..f662f42d64 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -10,6 +10,7 @@ void MwIniImporter::setVerbose(bool verbose) { strmap MwIniImporter::loadIniFile(std::string filename) { std::cout << "load ini file: " << filename << std::endl; + std::string section(""); std::map map; boost::iostreams::streamfile(filename.c_str()); @@ -17,17 +18,25 @@ strmap MwIniImporter::loadIniFile(std::string filename) { while (std::getline(file, line)) { // ignore sections for now - if(line.empty() || line[0] == ';' || line[0] == '[') { + if(line.empty() || line[0] == ';') { continue; } + if(line[0] == '[') { + if(line.length() > 2) { + section = line.substr(1, line.length()-3); + continue; + } + throw IniParseException(); + } + int pos = line.find("="); if(pos < 1) { throw IniParseException(); } map.insert(std::pair( - line.substr(0,pos), line.substr(pos+1) + section + " " + line.substr(0,pos), line.substr(pos+1) )); } From 6eb3281c4c504dfc2d6398156ee5c449772325c8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 31 Mar 2012 11:36:51 +0200 Subject: [PATCH 19/40] boost fix --- apps/mwiniimporter/main.cpp | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index fa7a5c512f..059703ea89 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -13,23 +13,23 @@ int main(int argc, char *argv[]) { desc.add_options() ("help,h", "produce help message") ("verbose,v", "verbose output") - ("ini,i", bpo::value()->required(), "morrowind.ini file") - ("cfg,c", bpo::value()->required(), "openmw.cfg file") + ("ini,i", bpo::value(), "morrowind.ini file") + ("cfg,c", bpo::value(), "openmw.cfg file") ("output,o", bpo::value()->default_value(""), "openmw.cfg file") ; - + bpo::variables_map vm; try { bpo::store(boost::program_options::parse_command_line(argc, argv, desc), vm); - + // parse help before calling notify because we dont want it to throw an error if help is set if(vm.count("help")) { std::cout << desc; return 0; } - + bpo::notify(vm); - + } catch(std::exception& e) { std::cerr << "Error:" << e.what() << std::endl; @@ -39,16 +39,16 @@ int main(int argc, char *argv[]) { std::cerr << "Error" << std::endl; return -2; } - + std::string iniFile = vm["ini"].as(); std::string cfgFile = vm["cfg"].as(); - + // if no output is given, write back to cfg file std::string outputFile(vm["output"].as()); if(vm["output"].defaulted()) { outputFile = vm["cfg"].as(); } - + if(!boost::filesystem::exists(iniFile)) { std::cerr << "ini file does not exist" << std::endl; return -3; @@ -57,19 +57,17 @@ int main(int argc, char *argv[]) { std::cerr << "cfg file does not exist" << std::endl; return -4; } - + MwIniImporter importer; importer.setVerbose(vm.count("verbose")); - + std::mapini = importer.loadIniFile(iniFile); std::mapcfg = importer.loadCfgFile(cfgFile); - + importer.merge(cfg, ini); - + std::cout << "write to: " << outputFile << std::endl; importer.writeToFile(outputFile, cfg); - + return 0; } - - From e35670c6cba25e055b6cda9dc2e3ad2ae005997d Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Sat, 31 Mar 2012 14:28:19 +0200 Subject: [PATCH 20/40] ignore syntax errors and empty lines; fixed merge function --- apps/mwiniimporter/importer.cpp | 37 +++++++++++++++------------------ apps/mwiniimporter/importer.hpp | 14 ++++++------- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index f662f42d64..9a76adeed8 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -25,19 +25,16 @@ strmap MwIniImporter::loadIniFile(std::string filename) { if(line[0] == '[') { if(line.length() > 2) { section = line.substr(1, line.length()-3); - continue; } - throw IniParseException(); + continue; } int pos = line.find("="); if(pos < 1) { - throw IniParseException(); + continue; } - map.insert(std::pair( - section + " " + line.substr(0,pos), line.substr(pos+1) - )); + map.insert(STRPAIR(section + ":" + line.substr(0,pos), line.substr(pos+1))); } return map; @@ -68,32 +65,32 @@ strmap MwIniImporter::loadCfgFile(std::string filename) { int pos = line.find("="); if(pos < 1) { - throw IniParseException(); + continue; } - map.insert(std::pair( - line.substr(0,pos), line.substr(pos+1) - )); + map.insert(STRPAIR(line.substr(0,pos), line.substr(pos+1))); } return map; } void MwIniImporter::merge(strmap &cfg, strmap &ini) { - strmap::iterator ini_it; - for(strmap::iterator it=cfg.begin(); it != cfg.end(); it++) { - ini_it = ini.find(it->first); - - // found a key in both files - if(ini_it != ini.end()) { - cfg.erase(it); - cfg.insert(std::pair( - ini_it->first, ini_it->second - )); + strmap::iterator cfgIt; + strmap::iterator iniIt; + for(strmap::iterator it=mMergeMap.begin(); it!=mMergeMap.end(); it++) { + if((iniIt = ini.find(it->second)) != ini.end()) { + cfg.erase(it->first); + if(!this->specialMerge(it->first, it->second, cfg, ini)) { + cfg.insert(STRPAIR(it->first, iniIt->second)); + } } } } +bool MwIniImporter::specialMerge(std::string cfgKey, std::string iniKey, strmap cfg, strmap ini) { + return false; +} + void MwIniImporter::writeToFile(std::string file, strmap &cfg) { boost::iostreams::stream out(file); diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index 1933830f21..3ab1d892ee 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -5,17 +5,16 @@ #include #include -typedef std::map strmap; -class IniParseException : public std::exception { - virtual const char* what() const throw() { - return "unexpected end of line"; - } -}; +typedef std::map strmap; +#define STRPAIR std::make_pair class MwIniImporter { public: + MwIniImporter() { + mMergeMap.insert(STRPAIR("fps", "General:Show FPS")); + }; void setVerbose(bool verbose); strmap loadIniFile(std::string filename); strmap loadCfgFile(std::string filename); @@ -23,8 +22,9 @@ class MwIniImporter { void writeToFile(std::string file, strmap &cfg); private: + bool specialMerge(std::string cfgKey, std::string iniKey, strmap cfg, strmap ini); bool mVerbose; - + strmap mMergeMap; }; From b7635b3d4a12bacf31a0c4d7aad92bfaacd2b711 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Sat, 31 Mar 2012 14:34:00 +0200 Subject: [PATCH 21/40] pass maps by reference --- apps/mwiniimporter/importer.cpp | 2 +- apps/mwiniimporter/importer.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 9a76adeed8..041712b216 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -87,7 +87,7 @@ void MwIniImporter::merge(strmap &cfg, strmap &ini) { } } -bool MwIniImporter::specialMerge(std::string cfgKey, std::string iniKey, strmap cfg, strmap ini) { +bool MwIniImporter::specialMerge(std::string cfgKey, std::string iniKey, strmap &cfg, strmap &ini) { return false; } diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index 3ab1d892ee..d0034a13d4 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -22,7 +22,7 @@ class MwIniImporter { void writeToFile(std::string file, strmap &cfg); private: - bool specialMerge(std::string cfgKey, std::string iniKey, strmap cfg, strmap ini); + bool specialMerge(std::string cfgKey, std::string iniKey, strmap &cfg, strmap &ini); bool mVerbose; strmap mMergeMap; }; From ceedae4a1af3c155f31221376ac9ef66c3e9dca8 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Sat, 31 Mar 2012 16:54:53 +0200 Subject: [PATCH 22/40] technical corrections --- apps/mwiniimporter/importer.cpp | 18 +++++++++++++++--- apps/mwiniimporter/importer.hpp | 5 +---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 041712b216..09088774b4 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -3,6 +3,18 @@ #include #include +MwIniImporter::MwIniImporter() { + const char *map[][2] = + { + { "fps", "General:Show FPS" }, + { 0, 0 } + }; + + for(int i=0; map[i][0]; i++) { + mMergeMap.insert(std::make_pair(map[i][0], map[i][1])); + } +} + void MwIniImporter::setVerbose(bool verbose) { mVerbose = verbose; } @@ -34,7 +46,7 @@ strmap MwIniImporter::loadIniFile(std::string filename) { continue; } - map.insert(STRPAIR(section + ":" + line.substr(0,pos), line.substr(pos+1))); + map.insert(std::make_pair(section + ":" + line.substr(0,pos), line.substr(pos+1))); } return map; @@ -68,7 +80,7 @@ strmap MwIniImporter::loadCfgFile(std::string filename) { continue; } - map.insert(STRPAIR(line.substr(0,pos), line.substr(pos+1))); + map.insert(std::make_pair(line.substr(0,pos), line.substr(pos+1))); } return map; @@ -81,7 +93,7 @@ void MwIniImporter::merge(strmap &cfg, strmap &ini) { if((iniIt = ini.find(it->second)) != ini.end()) { cfg.erase(it->first); if(!this->specialMerge(it->first, it->second, cfg, ini)) { - cfg.insert(STRPAIR(it->first, iniIt->second)); + cfg.insert(std::make_pair(it->first, iniIt->second)); } } } diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index d0034a13d4..ad5aaacde3 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -7,14 +7,11 @@ typedef std::map strmap; -#define STRPAIR std::make_pair class MwIniImporter { public: - MwIniImporter() { - mMergeMap.insert(STRPAIR("fps", "General:Show FPS")); - }; + MwIniImporter(); void setVerbose(bool verbose); strmap loadIniFile(std::string filename); strmap loadCfgFile(std::string filename); From 653fbdd10cf83a3d361b7017b6e491d6df7aa67a Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Sat, 31 Mar 2012 18:24:43 +0200 Subject: [PATCH 23/40] master/plugin support; needs multimap instead of map --- apps/mwiniimporter/importer.cpp | 58 +++++++++++++++++++++++++++++++++ apps/mwiniimporter/importer.hpp | 1 + apps/mwiniimporter/main.cpp | 5 +++ 3 files changed, 64 insertions(+) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 09088774b4..7532bf1dae 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -2,6 +2,9 @@ #include #include #include +#include +#include +#include MwIniImporter::MwIniImporter() { const char *map[][2] = @@ -99,6 +102,61 @@ void MwIniImporter::merge(strmap &cfg, strmap &ini) { } } +void MwIniImporter::importGameFiles(strmap &cfg, strmap &ini) { + std::vector esmFiles; + std::string baseEsm("Game Files:GameFile"); + std::string esmFile(""); + + strmap::iterator it = ini.begin(); + for(int i=0; it != ini.end(); i++) { + esmFile = baseEsm; + esmFile.append(1,i+'0'); + + it = ini.find(esmFile); + if(it == ini.end()) { + break; + } + + std::cout << "found EMS file: " << it->second << std::endl; + esmFiles.push_back(it->second); + esmFile = ""; + } + + + std::vector bsaFiles; + std::string baseBsa("Archives:Archive "); + std::string bsaFile(""); + + it = ini.begin(); + for(int i=0; it != ini.end(); i++) { + bsaFile = baseBsa; + bsaFile.append(1,i+'0'); + + it = ini.find(bsaFile); + if(it == ini.end()) { + break; + } + + std::cout << "found BSA file: " << it->second << std::endl; + bsaFiles.push_back(it->second); + bsaFile = ""; + } + + if(!esmFiles.empty()) { + cfg.erase("master"); + for(std::vector::iterator it = esmFiles.begin(); it != esmFiles.end(); it++) { + cfg.insert(std::make_pair("master", *it)); + } + } + + if(!bsaFile.empty()) { + cfg.erase("plugin"); + for(std::vector::iterator it = bsaFiles.begin(); it != bsaFiles.end(); it++) { + cfg.insert(std::make_pair("plugin", *it)); + } + } +} + bool MwIniImporter::specialMerge(std::string cfgKey, std::string iniKey, strmap &cfg, strmap &ini) { return false; } diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index ad5aaacde3..13cb02ee69 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -16,6 +16,7 @@ class MwIniImporter { strmap loadIniFile(std::string filename); strmap loadCfgFile(std::string filename); void merge(strmap &cfg, strmap &ini); + void importGameFiles(strmap &cfg, strmap &ini); void writeToFile(std::string file, strmap &cfg); private: diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 059703ea89..87225432d1 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -16,6 +16,7 @@ int main(int argc, char *argv[]) { ("ini,i", bpo::value(), "morrowind.ini file") ("cfg,c", bpo::value(), "openmw.cfg file") ("output,o", bpo::value()->default_value(""), "openmw.cfg file") + ("game-files,g", "import esm and esp files") ; bpo::variables_map vm; @@ -65,6 +66,10 @@ int main(int argc, char *argv[]) { std::mapcfg = importer.loadCfgFile(cfgFile); importer.merge(cfg, ini); + + if(vm.count("game-files")) { + importer.importGameFiles(cfg, ini); + } std::cout << "write to: " << outputFile << std::endl; importer.writeToFile(outputFile, cfg); From 092de45924ec2c263049e9fe46757892fb93c039 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Sat, 31 Mar 2012 18:28:48 +0200 Subject: [PATCH 24/40] std::map to std::multimap --- apps/mwiniimporter/importer.cpp | 4 ++-- apps/mwiniimporter/importer.hpp | 2 +- apps/mwiniimporter/main.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 7532bf1dae..a92eee725c 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -26,7 +26,7 @@ strmap MwIniImporter::loadIniFile(std::string filename) { std::cout << "load ini file: " << filename << std::endl; std::string section(""); - std::map map; + std::multimap map; boost::iostreams::streamfile(filename.c_str()); std::string line; @@ -58,7 +58,7 @@ strmap MwIniImporter::loadIniFile(std::string filename) { strmap MwIniImporter::loadCfgFile(std::string filename) { std::cout << "load cfg file: " << filename << std::endl; - std::map map; + std::multimap map; boost::iostreams::streamfile(filename.c_str()); std::string line; diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index 13cb02ee69..3c85fd25a2 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -6,7 +6,7 @@ #include -typedef std::map strmap; +typedef std::multimap strmap; class MwIniImporter { diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 87225432d1..5eba95961a 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -62,8 +62,8 @@ int main(int argc, char *argv[]) { MwIniImporter importer; importer.setVerbose(vm.count("verbose")); - std::mapini = importer.loadIniFile(iniFile); - std::mapcfg = importer.loadCfgFile(cfgFile); + std::multimapini = importer.loadIniFile(iniFile); + std::multimapcfg = importer.loadCfgFile(cfgFile); importer.merge(cfg, ini); From cbf6c0404a7f0177e5eea47da04c77beb0c8a7f3 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 31 Mar 2012 10:06:12 -0700 Subject: [PATCH 25/40] Implement a basic underwater sound environment --- apps/openmw/mwsound/openal_output.cpp | 60 +++++++++++++++++++++++---- apps/openmw/mwsound/openal_output.hpp | 6 ++- apps/openmw/mwsound/sound_output.hpp | 4 +- apps/openmw/mwsound/soundmanager.cpp | 11 ++++- apps/openmw/mwsound/soundmanager.hpp | 5 +++ 5 files changed, 72 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index ddf4df7057..6c7fff973a 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -260,7 +260,16 @@ bool OpenAL_SoundStream::isPlaying() void OpenAL_SoundStream::update() { - alSourcef(mSource, AL_GAIN, mVolume*mBaseVolume); + ALfloat gain = mVolume*mBaseVolume; + ALfloat pitch = 1.0f; + if(!(mFlags&Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(mSource, AL_GAIN, gain); + alSourcef(mSource, AL_PITCH, pitch); alSource3f(mSource, AL_POSITION, mPos[0], mPos[2], -mPos[1]); alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f); alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f); @@ -388,7 +397,16 @@ bool OpenAL_Sound::isPlaying() void OpenAL_Sound::update() { - alSourcef(mSource, AL_GAIN, mVolume*mBaseVolume); + ALfloat gain = mVolume*mBaseVolume; + ALfloat pitch = 1.0f; + if(!(mFlags&Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(mSource, AL_GAIN, gain); + alSourcef(mSource, AL_PITCH, pitch); alSource3f(mSource, AL_POSITION, mPos[0], mPos[2], -mPos[1]); alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f); alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f); @@ -397,10 +415,18 @@ void OpenAL_Sound::update() void OpenAL_Sound3D::update() { + ALfloat gain = mVolume*mBaseVolume; + ALfloat pitch = 1.0f; if(mPos.squaredDistance(mOutput.mPos) > mMaxDistance*mMaxDistance) - alSourcef(mSource, AL_GAIN, 0.0f); - else - alSourcef(mSource, AL_GAIN, mVolume*mBaseVolume); + gain = 0.0f; + else if(!(mFlags&Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) + { + gain *= 0.9f; + pitch *= 0.7f; + } + + alSourcef(mSource, AL_GAIN, gain); + alSourcef(mSource, AL_PITCH, pitch); alSource3f(mSource, AL_POSITION, mPos[0], mPos[2], -mPos[1]); alSource3f(mSource, AL_DIRECTION, 0.0f, 0.0f, 0.0f); alSource3f(mSource, AL_VELOCITY, 0.0f, 0.0f, 0.0f); @@ -638,6 +664,11 @@ SoundPtr OpenAL_Output::playSound(const std::string &fname, float volume, float alSourcef(src, AL_MAX_DISTANCE, 1000.0f); alSourcef(src, AL_ROLLOFF_FACTOR, 0.0f); + if(!(flags&Play_NoEnv) && mLastEnvironment == Env_Underwater) + { + volume *= 0.9f; + pitch *= 0.7f; + } alSourcef(src, AL_GAIN, volume); alSourcef(src, AL_PITCH, pitch); @@ -685,6 +716,11 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector alSourcef(src, AL_MAX_DISTANCE, max); alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f); + if(!(flags&Play_NoEnv) && mLastEnvironment == Env_Underwater) + { + volume *= 0.9f; + pitch *= 0.7f; + } alSourcef(src, AL_GAIN, (pos.squaredDistance(mPos) > max*max) ? 0.0f : volume); alSourcef(src, AL_PITCH, pitch); @@ -701,7 +737,7 @@ SoundPtr OpenAL_Output::playSound3D(const std::string &fname, const Ogre::Vector } -SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, float pitch) +SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, float pitch, int flags) { boost::shared_ptr sound; ALuint src; @@ -713,6 +749,8 @@ SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, floa try { + if((flags&Play_Loop)) + std::cout <<"Warning: cannot loop stream "<open(fname); sound.reset(new OpenAL_SoundStream(*this, src, decoder)); @@ -731,6 +769,11 @@ SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, floa alSourcef(src, AL_MAX_DISTANCE, 1000.0f); alSourcef(src, AL_ROLLOFF_FACTOR, 0.0f); + if(!(flags&Play_NoEnv) && mLastEnvironment == Env_Underwater) + { + volume *= 0.9f; + pitch *= 0.7f; + } alSourcef(src, AL_GAIN, volume); alSourcef(src, AL_PITCH, pitch); @@ -743,9 +786,10 @@ SoundPtr OpenAL_Output::streamSound(const std::string &fname, float volume, floa } -void OpenAL_Output::updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir) +void OpenAL_Output::updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env) { mPos = pos; + mLastEnvironment = env; if(mContext) { @@ -762,7 +806,7 @@ void OpenAL_Output::updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 OpenAL_Output::OpenAL_Output(SoundManager &mgr) : Sound_Output(mgr), mDevice(0), mContext(0), mBufferCacheMemSize(0), - mStreamThread(new StreamThread) + mLastEnvironment(Env_Normal), mStreamThread(new StreamThread) { } diff --git a/apps/openmw/mwsound/openal_output.hpp b/apps/openmw/mwsound/openal_output.hpp index a709576bae..d62d20286a 100644 --- a/apps/openmw/mwsound/openal_output.hpp +++ b/apps/openmw/mwsound/openal_output.hpp @@ -36,6 +36,8 @@ namespace MWSound ALuint getBuffer(const std::string &fname); void bufferFinished(ALuint buffer); + Environment mLastEnvironment; + virtual std::vector enumerate(); virtual void init(const std::string &devname=""); virtual void deinit(); @@ -43,9 +45,9 @@ namespace MWSound virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags); virtual SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos, float volume, float pitch, float min, float max, int flags); - virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch); + virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch, int flags); - virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir); + virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env); OpenAL_Output& operator=(const OpenAL_Output &rhs); OpenAL_Output(const OpenAL_Output &rhs); diff --git a/apps/openmw/mwsound/sound_output.hpp b/apps/openmw/mwsound/sound_output.hpp index 1507e18472..774e42efa3 100644 --- a/apps/openmw/mwsound/sound_output.hpp +++ b/apps/openmw/mwsound/sound_output.hpp @@ -27,9 +27,9 @@ namespace MWSound virtual SoundPtr playSound(const std::string &fname, float volume, float pitch, int flags) = 0; virtual SoundPtr playSound3D(const std::string &fname, const Ogre::Vector3 &pos, float volume, float pitch, float min, float max, int flags) = 0; - virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch) = 0; + virtual SoundPtr streamSound(const std::string &fname, float volume, float pitch, int flags) = 0; - virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir) = 0; + virtual void updateListener(const Ogre::Vector3 &pos, const Ogre::Vector3 &atdir, const Ogre::Vector3 &updir, Environment env) = 0; Sound_Output& operator=(const Sound_Output &rhs); Sound_Output(const Sound_Output &rhs); diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 2c2e6e9f91..aaeef80ff5 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -137,8 +137,9 @@ namespace MWSound { if(mMusic) mMusic->stop(); - mMusic = mOutput->streamSound(filename, 0.4f, 1.0f); + mMusic = mOutput->streamSound(filename, 0.4f, 1.0f, Play_NoEnv); mMusic->mBaseVolume = 0.4f; + mMusic->mFlags = Play_NoEnv; } catch(std::exception &e) { @@ -408,19 +409,25 @@ namespace MWSound if(!isMusicPlaying()) startRandomTitle(); + MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell(); Ogre::Camera *cam = mEnvironment.mWorld->getPlayer().getRenderer()->getCamera(); Ogre::Vector3 nPos, nDir, nUp; nPos = cam->getRealPosition(); nDir = cam->getRealDirection(); nUp = cam->getRealUp(); + Environment env = Env_Normal; + if(nPos.y < current->cell->water) + env = Env_Underwater; + // The output handler is expecting vectors oriented like the game // (that is, -Z goes down, +Y goes forward), but that's not what we // get from Ogre's camera, so we have to convert. const Ogre::Vector3 pos(nPos[0], -nPos[2], nPos[1]); const Ogre::Vector3 at(nDir[0], -nDir[2], nDir[1]); const Ogre::Vector3 up(nUp[0], -nUp[2], nUp[1]); - mOutput->updateListener(pos, at, up); + + mOutput->updateListener(pos, at, up, env); // Check if any sounds are finished playing, and trash them SoundMap::iterator snditer = mActiveSounds.begin(); diff --git a/apps/openmw/mwsound/soundmanager.hpp b/apps/openmw/mwsound/soundmanager.hpp index de5cca839c..cad5f61871 100644 --- a/apps/openmw/mwsound/soundmanager.hpp +++ b/apps/openmw/mwsound/soundmanager.hpp @@ -43,6 +43,11 @@ namespace MWSound static inline int operator&(const PlayMode &a, const PlayMode &b) { return (int)a & (int)b; } + enum Environment { + Env_Normal, + Env_Underwater, + }; + class SoundManager { Ogre::ResourceGroupManager& mResourceMgr; From f8d45eae52413bba78fea6715046ac7ac7eb2182 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 Mar 2012 19:08:05 +0200 Subject: [PATCH 26/40] fix #1 --- apps/openmw/mwrender/occlusionquery.cpp | 7 +++++-- apps/openmw/mwrender/occlusionquery.hpp | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 228d8a4990..b571e3c3ad 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -55,20 +55,21 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBNode = mSunNode->getParentSceneNode()->createChildSceneNode(); mObjectNode = mRendering->getScene()->getRootSceneNode()->createChildSceneNode(); + mBBNodeReal = mRendering->getScene()->getRootSceneNode()->createChildSceneNode(); mBBQueryTotal = mRendering->getScene()->createBillboardSet(1); mBBQueryTotal->setDefaultDimensions(150, 150); mBBQueryTotal->createBillboard(Vector3::ZERO); mBBQueryTotal->setMaterialName("QueryTotalPixels"); mBBQueryTotal->setRenderQueueGroup(queue); - mBBNode->attachObject(mBBQueryTotal); + mBBNodeReal->attachObject(mBBQueryTotal); mBBQueryVisible = mRendering->getScene()->createBillboardSet(1); mBBQueryVisible->setDefaultDimensions(150, 150); mBBQueryVisible->createBillboard(Vector3::ZERO); mBBQueryVisible->setMaterialName("QueryVisiblePixels"); mBBQueryVisible->setRenderQueueGroup(queue); - mBBNode->attachObject(mBBQueryVisible); + mBBNodeReal->attachObject(mBBQueryVisible); mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1); /// \todo ideally this should occupy exactly 1 pixel on the screen @@ -178,6 +179,8 @@ void OcclusionQuery::update(float duration) dist /= 1000.f; mBBNode->setPosition(mSunNode->getPosition() * dist); mBBNode->setScale(dist, dist, dist); + mBBNodeReal->setPosition(mBBNode->_getDerivedPosition()); + mBBNodeReal->setScale(mBBNode->getScale()); // Stop occlusion queries until we get their information // (may not happen on the same frame they are requested in) diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index e81358eb6c..102b18bee3 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -65,6 +65,7 @@ namespace MWRender Ogre::SceneNode* mSunNode; Ogre::SceneNode* mBBNode; + Ogre::SceneNode* mBBNodeReal; float mSunVisibility; Ogre::SceneNode* mObjectNode; From 909abb480d8479f7f70268f717556cb2f82b9102 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 Mar 2012 19:09:36 +0200 Subject: [PATCH 27/40] fix 2 --- apps/openmw/mwrender/occlusionquery.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index b571e3c3ad..9baea23b51 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -217,8 +217,6 @@ void OcclusionQuery::update(float duration) //std::cout << "Single object query result: " << result << " pixels " << std::endl; mTestResult = (result != 0); - mBBQuerySingleObject->setVisible(false); - mQuerySingleObjectStarted = false; mQuerySingleObjectRequested = false; } From c08a2b294224da72d32d409c7229aa999c1c4f82 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 Mar 2012 19:12:02 +0200 Subject: [PATCH 28/40] fix 3 --- apps/openmw/mwrender/occlusionquery.cpp | 10 +++++++--- apps/openmw/mwrender/occlusionquery.hpp | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 9baea23b51..de66df6d97 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -12,7 +12,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) + mQuerySingleObjectRequested(false), mWasVisible(false), mObjectWasVisible(false), mDoQuery2(false) { mRendering = renderer; mSunNode = sunNode; @@ -82,6 +82,7 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mRendering->getScene()->addRenderObjectListener(this); mRendering->getScene()->addRenderQueueListener(this); mDoQuery = true; + mDoQuery2 = true; } OcclusionQuery::~OcclusionQuery() @@ -125,7 +126,7 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass mActiveQuery = mSunVisibleAreaQuery; } } - if (rend == mBBQuerySingleObject && mQuerySingleObjectRequested) + if (mDoQuery2 == true && rend == mBBQuerySingleObject && mQuerySingleObjectRequested) { mQuerySingleObjectStarted = true; mQuerySingleObjectRequested = false; @@ -154,7 +155,7 @@ void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocati mSunVisibleAreaQuery->beginOcclusionQuery(); mSunVisibleAreaQuery->endOcclusionQuery(); } - if (mObjectWasVisible == false && mQuerySingleObjectRequested) + if (mObjectWasVisible == false && mDoQuery2 && mQuerySingleObjectRequested) { mSingleObjectQuery->beginOcclusionQuery(); mSingleObjectQuery->endOcclusionQuery(); @@ -185,6 +186,7 @@ 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()) @@ -219,6 +221,8 @@ void OcclusionQuery::update(float duration) mQuerySingleObjectStarted = false; mQuerySingleObjectRequested = false; + + mDoQuery2 = true; } } diff --git a/apps/openmw/mwrender/occlusionquery.hpp b/apps/openmw/mwrender/occlusionquery.hpp index 102b18bee3..ebdc51311d 100644 --- a/apps/openmw/mwrender/occlusionquery.hpp +++ b/apps/openmw/mwrender/occlusionquery.hpp @@ -77,6 +77,7 @@ namespace MWRender bool mSupported; bool mDoQuery; + bool mDoQuery2; bool mQuerySingleObjectRequested; bool mQuerySingleObjectStarted; From c9067249dd0a3e4eef6d5db37480bc74426721c8 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 Mar 2012 19:16:14 +0200 Subject: [PATCH 29/40] fix 4 --- apps/openmw/mwrender/occlusionquery.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index de66df6d97..2bcf6bd4b4 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -126,7 +126,7 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass mActiveQuery = mSunVisibleAreaQuery; } } - if (mDoQuery2 == true && rend == mBBQuerySingleObject && mQuerySingleObjectRequested) + if (mDoQuery2 == true && rend == mBBQuerySingleObject) { mQuerySingleObjectStarted = true; mQuerySingleObjectRequested = false; @@ -155,7 +155,7 @@ void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocati mSunVisibleAreaQuery->beginOcclusionQuery(); mSunVisibleAreaQuery->endOcclusionQuery(); } - if (mObjectWasVisible == false && mDoQuery2 && mQuerySingleObjectRequested) + if (mObjectWasVisible == false && mDoQuery2) { mSingleObjectQuery->beginOcclusionQuery(); mSingleObjectQuery->endOcclusionQuery(); @@ -210,13 +210,13 @@ void OcclusionQuery::update(float duration) mDoQuery = true; } - if (mQuerySingleObjectStarted && !mSingleObjectQuery->isStillOutstanding()) + if (!mSingleObjectQuery->isStillOutstanding()) { unsigned int result; mSingleObjectQuery->pullOcclusionQuery(&result); - //std::cout << "Single object query result: " << result << " pixels " << std::endl; + std::cout << "Single object query result: " << result << " pixels " << std::endl; mTestResult = (result != 0); mQuerySingleObjectStarted = false; From 4944a29b21b515f33686ab54dc0ecfd71e8b6cbd Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 31 Mar 2012 10:41:12 -0700 Subject: [PATCH 30/40] Keep track of the sound pitch --- apps/openmw/mwsound/openal_output.cpp | 6 +++--- apps/openmw/mwsound/sound.hpp | 2 ++ apps/openmw/mwsound/soundmanager.cpp | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwsound/openal_output.cpp b/apps/openmw/mwsound/openal_output.cpp index 6c7fff973a..41411a6216 100644 --- a/apps/openmw/mwsound/openal_output.cpp +++ b/apps/openmw/mwsound/openal_output.cpp @@ -261,7 +261,7 @@ bool OpenAL_SoundStream::isPlaying() void OpenAL_SoundStream::update() { ALfloat gain = mVolume*mBaseVolume; - ALfloat pitch = 1.0f; + ALfloat pitch = mPitch; if(!(mFlags&Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) { gain *= 0.9f; @@ -398,7 +398,7 @@ bool OpenAL_Sound::isPlaying() void OpenAL_Sound::update() { ALfloat gain = mVolume*mBaseVolume; - ALfloat pitch = 1.0f; + ALfloat pitch = mPitch; if(!(mFlags&Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) { gain *= 0.9f; @@ -416,7 +416,7 @@ void OpenAL_Sound::update() void OpenAL_Sound3D::update() { ALfloat gain = mVolume*mBaseVolume; - ALfloat pitch = 1.0f; + ALfloat pitch = mPitch; if(mPos.squaredDistance(mOutput.mPos) > mMaxDistance*mMaxDistance) gain = 0.0f; else if(!(mFlags&Play_NoEnv) && mOutput.mLastEnvironment == Env_Underwater) diff --git a/apps/openmw/mwsound/sound.hpp b/apps/openmw/mwsound/sound.hpp index ca12ec5571..a33892548c 100644 --- a/apps/openmw/mwsound/sound.hpp +++ b/apps/openmw/mwsound/sound.hpp @@ -16,6 +16,7 @@ namespace MWSound Ogre::Vector3 mPos; float mVolume; /* NOTE: Real volume = mVolume*mBaseVolume */ float mBaseVolume; + float mPitch; float mMinDistance; float mMaxDistance; int mFlags; @@ -29,6 +30,7 @@ namespace MWSound Sound() : mPos(0.0f, 0.0f, 0.0f) , mVolume(1.0f) , mBaseVolume(1.0f) + , mPitch(1.0f) , mMinDistance(20.0f) /* 1 * min_range_scale */ , mMaxDistance(12750.0f) /* 255 * max_range_scale */ , mFlags(Play_Normal) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index aaeef80ff5..a00b7dc661 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -216,6 +216,7 @@ namespace MWSound sound = mOutput->playSound(file, volume*basevol, pitch, mode); sound->mVolume = volume; sound->mBaseVolume = basevol; + sound->mPitch = pitch; sound->mMinDistance = min; sound->mMaxDistance = max; sound->mFlags = mode; @@ -246,6 +247,7 @@ namespace MWSound sound->mPos = objpos; sound->mVolume = volume; sound->mBaseVolume = basevol; + sound->mPitch = pitch; sound->mMinDistance = min; sound->mMaxDistance = max; sound->mFlags = mode; From 3a57746ee47f8504f6c531fd43166316ba973fd9 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 31 Mar 2012 10:43:55 -0700 Subject: [PATCH 31/40] Remove an unneeded volume special-case --- apps/openmw/mwsound/soundmanager.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index a00b7dc661..1aa2bf2bf7 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -88,10 +88,7 @@ namespace MWSound if(snd == NULL) throw std::runtime_error(std::string("Failed to lookup sound ")+soundId); - if(snd->data.volume == 0) - volume = 0.0f; - else - volume *= pow(10.0, (snd->data.volume/255.0f*3348.0 - 3348.0) / 2000.0); + volume *= pow(10.0, (snd->data.volume/255.0*3348.0 - 3348.0) / 2000.0); if(snd->data.minRange == 0 && snd->data.maxRange == 0) { From e8e8d3fb1b4ef1fb917e04278fd6493c310d34ca Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 31 Mar 2012 10:59:29 -0700 Subject: [PATCH 32/40] Fully reset the music before starting the next track --- apps/openmw/mwsound/soundmanager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/openmw/mwsound/soundmanager.cpp b/apps/openmw/mwsound/soundmanager.cpp index 1aa2bf2bf7..a96aac6c5c 100644 --- a/apps/openmw/mwsound/soundmanager.cpp +++ b/apps/openmw/mwsound/soundmanager.cpp @@ -132,8 +132,7 @@ namespace MWSound std::cout <<"Playing "<stop(); + stopMusic(); mMusic = mOutput->streamSound(filename, 0.4f, 1.0f, Play_NoEnv); mMusic->mBaseVolume = 0.4f; mMusic->mFlags = Play_NoEnv; From b018d00fd3feff313ec9c099ea5c73be89f24e5d Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 Mar 2012 20:05:23 +0200 Subject: [PATCH 33/40] fix 5 --- apps/openmw/mwrender/occlusionquery.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index 2bcf6bd4b4..f4eb08acdc 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -126,7 +126,7 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass mActiveQuery = mSunVisibleAreaQuery; } } - if (mDoQuery2 == true && rend == mBBQuerySingleObject) + if (mDoQuery == true && rend == mBBQuerySingleObject) { mQuerySingleObjectStarted = true; mQuerySingleObjectRequested = false; @@ -155,7 +155,7 @@ void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocati mSunVisibleAreaQuery->beginOcclusionQuery(); mSunVisibleAreaQuery->endOcclusionQuery(); } - if (mObjectWasVisible == false && mDoQuery2) + if (mObjectWasVisible == false && mDoQuery) { mSingleObjectQuery->beginOcclusionQuery(); mSingleObjectQuery->endOcclusionQuery(); @@ -189,7 +189,8 @@ void OcclusionQuery::update(float duration) mDoQuery2 = false; if (!mSunTotalAreaQuery->isStillOutstanding() - && !mSunVisibleAreaQuery->isStillOutstanding()) + && !mSunVisibleAreaQuery->isStillOutstanding() + && !mSingleObjectQuery->isStillOutstanding()) { unsigned int totalPixels; unsigned int visiblePixels; @@ -208,10 +209,6 @@ void OcclusionQuery::update(float duration) if (mSunVisibility > 1) mSunVisibility = 1; } - mDoQuery = true; - } - if (!mSingleObjectQuery->isStillOutstanding()) - { unsigned int result; mSingleObjectQuery->pullOcclusionQuery(&result); @@ -222,7 +219,7 @@ void OcclusionQuery::update(float duration) mQuerySingleObjectStarted = false; mQuerySingleObjectRequested = false; - mDoQuery2 = true; + mDoQuery = true; } } From 5f78f6c72325de90c7efbc55fc191dc3c27dee44 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 Mar 2012 20:10:34 +0200 Subject: [PATCH 34/40] change queue --- apps/openmw/mwrender/occlusionquery.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index f4eb08acdc..ade0f976e0 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -61,14 +61,14 @@ OcclusionQuery::OcclusionQuery(OEngine::Render::OgreRenderer* renderer, SceneNod mBBQueryTotal->setDefaultDimensions(150, 150); mBBQueryTotal->createBillboard(Vector3::ZERO); mBBQueryTotal->setMaterialName("QueryTotalPixels"); - mBBQueryTotal->setRenderQueueGroup(queue); + mBBQueryTotal->setRenderQueueGroup(queue+1); mBBNodeReal->attachObject(mBBQueryTotal); mBBQueryVisible = mRendering->getScene()->createBillboardSet(1); mBBQueryVisible->setDefaultDimensions(150, 150); mBBQueryVisible->createBillboard(Vector3::ZERO); mBBQueryVisible->setMaterialName("QueryVisiblePixels"); - mBBQueryVisible->setRenderQueueGroup(queue); + mBBQueryVisible->setRenderQueueGroup(queue+1); mBBNodeReal->attachObject(mBBQueryVisible); mBBQuerySingleObject = mRendering->getScene()->createBillboardSet(1); From cfb194f1d13c1836022b0845d7ffdc5d896a768b Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 Mar 2012 20:18:20 +0200 Subject: [PATCH 35/40] fix 6 --- apps/openmw/mwrender/occlusionquery.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index ade0f976e0..bfa3b73aef 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -140,6 +140,11 @@ void OcclusionQuery::notifyRenderSingleObject(Renderable* rend, const Pass* pass void OcclusionQuery::renderQueueEnded(uint8 queueGroupId, const String& invocation, bool& repeatThisInvocation) { + if (mActiveQuery != NULL) + { + mActiveQuery->endOcclusionQuery(); + mActiveQuery = NULL; + } /** * for every beginOcclusionQuery(), we want a respective pullOcclusionQuery() and vice versa * this also means that results can be wrong at other places if we pull, but beginOcclusionQuery() was never called From 13efe68fc3a628abaa8ca65181390030983c4e22 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sat, 31 Mar 2012 20:28:07 +0200 Subject: [PATCH 36/40] disabled some debug output --- apps/openmw/mwrender/occlusionquery.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/openmw/mwrender/occlusionquery.cpp b/apps/openmw/mwrender/occlusionquery.cpp index bfa3b73aef..cc3464c646 100644 --- a/apps/openmw/mwrender/occlusionquery.cpp +++ b/apps/openmw/mwrender/occlusionquery.cpp @@ -95,7 +95,6 @@ OcclusionQuery::~OcclusionQuery() bool OcclusionQuery::supported() { - //if (!mResponding) std::cout << "Occlusion query timed out" << std::endl; return mSupported; } @@ -218,7 +217,6 @@ void OcclusionQuery::update(float duration) mSingleObjectQuery->pullOcclusionQuery(&result); - std::cout << "Single object query result: " << result << " pixels " << std::endl; mTestResult = (result != 0); mQuerySingleObjectStarted = false; From 6d875dfd54105505c62f831717632e6c9eeaad12 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Sat, 31 Mar 2012 21:06:48 +0200 Subject: [PATCH 37/40] handle master/plugin properly --- apps/mwiniimporter/importer.cpp | 120 ++++++++++++++------------------ apps/mwiniimporter/importer.hpp | 10 ++- apps/mwiniimporter/main.cpp | 14 ++-- 3 files changed, 69 insertions(+), 75 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index a92eee725c..937073632d 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -5,6 +5,7 @@ #include #include #include +#include MwIniImporter::MwIniImporter() { const char *map[][2] = @@ -26,17 +27,12 @@ strmap MwIniImporter::loadIniFile(std::string filename) { std::cout << "load ini file: " << filename << std::endl; std::string section(""); - std::multimap map; + std::map map; boost::iostreams::streamfile(filename.c_str()); std::string line; while (std::getline(file, line)) { - // ignore sections for now - if(line.empty() || line[0] == ';') { - continue; - } - if(line[0] == '[') { if(line.length() > 2) { section = line.substr(1, line.length()-3); @@ -44,6 +40,15 @@ strmap MwIniImporter::loadIniFile(std::string filename) { continue; } + int comment_pos = line.find(";"); + if(comment_pos > 0) { + line = line.substr(0,comment_pos); + } + + if(line.empty()) { + continue; + } + int pos = line.find("="); if(pos < 1) { continue; @@ -58,16 +63,12 @@ strmap MwIniImporter::loadIniFile(std::string filename) { strmap MwIniImporter::loadCfgFile(std::string filename) { std::cout << "load cfg file: " << filename << std::endl; - std::multimap map; + std::map map; boost::iostreams::streamfile(filename.c_str()); std::string line; while (std::getline(file, line)) { - if(line[0] == '[') { // section - continue; // ignore for now - } - // we cant say comment by only looking at first char anymore int comment_pos = line.find("#"); if(comment_pos > 0) { @@ -102,67 +103,50 @@ void MwIniImporter::merge(strmap &cfg, strmap &ini) { } } -void MwIniImporter::importGameFiles(strmap &cfg, strmap &ini) { - std::vector esmFiles; - std::string baseEsm("Game Files:GameFile"); - std::string esmFile(""); - - strmap::iterator it = ini.begin(); - for(int i=0; it != ini.end(); i++) { - esmFile = baseEsm; - esmFile.append(1,i+'0'); - - it = ini.find(esmFile); - if(it == ini.end()) { - break; - } - - std::cout << "found EMS file: " << it->second << std::endl; - esmFiles.push_back(it->second); - esmFile = ""; - } - - - std::vector bsaFiles; - std::string baseBsa("Archives:Archive "); - std::string bsaFile(""); - - it = ini.begin(); - for(int i=0; it != ini.end(); i++) { - bsaFile = baseBsa; - bsaFile.append(1,i+'0'); - - it = ini.find(bsaFile); - if(it == ini.end()) { - break; - } - - std::cout << "found BSA file: " << it->second << std::endl; - bsaFiles.push_back(it->second); - bsaFile = ""; - } - - if(!esmFiles.empty()) { - cfg.erase("master"); - for(std::vector::iterator it = esmFiles.begin(); it != esmFiles.end(); it++) { - cfg.insert(std::make_pair("master", *it)); - } - } - - if(!bsaFile.empty()) { - cfg.erase("plugin"); - for(std::vector::iterator it = bsaFiles.begin(); it != bsaFiles.end(); it++) { - cfg.insert(std::make_pair("plugin", *it)); - } - } -} - bool MwIniImporter::specialMerge(std::string cfgKey, std::string iniKey, strmap &cfg, strmap &ini) { return false; } -void MwIniImporter::writeToFile(std::string file, strmap &cfg) { - boost::iostreams::stream out(file); +void MwIniImporter::importGameFiles(strmap &cfg, strmap &ini, std::vector &esmFiles, std::vector &espFiles) { + std::string baseGameFile("Game Files:GameFile"); + std::string gameFile(""); + + strmap::iterator it = ini.begin(); + for(int i=0; it != ini.end(); i++) { + gameFile = baseGameFile; + gameFile.append(1,i+'0'); + + it = ini.find(gameFile); + if(it == ini.end()) { + break; + } + + std::string filetype(it->second.substr(it->second.length()-4, 3)); + std::transform(filetype.begin(), filetype.end(), filetype.begin(), ::tolower); + + if(filetype.compare("esm") == 0) { + esmFiles.push_back(it->second); + } + else if(filetype.compare("esp") == 0) { + espFiles.push_back(it->second); + } + + gameFile = ""; + } +} + +void MwIniImporter::writeGameFiles(boost::iostreams::stream &out, std::vector &esmFiles, std::vector &espFiles) { + for(std::vector::iterator it=esmFiles.begin(); it != esmFiles.end(); it++) { + out << "master=" << *it << std::endl; + } + for(std::vector::iterator it=espFiles.begin(); it != espFiles.end(); it++) { + out << "plugin=" << *it << std::endl; + } +} + +void MwIniImporter::writeToFile(boost::iostreams::stream &out, strmap &cfg) { + cfg.erase("master"); + cfg.erase("plugin"); for(strmap::iterator it=cfg.begin(); it != cfg.end(); it++) { out << (it->first) << "=" << (it->second) << std::endl; diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index 3c85fd25a2..d7250f5e25 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -1,12 +1,15 @@ #ifndef MWINIIMPORTER_IMPORTER #define MWINIIMPORTER_IMPORTER 1 +#include +#include #include #include +#include #include -typedef std::multimap strmap; +typedef std::map strmap; class MwIniImporter { @@ -16,8 +19,9 @@ class MwIniImporter { strmap loadIniFile(std::string filename); strmap loadCfgFile(std::string filename); void merge(strmap &cfg, strmap &ini); - void importGameFiles(strmap &cfg, strmap &ini); - void writeToFile(std::string file, strmap &cfg); + void importGameFiles(strmap &cfg, strmap &ini, std::vector &esmFiles, std::vector &espFiles); + void writeGameFiles(boost::iostreams::stream &out, std::vector &esmFiles, std::vector &espFiles); + void writeToFile(boost::iostreams::stream &out, strmap &cfg); private: bool specialMerge(std::string cfgKey, std::string iniKey, strmap &cfg, strmap &ini); diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 5eba95961a..7426e71ea0 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -58,21 +58,27 @@ int main(int argc, char *argv[]) { std::cerr << "cfg file does not exist" << std::endl; return -4; } + MwIniImporter importer; importer.setVerbose(vm.count("verbose")); + boost::iostreams::stream file(outputFile); - std::multimapini = importer.loadIniFile(iniFile); - std::multimapcfg = importer.loadCfgFile(cfgFile); + std::mapini = importer.loadIniFile(iniFile); + std::mapcfg = importer.loadCfgFile(cfgFile); importer.merge(cfg, ini); if(vm.count("game-files")) { - importer.importGameFiles(cfg, ini); + std::vector esmFiles; + std::vector espFiles; + + importer.importGameFiles(cfg, ini, esmFiles, espFiles); + importer.writeGameFiles(file, esmFiles, espFiles); } std::cout << "write to: " << outputFile << std::endl; - importer.writeToFile(outputFile, cfg); + importer.writeToFile(file, cfg); return 0; } From 1d596d6c722ac579e527b785ff6b393d8375f3b6 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Sat, 31 Mar 2012 22:48:50 +0200 Subject: [PATCH 38/40] use std::map > instead of std::map --- apps/mwiniimporter/importer.cpp | 103 ++++++++++++++++++++------------ apps/mwiniimporter/importer.hpp | 20 +++---- apps/mwiniimporter/main.cpp | 11 +--- 3 files changed, 78 insertions(+), 56 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index 937073632d..f7ddb2bf07 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -23,11 +23,11 @@ void MwIniImporter::setVerbose(bool verbose) { mVerbose = verbose; } -strmap MwIniImporter::loadIniFile(std::string filename) { +MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) { std::cout << "load ini file: " << filename << std::endl; std::string section(""); - std::map map; + MwIniImporter::multistrmap map; boost::iostreams::streamfile(filename.c_str()); std::string line; @@ -54,16 +54,23 @@ strmap MwIniImporter::loadIniFile(std::string filename) { continue; } - map.insert(std::make_pair(section + ":" + line.substr(0,pos), line.substr(pos+1))); + std::string key(section + ":" + line.substr(0,pos)); + std::string value(line.substr(pos+1)); + + multistrmap::iterator it; + if((it = map.find(key)) == map.end()) { + map.insert( std::make_pair > (key, std::vector() ) ); + } + map[key].push_back(value); } return map; } -strmap MwIniImporter::loadCfgFile(std::string filename) { +MwIniImporter::multistrmap MwIniImporter::loadCfgFile(std::string filename) { std::cout << "load cfg file: " << filename << std::endl; - std::map map; + MwIniImporter::multistrmap map; boost::iostreams::streamfile(filename.c_str()); std::string line; @@ -84,34 +91,43 @@ strmap MwIniImporter::loadCfgFile(std::string filename) { continue; } - map.insert(std::make_pair(line.substr(0,pos), line.substr(pos+1))); + std::string key(line.substr(0,pos)); + std::string value(line.substr(pos+1)); + + multistrmap::iterator it; + if((it = map.find(key)) == map.end()) { + map.insert( std::make_pair > (key, std::vector() ) ); + } + map[key].push_back(value); } return map; } -void MwIniImporter::merge(strmap &cfg, strmap &ini) { - strmap::iterator cfgIt; - strmap::iterator iniIt; +void MwIniImporter::merge(multistrmap &cfg, multistrmap &ini) { + multistrmap::iterator cfgIt; + multistrmap::iterator iniIt; for(strmap::iterator it=mMergeMap.begin(); it!=mMergeMap.end(); it++) { if((iniIt = ini.find(it->second)) != ini.end()) { cfg.erase(it->first); if(!this->specialMerge(it->first, it->second, cfg, ini)) { - cfg.insert(std::make_pair(it->first, iniIt->second)); + cfg.insert(std::make_pair >(it->first, iniIt->second)); } } } } -bool MwIniImporter::specialMerge(std::string cfgKey, std::string iniKey, strmap &cfg, strmap &ini) { +bool MwIniImporter::specialMerge(std::string cfgKey, std::string iniKey, multistrmap &cfg, multistrmap &ini) { return false; } -void MwIniImporter::importGameFiles(strmap &cfg, strmap &ini, std::vector &esmFiles, std::vector &espFiles) { +void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) { + std::vector esmFiles; + std::vector espFiles; std::string baseGameFile("Game Files:GameFile"); std::string gameFile(""); - strmap::iterator it = ini.begin(); + multistrmap::iterator it = ini.begin(); for(int i=0; it != ini.end(); i++) { gameFile = baseGameFile; gameFile.append(1,i+'0'); @@ -121,35 +137,48 @@ void MwIniImporter::importGameFiles(strmap &cfg, strmap &ini, std::vectorsecond.substr(it->second.length()-4, 3)); - std::transform(filetype.begin(), filetype.end(), filetype.begin(), ::tolower); - - if(filetype.compare("esm") == 0) { - esmFiles.push_back(it->second); - } - else if(filetype.compare("esp") == 0) { - espFiles.push_back(it->second); + for(std::vector::iterator entry = it->second.begin(); entry!=it->second.end(); entry++) { + std::string filetype(entry->substr(entry->length()-4, 3)); + std::transform(filetype.begin(), filetype.end(), filetype.begin(), ::tolower); + + if(filetype.compare("esm") == 0) { + esmFiles.push_back(*entry); + } + else if(filetype.compare("esp") == 0) { + espFiles.push_back(*entry); + } } gameFile = ""; } -} - -void MwIniImporter::writeGameFiles(boost::iostreams::stream &out, std::vector &esmFiles, std::vector &espFiles) { - for(std::vector::iterator it=esmFiles.begin(); it != esmFiles.end(); it++) { - out << "master=" << *it << std::endl; - } - for(std::vector::iterator it=espFiles.begin(); it != espFiles.end(); it++) { - out << "plugin=" << *it << std::endl; - } -} - -void MwIniImporter::writeToFile(boost::iostreams::stream &out, strmap &cfg) { - cfg.erase("master"); - cfg.erase("plugin"); - for(strmap::iterator it=cfg.begin(); it != cfg.end(); it++) { - out << (it->first) << "=" << (it->second) << std::endl; + if(!esmFiles.empty()) { + multistrmap::iterator it; + cfg.erase("master"); + cfg.insert( std::make_pair > ("master", std::vector() ) ); + + for(std::vector::iterator it=esmFiles.begin(); it!=esmFiles.end(); it++) { + cfg["master"].push_back(*it); + } + } + + if(!espFiles.empty()) { + multistrmap::iterator it; + cfg.erase("plugin"); + cfg.insert( std::make_pair > ("plugin", std::vector() ) ); + + for(std::vector::iterator it=espFiles.begin(); it!=espFiles.end(); it++) { + cfg["plugin"].push_back(*it); + } + } +} + +void MwIniImporter::writeToFile(boost::iostreams::stream &out, multistrmap &cfg) { + + for(multistrmap::iterator it=cfg.begin(); it != cfg.end(); it++) { + for(std::vector::iterator entry=it->second.begin(); entry != it->second.end(); entry++) { + out << (it->first) << "=" << (*entry) << std::endl; + } } } diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index d7250f5e25..454dc209af 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -8,23 +8,21 @@ #include #include - -typedef std::map strmap; - class MwIniImporter { - public: + typedef std::map strmap; + typedef std::map > multistrmap; + MwIniImporter(); void setVerbose(bool verbose); - strmap loadIniFile(std::string filename); - strmap loadCfgFile(std::string filename); - void merge(strmap &cfg, strmap &ini); - void importGameFiles(strmap &cfg, strmap &ini, std::vector &esmFiles, std::vector &espFiles); - void writeGameFiles(boost::iostreams::stream &out, std::vector &esmFiles, std::vector &espFiles); - void writeToFile(boost::iostreams::stream &out, strmap &cfg); + multistrmap loadIniFile(std::string filename); + multistrmap loadCfgFile(std::string filename); + void merge(multistrmap &cfg, multistrmap &ini); + void importGameFiles(multistrmap &cfg, multistrmap &ini); + void writeToFile(boost::iostreams::stream &out, multistrmap &cfg); private: - bool specialMerge(std::string cfgKey, std::string iniKey, strmap &cfg, strmap &ini); + bool specialMerge(std::string cfgKey, std::string iniKey, multistrmap &cfg, multistrmap &ini); bool mVerbose; strmap mMergeMap; }; diff --git a/apps/mwiniimporter/main.cpp b/apps/mwiniimporter/main.cpp index 7426e71ea0..9a6e61645d 100644 --- a/apps/mwiniimporter/main.cpp +++ b/apps/mwiniimporter/main.cpp @@ -59,22 +59,17 @@ int main(int argc, char *argv[]) { return -4; } - MwIniImporter importer; importer.setVerbose(vm.count("verbose")); boost::iostreams::stream file(outputFile); - std::mapini = importer.loadIniFile(iniFile); - std::mapcfg = importer.loadCfgFile(cfgFile); + MwIniImporter::multistrmap ini = importer.loadIniFile(iniFile); + MwIniImporter::multistrmap cfg = importer.loadCfgFile(cfgFile); importer.merge(cfg, ini); if(vm.count("game-files")) { - std::vector esmFiles; - std::vector espFiles; - - importer.importGameFiles(cfg, ini, esmFiles, espFiles); - importer.writeGameFiles(file, esmFiles, espFiles); + importer.importGameFiles(cfg, ini); } std::cout << "write to: " << outputFile << std::endl; From a2a7539fd55b2a4480c36575f0814d4180215146 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Sat, 31 Mar 2012 23:15:33 +0200 Subject: [PATCH 39/40] fix for more than 10 game files; delete both master and plugin settings if called with --game-files --- apps/mwiniimporter/importer.cpp | 36 +++++++++++++++++---------------- apps/mwiniimporter/importer.hpp | 1 + 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index f7ddb2bf07..a82240a8aa 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -6,6 +6,7 @@ #include #include #include +#include MwIniImporter::MwIniImporter() { const char *map[][2] = @@ -23,6 +24,12 @@ void MwIniImporter::setVerbose(bool verbose) { mVerbose = verbose; } +std::string MwIniImporter::numberToString(int n) { + std::stringstream str; + str << n; + return str.str(); +} + MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) { std::cout << "load ini file: " << filename << std::endl; @@ -130,7 +137,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) { multistrmap::iterator it = ini.begin(); for(int i=0; it != ini.end(); i++) { gameFile = baseGameFile; - gameFile.append(1,i+'0'); + gameFile.append(this->numberToString(i)); it = ini.find(gameFile); if(it == ini.end()) { @@ -152,24 +159,19 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) { gameFile = ""; } - if(!esmFiles.empty()) { - multistrmap::iterator it; - cfg.erase("master"); - cfg.insert( std::make_pair > ("master", std::vector() ) ); - - for(std::vector::iterator it=esmFiles.begin(); it!=esmFiles.end(); it++) { - cfg["master"].push_back(*it); - } + multistrmap::iterator it; + cfg.erase("master"); + cfg.insert( std::make_pair > ("master", std::vector() ) ); + + for(std::vector::iterator it=esmFiles.begin(); it!=esmFiles.end(); it++) { + cfg["master"].push_back(*it); } - if(!espFiles.empty()) { - multistrmap::iterator it; - cfg.erase("plugin"); - cfg.insert( std::make_pair > ("plugin", std::vector() ) ); - - for(std::vector::iterator it=espFiles.begin(); it!=espFiles.end(); it++) { - cfg["plugin"].push_back(*it); - } + cfg.erase("plugin"); + cfg.insert( std::make_pair > ("plugin", std::vector() ) ); + + for(std::vector::iterator it=espFiles.begin(); it!=espFiles.end(); it++) { + cfg["plugin"].push_back(*it); } } diff --git a/apps/mwiniimporter/importer.hpp b/apps/mwiniimporter/importer.hpp index 454dc209af..988f10255e 100644 --- a/apps/mwiniimporter/importer.hpp +++ b/apps/mwiniimporter/importer.hpp @@ -23,6 +23,7 @@ class MwIniImporter { private: bool specialMerge(std::string cfgKey, std::string iniKey, multistrmap &cfg, multistrmap &ini); + std::string numberToString(int n); bool mVerbose; strmap mMergeMap; }; From 8aa4001937834851b83146177cc591ebbc6f0c47 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 1 Apr 2012 10:34:51 +0200 Subject: [PATCH 40/40] compile fix --- apps/mwiniimporter/importer.cpp | 51 ++++++++++++++++----------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/apps/mwiniimporter/importer.cpp b/apps/mwiniimporter/importer.cpp index a82240a8aa..08b05f417e 100644 --- a/apps/mwiniimporter/importer.cpp +++ b/apps/mwiniimporter/importer.cpp @@ -14,7 +14,7 @@ MwIniImporter::MwIniImporter() { { "fps", "General:Show FPS" }, { 0, 0 } }; - + for(int i=0; map[i][0]; i++) { mMergeMap.insert(std::make_pair(map[i][0], map[i][1])); } @@ -32,7 +32,7 @@ std::string MwIniImporter::numberToString(int n) { MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) { std::cout << "load ini file: " << filename << std::endl; - + std::string section(""); MwIniImporter::multistrmap map; boost::iostreams::streamfile(filename.c_str()); @@ -46,68 +46,68 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(std::string filename) { } continue; } - + int comment_pos = line.find(";"); if(comment_pos > 0) { line = line.substr(0,comment_pos); } - + if(line.empty()) { continue; } - + int pos = line.find("="); if(pos < 1) { continue; } - + std::string key(section + ":" + line.substr(0,pos)); std::string value(line.substr(pos+1)); - + multistrmap::iterator it; if((it = map.find(key)) == map.end()) { map.insert( std::make_pair > (key, std::vector() ) ); } map[key].push_back(value); } - + return map; } MwIniImporter::multistrmap MwIniImporter::loadCfgFile(std::string filename) { std::cout << "load cfg file: " << filename << std::endl; - + MwIniImporter::multistrmap map; boost::iostreams::streamfile(filename.c_str()); std::string line; while (std::getline(file, line)) { - + // we cant say comment by only looking at first char anymore int comment_pos = line.find("#"); if(comment_pos > 0) { line = line.substr(0,comment_pos); } - + if(line.empty()) { continue; } - + int pos = line.find("="); if(pos < 1) { continue; } - + std::string key(line.substr(0,pos)); std::string value(line.substr(pos+1)); - + multistrmap::iterator it; if((it = map.find(key)) == map.end()) { map.insert( std::make_pair > (key, std::vector() ) ); } map[key].push_back(value); } - + return map; } @@ -138,16 +138,16 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) { for(int i=0; it != ini.end(); i++) { gameFile = baseGameFile; gameFile.append(this->numberToString(i)); - + it = ini.find(gameFile); if(it == ini.end()) { break; } - + for(std::vector::iterator entry = it->second.begin(); entry!=it->second.end(); entry++) { std::string filetype(entry->substr(entry->length()-4, 3)); std::transform(filetype.begin(), filetype.end(), filetype.begin(), ::tolower); - + if(filetype.compare("esm") == 0) { esmFiles.push_back(*entry); } @@ -155,33 +155,30 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, multistrmap &ini) { espFiles.push_back(*entry); } } - + gameFile = ""; } - - multistrmap::iterator it; + cfg.erase("master"); cfg.insert( std::make_pair > ("master", std::vector() ) ); - + for(std::vector::iterator it=esmFiles.begin(); it!=esmFiles.end(); it++) { cfg["master"].push_back(*it); } - + cfg.erase("plugin"); cfg.insert( std::make_pair > ("plugin", std::vector() ) ); - + for(std::vector::iterator it=espFiles.begin(); it!=espFiles.end(); it++) { cfg["plugin"].push_back(*it); } } void MwIniImporter::writeToFile(boost::iostreams::stream &out, multistrmap &cfg) { - + for(multistrmap::iterator it=cfg.begin(); it != cfg.end(); it++) { for(std::vector::iterator entry=it->second.begin(); entry != it->second.end(); entry++) { out << (it->first) << "=" << (*entry) << std::endl; } } } - -