From 30b05b557bc70cf6d20b989507499b96018a01be Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 14 Oct 2017 10:23:59 +0400 Subject: [PATCH 01/35] ExtraSpell magic effect: a basic implementation --- apps/openmw/mwmechanics/spellcasting.cpp | 7 +++++++ components/esm/loadmgef.cpp | 1 + 2 files changed, 8 insertions(+) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index a808b8285..a09436d14 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -536,6 +536,13 @@ namespace MWMechanics appliedLastingEffects.push_back(effect); + // Unequip all items, if a spell with the ExtraSpell effect was casted + if (effectIt->mEffectID == ESM::MagicEffect::ExtraSpell && target.getClass().hasInventoryStore(target)) + { + MWWorld::InventoryStore& store = target.getClass().getInventoryStore(target); + store.unequipAll(target); + } + // Command spells should have their effect, including taking the target out of combat, each time the spell successfully affects the target if (((effectIt->mEffectID == ESM::MagicEffect::CommandHumanoid && target.getClass().isNpc()) || (effectIt->mEffectID == ESM::MagicEffect::CommandCreature && target.getTypeName() == typeid(ESM::Creature).name())) diff --git a/components/esm/loadmgef.cpp b/components/esm/loadmgef.cpp index 3a918cf19..9f8ad94e1 100644 --- a/components/esm/loadmgef.cpp +++ b/components/esm/loadmgef.cpp @@ -380,6 +380,7 @@ static std::map genNameMap() names[131] ="sEffectBoundGloves"; names[128] ="sEffectBoundHelm"; names[125] ="sEffectBoundLongbow"; + names[126] ="sEffectExtraSpell"; names[121] ="sEffectBoundLongsword"; names[122] ="sEffectBoundMace"; names[130] ="sEffectBoundShield"; From 548af6dbfbdd265c94796fa79f6c87cedabc5135 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sat, 14 Oct 2017 14:02:20 +0000 Subject: [PATCH 02/35] Fix jail screen fading --- apps/openmw/mwgui/jailscreen.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwgui/jailscreen.cpp b/apps/openmw/mwgui/jailscreen.cpp index 11d7466a8..9fa5927ac 100644 --- a/apps/openmw/mwgui/jailscreen.cpp +++ b/apps/openmw/mwgui/jailscreen.cpp @@ -58,6 +58,7 @@ namespace MWGui { MWWorld::Ptr player = MWMechanics::getPlayer(); MWBase::Environment::get().getWorld()->teleportToClosestMarker(player, "prisonmarker"); + MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.f); // override fade-in caused by cell transition setVisible(true); mTimeAdvancer.run(100); From 6d9d98c02cc663d67372a65c1aaea58b35dacc23 Mon Sep 17 00:00:00 2001 From: Kyle Cooley Date: Sat, 14 Oct 2017 11:32:42 -0400 Subject: [PATCH 03/35] Merge Land/LandTextures --- apps/opencs/model/tools/mergeoperation.cpp | 4 +- apps/opencs/model/tools/mergestages.cpp | 161 ++++++--------------- apps/opencs/model/tools/mergestages.hpp | 37 ++--- 3 files changed, 65 insertions(+), 137 deletions(-) diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index 9b595046a..cbd2abe0d 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -38,9 +38,9 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::Fr appendStage (new MergeRefIdsStage (mState)); appendStage (new MergeReferencesStage (mState)); appendStage (new MergeReferencesStage (mState)); - appendStage (new ListLandTexturesMergeStage (mState)); - appendStage (new MergeLandTexturesStage (mState)); + appendStage (new PopulateLandTexturesMergeStage (mState)); appendStage (new MergeLandStage (mState)); + appendStage (new FixLandsAndLandTexturesMergeStage (mState)); appendStage (new FinishMergedDocumentStage (mState, encoding)); } diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index 176d35914..eea0656b7 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -8,7 +8,9 @@ #include "mergestate.hpp" #include "../doc/document.hpp" +#include "../world/commands.hpp" #include "../world/data.hpp" +#include "../world/idtable.hpp" CSMTools::StartMergeStage::StartMergeStage (MergeState& state) @@ -109,102 +111,32 @@ void CSMTools::MergeReferencesStage::perform (int stage, CSMDoc::Messages& messa } -CSMTools::ListLandTexturesMergeStage::ListLandTexturesMergeStage (MergeState& state) -: mState (state) -{} - -int CSMTools::ListLandTexturesMergeStage::setup() +CSMTools::PopulateLandTexturesMergeStage::PopulateLandTexturesMergeStage (MergeState& state) + : mState (state) { - return mState.mSource.getData().getLand().getSize(); } -void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages) +int CSMTools::PopulateLandTexturesMergeStage::setup() { - const CSMWorld::Record& record = - mState.mSource.getData().getLand().getRecord (stage); - - if (!record.isDeleted()) - { - const CSMWorld::Land& land = record.get(); - - // make sure record is loaded - land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | - ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX); - - if (const ESM::Land::LandData *data = land.getLandData (ESM::Land::DATA_VTEX)) - { - // list texture indices - std::pair key; - key.second = land.mPlugin; - - for (int i=0; imTextures[i]; - - mState.mTextureIndices[key] = -1; - } - } - } -} - - -CSMTools::MergeLandTexturesStage::MergeLandTexturesStage (MergeState& state) -: mState (state), mNext (mState.mTextureIndices.end()) -{} - -int CSMTools::MergeLandTexturesStage::setup() -{ - // Should use the size of mState.mTextureIndices instead, but that is not available at this - // point. Unless there are any errors in the land and land texture records this will not - // make a difference. return mState.mSource.getData().getLandTextures().getSize(); } -void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& messages) +void CSMTools::PopulateLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages) { - if (stage==0) - mNext = mState.mTextureIndices.begin(); + const CSMWorld::Record& record = + mState.mSource.getData().getLandTextures().getRecord (stage); - bool found = false; - - do + if (!record.isDeleted()) { - if (mNext==mState.mTextureIndices.end()) - return; - - mNext->second = stage+1; - - std::ostringstream stream; - stream << mNext->first.first-1 << "_" << mNext->first.second; - - int index = mState.mSource.getData().getLandTextures().searchId (stream.str()); - - if (index!=-1) - { - CSMWorld::LandTexture texture = - mState.mSource.getData().getLandTextures().getRecord (index).get(); - - stream.clear(); - stream << mNext->second-1 << "_0"; - - texture.mIndex = mNext->second-1; - texture.mId = stream.str(); - - CSMWorld::Record newRecord ( - CSMWorld::RecordBase::State_ModifiedOnly, 0, &texture); - - mState.mTarget->getData().getLandTextures().appendRecord (newRecord); - - found = true; - } - - ++mNext; + mState.mTarget->getData().getLandTextures().appendRecord(record); } - while (!found); } -CSMTools::MergeLandStage::MergeLandStage (MergeState& state) : mState (state) {} +CSMTools::MergeLandStage::MergeLandStage (MergeState& state) + : mState (state) +{ +} int CSMTools::MergeLandStage::setup() { @@ -218,40 +150,35 @@ void CSMTools::MergeLandStage::perform (int stage, CSMDoc::Messages& messages) if (!record.isDeleted()) { - const CSMWorld::Land& land = record.get(); - - land.loadData (ESM::Land::DATA_VCLR | ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | - ESM::Land::DATA_VTEX); - - CSMWorld::Land newLand (land); - - newLand.mPlugin = 0; - - if (land.mDataTypes & ESM::Land::DATA_VTEX) - { - // adjust land texture references - if (ESM::Land::LandData *data = newLand.getLandData()) - { - std::pair key; - key.second = land.mPlugin; - - for (int i=0; imTextures[i]; - std::map, int>::const_iterator iter = - mState.mTextureIndices.find (key); - - if (iter!=mState.mTextureIndices.end()) - data->mTextures[i] = iter->second; - else - data->mTextures[i] = 0; - } - } - } - - CSMWorld::Record newRecord ( - CSMWorld::RecordBase::State_ModifiedOnly, 0, &newLand); - - mState.mTarget->getData().getLand().appendRecord (newRecord); + mState.mTarget->getData().getLand().appendRecord (record); + } +} + + +CSMTools::FixLandsAndLandTexturesMergeStage::FixLandsAndLandTexturesMergeStage (MergeState& state) + : mState (state) +{ +} + +int CSMTools::FixLandsAndLandTexturesMergeStage::setup() +{ + // We will have no more than the source + return mState.mSource.getData().getLand().getSize(); +} + +void CSMTools::FixLandsAndLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages) +{ + if (stage < mState.mTarget->getData().getLand().getSize()) + { + CSMWorld::IdTable& landTable = dynamic_cast( + *mState.mTarget->getData().getTableModel(CSMWorld::UniversalId::Type_Lands)); + + CSMWorld::IdTable& ltexTable = dynamic_cast( + *mState.mTarget->getData().getTableModel(CSMWorld::UniversalId::Type_LandTextures)); + + std::string id = mState.mTarget->getData().getLand().getId(stage); + + CSMWorld::TouchLandCommand cmd(landTable, ltexTable, id); + cmd.redo(); } } diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index f88f5be9f..96339ed4c 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -116,29 +116,14 @@ namespace CSMTools ///< Messages resulting from this stage will be appended to \a messages. }; - class ListLandTexturesMergeStage : public CSMDoc::Stage + /// Adds all land texture records that could potentially be referenced when merging + class PopulateLandTexturesMergeStage : public CSMDoc::Stage { MergeState& mState; public: - ListLandTexturesMergeStage (MergeState& state); - - virtual int setup(); - ///< \return number of steps - - virtual void perform (int stage, CSMDoc::Messages& messages); - ///< Messages resulting from this stage will be appended to \a messages. - }; - - class MergeLandTexturesStage : public CSMDoc::Stage - { - MergeState& mState; - std::map, int>::iterator mNext; - - public: - - MergeLandTexturesStage (MergeState& state); + PopulateLandTexturesMergeStage (MergeState& state); virtual int setup(); ///< \return number of steps @@ -161,6 +146,22 @@ namespace CSMTools virtual void perform (int stage, CSMDoc::Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; + + /// Flattens the added land and land texture records. + class FixLandsAndLandTexturesMergeStage : public CSMDoc::Stage + { + MergeState& mState; + + public: + + FixLandsAndLandTexturesMergeStage (MergeState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; } #endif From 98c38ad7d1201fe951d8c94ffcff4175f7c90875 Mon Sep 17 00:00:00 2001 From: Kyle Cooley Date: Sat, 14 Oct 2017 13:18:31 -0400 Subject: [PATCH 04/35] Merge cleanup. --- apps/opencs/model/tools/mergeoperation.cpp | 1 + apps/opencs/model/tools/mergestages.cpp | 31 ++++++++++++++++++++++ apps/opencs/model/tools/mergestages.hpp | 16 +++++++++++ 3 files changed, 48 insertions(+) diff --git a/apps/opencs/model/tools/mergeoperation.cpp b/apps/opencs/model/tools/mergeoperation.cpp index cbd2abe0d..b15b4b83f 100644 --- a/apps/opencs/model/tools/mergeoperation.cpp +++ b/apps/opencs/model/tools/mergeoperation.cpp @@ -41,6 +41,7 @@ CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::Fr appendStage (new PopulateLandTexturesMergeStage (mState)); appendStage (new MergeLandStage (mState)); appendStage (new FixLandsAndLandTexturesMergeStage (mState)); + appendStage (new CleanupLandTexturesMergeStage (mState)); appendStage (new FinishMergedDocumentStage (mState, encoding)); } diff --git a/apps/opencs/model/tools/mergestages.cpp b/apps/opencs/model/tools/mergestages.cpp index eea0656b7..897c3329c 100644 --- a/apps/opencs/model/tools/mergestages.cpp +++ b/apps/opencs/model/tools/mergestages.cpp @@ -180,5 +180,36 @@ void CSMTools::FixLandsAndLandTexturesMergeStage::perform (int stage, CSMDoc::Me CSMWorld::TouchLandCommand cmd(landTable, ltexTable, id); cmd.redo(); + + // Get rid of base data + const CSMWorld::Record& oldRecord = + mState.mTarget->getData().getLand().getRecord (stage); + + CSMWorld::Record newRecord(CSMWorld::RecordBase::State_ModifiedOnly, + nullptr, &oldRecord.get()); + + mState.mTarget->getData().getLand().setRecord(stage, newRecord); + } +} + +CSMTools::CleanupLandTexturesMergeStage::CleanupLandTexturesMergeStage (MergeState& state) + : mState (state) +{ +} + +int CSMTools::CleanupLandTexturesMergeStage::setup() +{ + return 1; +} + +void CSMTools::CleanupLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages) +{ + auto& landTextures = mState.mTarget->getData().getLandTextures(); + for (int i = 0; i < landTextures.getSize(); ) + { + if (!landTextures.getRecord(i).isModified()) + landTextures.removeRows(i, 1); + else + ++i; } } diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index 96339ed4c..9a16e03ab 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -162,6 +162,22 @@ namespace CSMTools virtual void perform (int stage, CSMDoc::Messages& messages); ///< Messages resulting from this stage will be appended to \a messages. }; + + // Removes base LandTexture records. + class CleanupLandTexturesMergeStage : public CSMDoc::Stage + { + MergeState& mState; + + public: + + CleanupLandTexturesMergeStage (MergeState& state); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, CSMDoc::Messages& messages); + ///< Messages resulting from this stage will be appended to \a messages. + }; } #endif From d27071f06a1276e1b5450bb8a02a565516b8b575 Mon Sep 17 00:00:00 2001 From: Kyle Cooley Date: Sat, 14 Oct 2017 13:18:54 -0400 Subject: [PATCH 05/35] Fix LTEX import bug. --- apps/opencs/model/world/idtable.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index fcfc8577e..3e503a80c 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -336,7 +336,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import int oldRow = idCollection()->searchId(id); // If it does not exist or it is in the current plugin, it can be skipped. - if (oldRow <= 0 || plugin == 0) + if (oldRow < 0 || plugin == 0) { results.recordMapping.push_back(std::make_pair(id, id)); continue; From 5fbdb64bb913717a81ccbf919dea2789b227df74 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sat, 14 Oct 2017 18:28:46 +0000 Subject: [PATCH 06/35] Add OPENMW_DECOMPRESS_TEXTURES environment variable to decompress textures in software if not supported by graphics hardware Disabled by default due to requiring new functionality that was just added to OSG 3.6 or OpenMW/OSG. --- components/resource/imagemanager.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/components/resource/imagemanager.cpp b/components/resource/imagemanager.cpp index 441fd8212..000a833cf 100644 --- a/components/resource/imagemanager.cpp +++ b/components/resource/imagemanager.cpp @@ -69,7 +69,6 @@ namespace Resource // This one works too. Should it be included in isTextureCompressionS3TCSupported()? Submitted as a patch to OSG. && !osg::isGLExtensionSupported(0, "GL_S3_s3tc")) { - std::cerr << "Error loading " << filename << ": no S3TC texture compression support installed" << std::endl; return false; } break; @@ -123,12 +122,31 @@ namespace Resource return mWarningImage; } - osg::Image* image = result.getImage(); + osg::ref_ptr image = result.getImage(); + image->setFileName(normalized); if (!checkSupported(image, filename)) { - mCache->addEntryToObjectCache(normalized, mWarningImage); - return mWarningImage; + static bool uncompress = (getenv("OPENMW_DECOMPRESS_TEXTURES") != 0); + if (!uncompress) + { + std::cerr << "Error loading " << filename << ": no S3TC texture compression support installed" << std::endl; + mCache->addEntryToObjectCache(normalized, mWarningImage); + return mWarningImage; + } + else + { + // decompress texture in software if not supported by GPU + // requires update to getColor() to be released with OSG 3.6 + osg::ref_ptr newImage = new osg::Image; + newImage->setFileName(image->getFileName()); + newImage->allocateImage(image->s(), image->t(), image->r(), image->isImageTranslucent() ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE); + for (int s=0; ss(); ++s) + for (int t=0; tt(); ++t) + for (int r=0; rr(); ++r) + newImage->setColor(image->getColor(s,t,r), s,t,r); + image = newImage; + } } mCache->addEntryToObjectCache(normalized, image); From 11eae166458440c99908e8a38c4b512a3e361062 Mon Sep 17 00:00:00 2001 From: Kyle Cooley Date: Sat, 14 Oct 2017 15:09:12 -0400 Subject: [PATCH 07/35] Get rid of duplicate function, fix flag checking --- apps/opencs/model/world/columnimp.cpp | 10 +++++----- components/esm/loadland.cpp | 11 +---------- components/esm/loadland.hpp | 1 - 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/apps/opencs/model/world/columnimp.cpp b/apps/opencs/model/world/columnimp.cpp index 18da81b53..49e4bebe6 100644 --- a/apps/opencs/model/world/columnimp.cpp +++ b/apps/opencs/model/world/columnimp.cpp @@ -108,7 +108,7 @@ namespace CSMWorld throw std::runtime_error("invalid land map LOD data"); Land copy = record.get(); - copy.setDataLoaded(Land::DATA_WNAM); + copy.add(Land::DATA_WNAM); for (int i = 0; i < values.size(); ++i) { @@ -155,7 +155,7 @@ namespace CSMWorld throw std::runtime_error("invalid land normals data"); Land copy = record.get(); - copy.setDataLoaded(Land::DATA_VNML); + copy.add(Land::DATA_VNML); for (int i = 0; i < values.size(); ++i) { @@ -202,7 +202,7 @@ namespace CSMWorld throw std::runtime_error("invalid land heights data"); Land copy = record.get(); - copy.setDataLoaded(Land::DATA_VHGT); + copy.add(Land::DATA_VHGT); for (int i = 0; i < values.size(); ++i) { @@ -249,7 +249,7 @@ namespace CSMWorld throw std::runtime_error("invalid land colours data"); Land copy = record.get(); - copy.setDataLoaded(Land::DATA_VCLR); + copy.add(Land::DATA_VCLR); for (int i = 0; i < values.size(); ++i) { @@ -296,7 +296,7 @@ namespace CSMWorld throw std::runtime_error("invalid land textures data"); Land copy = record.get(); - copy.setDataLoaded(Land::DATA_VTEX); + copy.add(Land::DATA_VTEX); for (int i = 0; i < values.size(); ++i) { diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index f3f72e88a..a91dfe3d3 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -315,16 +315,7 @@ namespace ESM bool Land::isDataLoaded(int flags) const { - return mLandData && (mLandData->mDataLoaded & flags) == (flags & mDataTypes); - } - - void Land::setDataLoaded(int flags) - { - if (!mLandData) - mLandData = new LandData; - - mDataTypes |= flags; - mLandData->mDataLoaded |= flags; + return mLandData && (mLandData->mDataLoaded & flags) == flags; } Land::Land (const Land& land) diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 7be954b3e..2163c30fc 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -132,7 +132,6 @@ struct Land void unloadData() const; /// Check if given data type is loaded - /// @note We only check data types that *can* be loaded (present in mDataTypes) bool isDataLoaded(int flags) const; /// Sets the flags and creates a LandData if needed From b95c9ba483c54362bc94d935704978c5b6f88ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Wed, 4 Oct 2017 16:41:55 +0200 Subject: [PATCH 08/35] rain independent from camera plus wrap-around --- apps/openmw/mwrender/renderingmanager.cpp | 2 +- apps/openmw/mwrender/sky.cpp | 55 +++++++++++++++++++++-- apps/openmw/mwrender/sky.hpp | 5 ++- 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 3826fd5f6..37abb1ec3 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -255,7 +255,7 @@ namespace MWRender mRootNode->getOrCreateStateSet()->addUniform(mUniformRainIntensity); - mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager())); + mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager(), this)); source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 178c753c6..0603c18a1 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -46,6 +47,8 @@ #include "vismask.hpp" #include "renderbin.hpp" +#define PARTICLE_WIDTH 600.0 + namespace { @@ -1091,8 +1094,9 @@ private: } }; -SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager) +SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager, MWRender::RenderingManager *renderingManager) : mSceneManager(sceneManager) + , mRendering(renderingManager) , mAtmosphereNightRoll(0.f) , mCreated(false) , mIsStorm(false) @@ -1337,6 +1341,43 @@ protected: osg::Uniform* mRainIntensityUniform; }; +class WeatherParticleDrawCallback : public osg::Drawable::DrawCallback +{ +public: + WeatherParticleDrawCallback(MWRender::RenderingManager *renderingManager) : osg::Drawable::DrawCallback() + { + mRendering = renderingManager; + } + + virtual void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable *drawable) const + { + osg::Vec3 cameraPos = mRendering->getCameraPosition(); + osg::Vec3 cameraOffset = osg::Vec3( + PARTICLE_WIDTH - fmod(cameraPos.x(), PARTICLE_WIDTH / 2), + PARTICLE_WIDTH - fmod(cameraPos.y(), PARTICLE_WIDTH / 2), + 0); + + osgParticle::ParticleSystem *ps = (osgParticle::ParticleSystem *) drawable; + + for (int xOff = 0; xOff < 3; xOff++) + for (int yOff = 0; yOff < 3; yOff++) + { + osg::Vec3 offset = cameraOffset + osg::Vec3(-1 * xOff * PARTICLE_WIDTH, -1 * yOff * PARTICLE_WIDTH,0); + + for(int i = 0; i < ps->numParticles(); i++) + ps->getParticle(i)->setPosition(ps->getParticle(i)->getPosition() + offset); + + ps->drawImplementation(renderInfo); + + for(int i = 0; i < ps->numParticles(); i++) + ps->getParticle(i)->setPosition(ps->getParticle(i)->getPosition() - offset); + } + } + +protected: + MWRender::RenderingManager *mRendering; +}; + void SkyManager::createRain() { if (mRainNode) @@ -1345,6 +1386,8 @@ void SkyManager::createRain() mRainNode = new osg::Group; mRainParticleSystem = new osgParticle::ParticleSystem; + mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(mRendering)); + mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED); mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0)); mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,1)); @@ -1370,8 +1413,8 @@ void SkyManager::createRain() emitter->setParticleSystem(mRainParticleSystem); osg::ref_ptr placer (new osgParticle::BoxPlacer); - placer->setXRange(-300, 300); // Rain_Diameter - placer->setYRange(-300, 300); + placer->setXRange(-PARTICLE_WIDTH / 2, PARTICLE_WIDTH / 2); // Rain_Diameter + placer->setYRange(-PARTICLE_WIDTH / 2, PARTICLE_WIDTH / 2); placer->setZRange(300, 300); emitter->setPlacer(placer); @@ -1559,6 +1602,12 @@ void SkyManager::setWeather(const WeatherResult& weather) SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor; mParticleEffect->accept(disableFreezeOnCullVisitor); + + osgParticle::ParticleSystem *ps = (osgParticle::ParticleSystem *) + (mParticleEffect->asGroup()->getChild(1)->asGroup()->getChild(0) + ->asGroup()->getChild(2)); + + ps->setDrawCallback(new WeatherParticleDrawCallback(mRendering)); } } diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 59a8ddc4e..37c999563 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -9,6 +9,8 @@ #include #include +#include + namespace osg { class Group; @@ -108,7 +110,7 @@ namespace MWRender class SkyManager { public: - SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager); + SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager, MWRender::RenderingManager *renderingManager); ~SkyManager(); void update(float duration); @@ -170,6 +172,7 @@ namespace MWRender void updateRainParameters(); Resource::SceneManager* mSceneManager; + MWRender::RenderingManager *mRendering; osg::ref_ptr mRootNode; osg::ref_ptr mEarlyRenderBinRoot; From 33a1459b11b3efca1ed566f8d58f3f3c16871648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Wed, 4 Oct 2017 22:29:59 +0200 Subject: [PATCH 09/35] search for particle system by class name --- apps/openmw/mwrender/sky.cpp | 49 ++++++++++++++++++++++---------- apps/openmw/mwrender/sky.hpp | 2 +- components/nifosg/particle.cpp | 5 ++++ components/nifosg/particle.hpp | 1 + components/sceneutil/visitor.cpp | 8 ++++++ components/sceneutil/visitor.hpp | 17 ++++++++++- 6 files changed, 65 insertions(+), 17 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 0603c18a1..cce2e1b1d 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -47,7 +47,7 @@ #include "vismask.hpp" #include "renderbin.hpp" -#define PARTICLE_WIDTH 600.0 +#define RAIN_WIDTH 600.0 namespace { @@ -1344,17 +1344,19 @@ protected: class WeatherParticleDrawCallback : public osg::Drawable::DrawCallback { public: - WeatherParticleDrawCallback(MWRender::RenderingManager *renderingManager) : osg::Drawable::DrawCallback() + WeatherParticleDrawCallback(MWRender::RenderingManager *renderingManager, float rangeX, float rangeY) : osg::Drawable::DrawCallback() { mRendering = renderingManager; + mRangeX = rangeX; + mRangeY = rangeY; } virtual void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable *drawable) const { osg::Vec3 cameraPos = mRendering->getCameraPosition(); osg::Vec3 cameraOffset = osg::Vec3( - PARTICLE_WIDTH - fmod(cameraPos.x(), PARTICLE_WIDTH / 2), - PARTICLE_WIDTH - fmod(cameraPos.y(), PARTICLE_WIDTH / 2), + mRangeX - fmod(cameraPos.x(), mRangeX / 2), + mRangeY - fmod(cameraPos.y(), mRangeY / 2), 0); osgParticle::ParticleSystem *ps = (osgParticle::ParticleSystem *) drawable; @@ -1362,7 +1364,7 @@ public: for (int xOff = 0; xOff < 3; xOff++) for (int yOff = 0; yOff < 3; yOff++) { - osg::Vec3 offset = cameraOffset + osg::Vec3(-1 * xOff * PARTICLE_WIDTH, -1 * yOff * PARTICLE_WIDTH,0); + osg::Vec3 offset = cameraOffset + osg::Vec3(-1 * xOff * mRangeX, -1 * yOff * mRangeY,0); for(int i = 0; i < ps->numParticles(); i++) ps->getParticle(i)->setPosition(ps->getParticle(i)->getPosition() + offset); @@ -1376,6 +1378,7 @@ public: protected: MWRender::RenderingManager *mRendering; + float mRangeX, mRangeY; }; void SkyManager::createRain() @@ -1386,7 +1389,7 @@ void SkyManager::createRain() mRainNode = new osg::Group; mRainParticleSystem = new osgParticle::ParticleSystem; - mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(mRendering)); + mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(mRendering,RAIN_WIDTH,RAIN_WIDTH)); mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED); mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0)); @@ -1413,8 +1416,8 @@ void SkyManager::createRain() emitter->setParticleSystem(mRainParticleSystem); osg::ref_ptr placer (new osgParticle::BoxPlacer); - placer->setXRange(-PARTICLE_WIDTH / 2, PARTICLE_WIDTH / 2); // Rain_Diameter - placer->setYRange(-PARTICLE_WIDTH / 2, PARTICLE_WIDTH / 2); + placer->setXRange(-RAIN_WIDTH / 2, RAIN_WIDTH / 2); // Rain_Diameter + placer->setYRange(-RAIN_WIDTH / 2, RAIN_WIDTH / 2); placer->setZRange(300, 300); emitter->setPlacer(placer); @@ -1493,8 +1496,6 @@ void SkyManager::update(float duration) osg::Quat quat; quat.makeRotate(osg::Vec3f(0,1,0), mStormDirection); - if (mParticleNode) - mParticleNode->setAttitude(quat); mCloudNode->setAttitude(quat); } else @@ -1586,7 +1587,7 @@ void SkyManager::setWeather(const WeatherResult& weather) { if (!mParticleNode) { - mParticleNode = new osg::PositionAttitudeTransform; + mParticleNode = new osg::Group; mParticleNode->addCullCallback(mUnderwaterSwitch); mParticleNode->setNodeMask(Mask_WeatherParticles); mRootNode->addChild(mParticleNode); @@ -1603,11 +1604,29 @@ void SkyManager::setWeather(const WeatherResult& weather) SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor; mParticleEffect->accept(disableFreezeOnCullVisitor); - osgParticle::ParticleSystem *ps = (osgParticle::ParticleSystem *) - (mParticleEffect->asGroup()->getChild(1)->asGroup()->getChild(0) - ->asGroup()->getChild(2)); + SceneUtil::FindByClassVisitor findEmitterVisitor(std::string("Emitter")); + mParticleEffect->accept(findEmitterVisitor); - ps->setDrawCallback(new WeatherParticleDrawCallback(mRendering)); + float rangeX = RAIN_WIDTH; + float rangeY = RAIN_WIDTH; + + if (findEmitterVisitor.mFoundNode) + { + osgParticle::Placer *placer = ((NifOsg::Emitter *) findEmitterVisitor.mFoundNode)->getPlacer(); + + if (placer && strcmp(placer->className(),"BoxPlacer") == 0) + { + rangeX = ((osgParticle::BoxPlacer *) placer)->getXRange().maximum; + rangeY = ((osgParticle::BoxPlacer *) placer)->getYRange().maximum; + } + } + + + SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem")); + mParticleEffect->accept(findPSVisitor); + + if (findPSVisitor.mFoundNode) + ((osgParticle::ParticleSystem *) findPSVisitor.mFoundNode)->setDrawCallback(new WeatherParticleDrawCallback(mRendering,rangeX,rangeY)); } } diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 37c999563..fdcd27e5a 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -177,7 +177,7 @@ namespace MWRender osg::ref_ptr mRootNode; osg::ref_ptr mEarlyRenderBinRoot; - osg::ref_ptr mParticleNode; + osg::ref_ptr mParticleNode; osg::ref_ptr mParticleEffect; std::vector > mParticleFaders; osg::ref_ptr mUnderwaterSwitch; diff --git a/components/nifosg/particle.cpp b/components/nifosg/particle.cpp index 62360b9d6..547b71034 100644 --- a/components/nifosg/particle.cpp +++ b/components/nifosg/particle.cpp @@ -250,6 +250,11 @@ void Emitter::setPlacer(osgParticle::Placer *placer) mPlacer = placer; } +osgParticle::Placer *Emitter::getPlacer() +{ + return mPlacer; +} + void Emitter::setCounter(osgParticle::Counter *counter) { mCounter = counter; diff --git a/components/nifosg/particle.hpp b/components/nifosg/particle.hpp index 7a2377f9d..df93d5ced 100644 --- a/components/nifosg/particle.hpp +++ b/components/nifosg/particle.hpp @@ -225,6 +225,7 @@ namespace NifOsg void setShooter(osgParticle::Shooter* shooter); void setPlacer(osgParticle::Placer* placer); + osgParticle::Placer *getPlacer(); void setCounter(osgParticle::Counter* counter); private: diff --git a/components/sceneutil/visitor.cpp b/components/sceneutil/visitor.cpp index 74b9be63d..202e6373e 100644 --- a/components/sceneutil/visitor.cpp +++ b/components/sceneutil/visitor.cpp @@ -19,6 +19,14 @@ namespace SceneUtil return false; } + void FindByClassVisitor::apply(osg::Node &node) + { + if (Misc::StringUtils::ciEqual(node.className(), mNameToFind)) + mFoundNode = &node; + else + traverse(node); + } + void FindByNameVisitor::apply(osg::Group &group) { if (!checkGroup(group)) diff --git a/components/sceneutil/visitor.hpp b/components/sceneutil/visitor.hpp index 209f2d9bd..973f44646 100644 --- a/components/sceneutil/visitor.hpp +++ b/components/sceneutil/visitor.hpp @@ -20,7 +20,6 @@ namespace SceneUtil } virtual void apply(osg::Group& group); - virtual void apply(osg::MatrixTransform& node); virtual void apply(osg::Geometry& node); @@ -30,6 +29,22 @@ namespace SceneUtil osg::Group* mFoundNode; }; + class FindByClassVisitor : public osg::NodeVisitor + { + public: + FindByClassVisitor(const std::string& nameToFind) + : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) + , mNameToFind(nameToFind) + , mFoundNode(NULL) + { + } + + virtual void apply(osg::Node &node); + + std::string mNameToFind; + osg::Node* mFoundNode; + }; + // Disable freezeOnCull for all visited particlesystems class DisableFreezeOnCullVisitor : public osg::NodeVisitor { From 8114126a62ecd4904f3c92fd0d5667d874700a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Thu, 5 Oct 2017 12:58:56 +0200 Subject: [PATCH 10/35] make use of renderinfo --- apps/openmw/mwrender/renderingmanager.cpp | 2 +- apps/openmw/mwrender/sky.cpp | 65 ++++++++++++++--------- apps/openmw/mwrender/sky.hpp | 7 +-- 3 files changed, 42 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 37abb1ec3..3826fd5f6 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -255,7 +255,7 @@ namespace MWRender mRootNode->getOrCreateStateSet()->addUniform(mUniformRainIntensity); - mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager(), this)); + mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager())); source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index cce2e1b1d..81494d8e2 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1094,9 +1094,8 @@ private: } }; -SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager, MWRender::RenderingManager *renderingManager) +SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager) : mSceneManager(sceneManager) - , mRendering(renderingManager) , mAtmosphereNightRoll(0.f) , mCreated(false) , mIsStorm(false) @@ -1344,40 +1343,50 @@ protected: class WeatherParticleDrawCallback : public osg::Drawable::DrawCallback { public: - WeatherParticleDrawCallback(MWRender::RenderingManager *renderingManager, float rangeX, float rangeY) : osg::Drawable::DrawCallback() + WeatherParticleDrawCallback(float rangeX, float rangeY) : osg::Drawable::DrawCallback() { - mRendering = renderingManager; mRangeX = rangeX; mRangeY = rangeY; } virtual void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable *drawable) const { - osg::Vec3 cameraPos = mRendering->getCameraPosition(); - osg::Vec3 cameraOffset = osg::Vec3( - mRangeX - fmod(cameraPos.x(), mRangeX / 2), - mRangeY - fmod(cameraPos.y(), mRangeY / 2), - 0); - osgParticle::ParticleSystem *ps = (osgParticle::ParticleSystem *) drawable; + osg::Vec3 cameraPos = renderInfo.getCurrentCamera()->getInverseViewMatrix().getTrans(); - for (int xOff = 0; xOff < 3; xOff++) - for (int yOff = 0; yOff < 3; yOff++) - { - osg::Vec3 offset = cameraOffset + osg::Vec3(-1 * xOff * mRangeX, -1 * yOff * mRangeY,0); + osg::Vec3 cameraOffset = osg::Vec3( + fmod(cameraPos.x(), mRangeX), + fmod(cameraPos.y(), mRangeY), + 0.0); - for(int i = 0; i < ps->numParticles(); i++) - ps->getParticle(i)->setPosition(ps->getParticle(i)->getPosition() + offset); + std::vector positionBackups; - ps->drawImplementation(renderInfo); + for (int i = 0; i < ps->numParticles(); i++) + { + osgParticle::Particle *particle = ps->getParticle(i); - for(int i = 0; i < ps->numParticles(); i++) - ps->getParticle(i)->setPosition(ps->getParticle(i)->getPosition() - offset); - } + positionBackups.push_back(particle->getPosition()); + + particle->setPosition(particle->getPosition() - cameraOffset); + + if (particle->getPosition().x() > mRangeX / 2.0) // wrap-around effect + particle->setPosition(particle->getPosition() - osg::Vec3(mRangeX,0,0)); + else if (particle->getPosition().x() < -mRangeX / 2.0) + particle->setPosition(particle->getPosition() + osg::Vec3(mRangeX,0,0)); + + if (particle->getPosition().y() > mRangeY / 2.0) + particle->setPosition(particle->getPosition() - osg::Vec3(0,mRangeY,0)); + else if (particle->getPosition().y() < -mRangeY / 2.0) + particle->setPosition(particle->getPosition() + osg::Vec3(0,mRangeY,0)); + } + + ps->drawImplementation(renderInfo); + + for (int i = 0; i < ps->numParticles(); i++) // restore positions + ps->getParticle(i)->setPosition(positionBackups[i]); } protected: - MWRender::RenderingManager *mRendering; float mRangeX, mRangeY; }; @@ -1389,11 +1398,12 @@ void SkyManager::createRain() mRainNode = new osg::Group; mRainParticleSystem = new osgParticle::ParticleSystem; - mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(mRendering,RAIN_WIDTH,RAIN_WIDTH)); + mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(RAIN_WIDTH,RAIN_WIDTH)); mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED); mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0)); mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,1)); + mRainParticleSystem->setCullingActive(false); osg::ref_ptr stateset (mRainParticleSystem->getOrCreateStateSet()); @@ -1422,7 +1432,8 @@ void SkyManager::createRain() emitter->setPlacer(placer); osg::ref_ptr counter (new osgParticle::ConstantRateCounter); - counter->setNumberOfParticlesPerSecondToCreate(600.0); +// counter->setNumberOfParticlesPerSecondToCreate(600.0); + counter->setNumberOfParticlesPerSecondToCreate(2000); emitter->setCounter(counter); osg::ref_ptr shooter (new RainShooter); @@ -1496,6 +1507,9 @@ void SkyManager::update(float duration) osg::Quat quat; quat.makeRotate(osg::Vec3f(0,1,0), mStormDirection); + if (mParticleNode) + mParticleNode->setAttitude(quat); + mCloudNode->setAttitude(quat); } else @@ -1587,7 +1601,7 @@ void SkyManager::setWeather(const WeatherResult& weather) { if (!mParticleNode) { - mParticleNode = new osg::Group; + mParticleNode = new osg::PositionAttitudeTransform; mParticleNode->addCullCallback(mUnderwaterSwitch); mParticleNode->setNodeMask(Mask_WeatherParticles); mRootNode->addChild(mParticleNode); @@ -1621,12 +1635,11 @@ void SkyManager::setWeather(const WeatherResult& weather) } } - SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem")); mParticleEffect->accept(findPSVisitor); if (findPSVisitor.mFoundNode) - ((osgParticle::ParticleSystem *) findPSVisitor.mFoundNode)->setDrawCallback(new WeatherParticleDrawCallback(mRendering,rangeX,rangeY)); + ((osgParticle::ParticleSystem *) findPSVisitor.mFoundNode)->setDrawCallback(new WeatherParticleDrawCallback(rangeX,rangeY)); } } diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index fdcd27e5a..59a8ddc4e 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -9,8 +9,6 @@ #include #include -#include - namespace osg { class Group; @@ -110,7 +108,7 @@ namespace MWRender class SkyManager { public: - SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager, MWRender::RenderingManager *renderingManager); + SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager); ~SkyManager(); void update(float duration); @@ -172,12 +170,11 @@ namespace MWRender void updateRainParameters(); Resource::SceneManager* mSceneManager; - MWRender::RenderingManager *mRendering; osg::ref_ptr mRootNode; osg::ref_ptr mEarlyRenderBinRoot; - osg::ref_ptr mParticleNode; + osg::ref_ptr mParticleNode; osg::ref_ptr mParticleEffect; std::vector > mParticleFaders; osg::ref_ptr mUnderwaterSwitch; From 38bfa64100414a4ab76c71805a569185c6cd8485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Sun, 8 Oct 2017 20:56:36 +0200 Subject: [PATCH 11/35] transform weather particles to world space --- apps/openmw/mwrender/sky.cpp | 50 +++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 81494d8e2..de1fb780c 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1361,24 +1361,38 @@ public: std::vector positionBackups; + osg::Matrix toWorld, toLocal; + + toWorld.makeIdentity(); + toLocal.makeIdentity(); + + std::vector worldMatrices = drawable->getWorldMatrices(); + + if (!worldMatrices.empty()) + { + toWorld = worldMatrices[0]; + toLocal.invert(toWorld); + } + for (int i = 0; i < ps->numParticles(); i++) - { - osgParticle::Particle *particle = ps->getParticle(i); + { + osgParticle::Particle *particle = ps->getParticle(i); + positionBackups.push_back(particle->getPosition()); + particle->setPosition(toWorld.preMult(particle->getPosition())); + particle->setPosition(particle->getPosition() - cameraOffset); - positionBackups.push_back(particle->getPosition()); + if (particle->getPosition().x() > mRangeX / 2.0) // wrap-around effect + particle->setPosition(particle->getPosition() - osg::Vec3(mRangeX,0,0)); + else if (particle->getPosition().x() < -mRangeX / 2.0) + particle->setPosition(particle->getPosition() + osg::Vec3(mRangeX,0,0)); - particle->setPosition(particle->getPosition() - cameraOffset); + if (particle->getPosition().y() > mRangeY / 2.0) + particle->setPosition(particle->getPosition() - osg::Vec3(0,mRangeY,0)); + else if (particle->getPosition().y() < -mRangeY / 2.0) + particle->setPosition(particle->getPosition() + osg::Vec3(0,mRangeY,0)); - if (particle->getPosition().x() > mRangeX / 2.0) // wrap-around effect - particle->setPosition(particle->getPosition() - osg::Vec3(mRangeX,0,0)); - else if (particle->getPosition().x() < -mRangeX / 2.0) - particle->setPosition(particle->getPosition() + osg::Vec3(mRangeX,0,0)); - - if (particle->getPosition().y() > mRangeY / 2.0) - particle->setPosition(particle->getPosition() - osg::Vec3(0,mRangeY,0)); - else if (particle->getPosition().y() < -mRangeY / 2.0) - particle->setPosition(particle->getPosition() + osg::Vec3(0,mRangeY,0)); - } + particle->setPosition(toLocal.preMult(particle->getPosition())); + } ps->drawImplementation(renderInfo); @@ -1388,6 +1402,7 @@ public: protected: float mRangeX, mRangeY; + }; void SkyManager::createRain() @@ -1432,8 +1447,7 @@ void SkyManager::createRain() emitter->setPlacer(placer); osg::ref_ptr counter (new osgParticle::ConstantRateCounter); -// counter->setNumberOfParticlesPerSecondToCreate(600.0); - counter->setNumberOfParticlesPerSecondToCreate(2000); + counter->setNumberOfParticlesPerSecondToCreate(600.0); emitter->setCounter(counter); osg::ref_ptr shooter (new RainShooter); @@ -1507,8 +1521,8 @@ void SkyManager::update(float duration) osg::Quat quat; quat.makeRotate(osg::Vec3f(0,1,0), mStormDirection); - if (mParticleNode) - mParticleNode->setAttitude(quat); + if (mParticleNode) + mParticleNode->setAttitude(quat); mCloudNode->setAttitude(quat); } From 380a5799dd0afdefe92af185ca63209685068d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Thu, 12 Oct 2017 12:56:03 +0200 Subject: [PATCH 12/35] use bbox as wrap range & apply to all particle systems --- apps/openmw/mwrender/sky.cpp | 55 +++++++++++++------------------- components/sceneutil/visitor.cpp | 6 ++-- components/sceneutil/visitor.hpp | 3 +- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index de1fb780c..fb3e477bb 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -48,6 +48,7 @@ #include "renderbin.hpp" #define RAIN_WIDTH 600.0 +#define RAIN_HEIGHT 600.0 namespace { @@ -1343,10 +1344,9 @@ protected: class WeatherParticleDrawCallback : public osg::Drawable::DrawCallback { public: - WeatherParticleDrawCallback(float rangeX, float rangeY) : osg::Drawable::DrawCallback() + WeatherParticleDrawCallback(osg::Vec3 wrapRange) : osg::Drawable::DrawCallback() { - mRangeX = rangeX; - mRangeY = rangeY; + mWrapRange = wrapRange; } virtual void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable *drawable) const @@ -1355,8 +1355,8 @@ public: osg::Vec3 cameraPos = renderInfo.getCurrentCamera()->getInverseViewMatrix().getTrans(); osg::Vec3 cameraOffset = osg::Vec3( - fmod(cameraPos.x(), mRangeX), - fmod(cameraPos.y(), mRangeY), + fmod(cameraPos.x(), mWrapRange.x()), + fmod(cameraPos.y(), mWrapRange.y()), 0.0); std::vector positionBackups; @@ -1381,15 +1381,15 @@ public: particle->setPosition(toWorld.preMult(particle->getPosition())); particle->setPosition(particle->getPosition() - cameraOffset); - if (particle->getPosition().x() > mRangeX / 2.0) // wrap-around effect - particle->setPosition(particle->getPosition() - osg::Vec3(mRangeX,0,0)); - else if (particle->getPosition().x() < -mRangeX / 2.0) - particle->setPosition(particle->getPosition() + osg::Vec3(mRangeX,0,0)); + if (particle->getPosition().x() > mWrapRange.x() / 2.0) // wrap-around effect + particle->setPosition(particle->getPosition() - osg::Vec3(mWrapRange.x(),0,0)); + else if (particle->getPosition().x() < -mWrapRange.x() / 2.0) + particle->setPosition(particle->getPosition() + osg::Vec3(mWrapRange.x(),0,0)); - if (particle->getPosition().y() > mRangeY / 2.0) - particle->setPosition(particle->getPosition() - osg::Vec3(0,mRangeY,0)); - else if (particle->getPosition().y() < -mRangeY / 2.0) - particle->setPosition(particle->getPosition() + osg::Vec3(0,mRangeY,0)); + if (particle->getPosition().y() > mWrapRange.y() / 2.0) + particle->setPosition(particle->getPosition() - osg::Vec3(0,mWrapRange.y(),0)); + else if (particle->getPosition().y() < -mWrapRange.y() / 2.0) + particle->setPosition(particle->getPosition() + osg::Vec3(0,mWrapRange.y(),0)); particle->setPosition(toLocal.preMult(particle->getPosition())); } @@ -1401,8 +1401,7 @@ public: } protected: - float mRangeX, mRangeY; - + osg::Vec3 mWrapRange; }; void SkyManager::createRain() @@ -1413,7 +1412,7 @@ void SkyManager::createRain() mRainNode = new osg::Group; mRainParticleSystem = new osgParticle::ParticleSystem; - mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(RAIN_WIDTH,RAIN_WIDTH)); + mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(osg::Vec3(RAIN_WIDTH,RAIN_WIDTH,RAIN_HEIGHT))); mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED); mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0)); @@ -1635,25 +1634,17 @@ void SkyManager::setWeather(const WeatherResult& weather) SceneUtil::FindByClassVisitor findEmitterVisitor(std::string("Emitter")); mParticleEffect->accept(findEmitterVisitor); - float rangeX = RAIN_WIDTH; - float rangeY = RAIN_WIDTH; + for (unsigned int i = 0; i < findEmitterVisitor.mFoundNodes.size(); i++) + { + NifOsg::Emitter *emitter = (NifOsg::Emitter *) findEmitterVisitor.mFoundNodes[i]; + NifOsg::ParticleSystem *ps = (NifOsg::ParticleSystem *) emitter->getParticleSystem(); - if (findEmitterVisitor.mFoundNode) - { - osgParticle::Placer *placer = ((NifOsg::Emitter *) findEmitterVisitor.mFoundNode)->getPlacer(); + osg::BoundingBox box = ps->getBoundingBox(); - if (placer && strcmp(placer->className(),"BoxPlacer") == 0) - { - rangeX = ((osgParticle::BoxPlacer *) placer)->getXRange().maximum; - rangeY = ((osgParticle::BoxPlacer *) placer)->getYRange().maximum; - } - } + osg::Vec3 wrapRange = osg::Vec3(box.xMax() - box.xMin(),box.yMax() - box.yMin(),box.zMax() - box.zMin()); - SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem")); - mParticleEffect->accept(findPSVisitor); - - if (findPSVisitor.mFoundNode) - ((osgParticle::ParticleSystem *) findPSVisitor.mFoundNode)->setDrawCallback(new WeatherParticleDrawCallback(rangeX,rangeY)); + ps->setDrawCallback(new WeatherParticleDrawCallback(wrapRange)); + } } } diff --git a/components/sceneutil/visitor.cpp b/components/sceneutil/visitor.cpp index 202e6373e..2f6123e34 100644 --- a/components/sceneutil/visitor.cpp +++ b/components/sceneutil/visitor.cpp @@ -22,9 +22,9 @@ namespace SceneUtil void FindByClassVisitor::apply(osg::Node &node) { if (Misc::StringUtils::ciEqual(node.className(), mNameToFind)) - mFoundNode = &node; - else - traverse(node); + mFoundNodes.push_back(&node); + + traverse(node); } void FindByNameVisitor::apply(osg::Group &group) diff --git a/components/sceneutil/visitor.hpp b/components/sceneutil/visitor.hpp index 973f44646..265fd6d02 100644 --- a/components/sceneutil/visitor.hpp +++ b/components/sceneutil/visitor.hpp @@ -35,14 +35,13 @@ namespace SceneUtil FindByClassVisitor(const std::string& nameToFind) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) , mNameToFind(nameToFind) - , mFoundNode(NULL) { } virtual void apply(osg::Node &node); std::string mNameToFind; - osg::Node* mFoundNode; + std::vector mFoundNodes; }; // Disable freezeOnCull for all visited particlesystems From 65977b910e017bbe4007fc1c71d47201c3bb02f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Thu, 12 Oct 2017 15:28:54 +0200 Subject: [PATCH 13/35] wrap weather around in all directions --- apps/openmw/mwrender/sky.cpp | 86 +++++++++++++++++----------------- components/nifosg/particle.cpp | 5 -- components/nifosg/particle.hpp | 1 - 3 files changed, 44 insertions(+), 48 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index fb3e477bb..eaa93ab88 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -39,7 +41,6 @@ #include #include #include -#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -47,12 +48,8 @@ #include "vismask.hpp" #include "renderbin.hpp" -#define RAIN_WIDTH 600.0 -#define RAIN_HEIGHT 600.0 - namespace { - osg::ref_ptr createAlphaTrackingUnlitMaterial() { osg::ref_ptr mat = new osg::Material; @@ -1344,60 +1341,69 @@ protected: class WeatherParticleDrawCallback : public osg::Drawable::DrawCallback { public: - WeatherParticleDrawCallback(osg::Vec3 wrapRange) : osg::Drawable::DrawCallback() + WeatherParticleDrawCallback(osg::Vec3 &wrapRange) : osg::Drawable::DrawCallback() { mWrapRange = wrapRange; } virtual void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable *drawable) const { + osgParticle::ParticleSystem *ps = (osgParticle::ParticleSystem *) drawable; + + osgParticle::ParticleSystem::ScopedReadLock *lock = new osgParticle::ParticleSystem::ScopedReadLock(*ps->getReadWriteMutex()); + osg::Vec3 cameraPos = renderInfo.getCurrentCamera()->getInverseViewMatrix().getTrans(); osg::Vec3 cameraOffset = osg::Vec3( fmod(cameraPos.x(), mWrapRange.x()), fmod(cameraPos.y(), mWrapRange.y()), - 0.0); + fmod(cameraPos.z(), mWrapRange.z())); std::vector positionBackups; osg::Matrix toWorld, toLocal; - toWorld.makeIdentity(); - toLocal.makeIdentity(); - std::vector worldMatrices = drawable->getWorldMatrices(); if (!worldMatrices.empty()) - { - toWorld = worldMatrices[0]; - toLocal.invert(toWorld); - } + { + toWorld = worldMatrices[0]; + toLocal.invert(toWorld); + } for (int i = 0; i < ps->numParticles(); i++) - { - osgParticle::Particle *particle = ps->getParticle(i); - positionBackups.push_back(particle->getPosition()); - particle->setPosition(toWorld.preMult(particle->getPosition())); - particle->setPosition(particle->getPosition() - cameraOffset); + { + osgParticle::Particle *particle = ps->getParticle(i); + positionBackups.push_back(particle->getPosition()); + particle->setPosition(toWorld.preMult(particle->getPosition())); + particle->setPosition(particle->getPosition() - cameraOffset); - if (particle->getPosition().x() > mWrapRange.x() / 2.0) // wrap-around effect - particle->setPosition(particle->getPosition() - osg::Vec3(mWrapRange.x(),0,0)); - else if (particle->getPosition().x() < -mWrapRange.x() / 2.0) - particle->setPosition(particle->getPosition() + osg::Vec3(mWrapRange.x(),0,0)); + for (int j = 0; j < 3; j++) // wrap-around effect in all 3 directions + { + osg::Vec3 newPosition = particle->getPosition(); - if (particle->getPosition().y() > mWrapRange.y() / 2.0) - particle->setPosition(particle->getPosition() - osg::Vec3(0,mWrapRange.y(),0)); - else if (particle->getPosition().y() < -mWrapRange.y() / 2.0) - particle->setPosition(particle->getPosition() + osg::Vec3(0,mWrapRange.y(),0)); + if (particle->getPosition()[j] > mWrapRange[j] / 2.0) + newPosition[j] -= mWrapRange[j]; + else if (particle->getPosition()[j] < -mWrapRange[j] / 2.0) + newPosition[j] += mWrapRange[j]; - particle->setPosition(toLocal.preMult(particle->getPosition())); + particle->setPosition(newPosition); } + particle->setPosition(toLocal.preMult(particle->getPosition())); + } + + delete lock; // unlock the mutex as ps will try to lock it in the following command + ps->drawImplementation(renderInfo); + lock = new osgParticle::ParticleSystem::ScopedReadLock(*ps->getReadWriteMutex()); + for (int i = 0; i < ps->numParticles(); i++) // restore positions ps->getParticle(i)->setPosition(positionBackups[i]); + + delete lock; } protected: @@ -1412,7 +1418,8 @@ void SkyManager::createRain() mRainNode = new osg::Group; mRainParticleSystem = new osgParticle::ParticleSystem; - mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(osg::Vec3(RAIN_WIDTH,RAIN_WIDTH,RAIN_HEIGHT))); + osg::Vec3 rainRange = osg::Vec3(600,600,600); + mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(rainRange)); mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED); mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0)); @@ -1440,8 +1447,8 @@ void SkyManager::createRain() emitter->setParticleSystem(mRainParticleSystem); osg::ref_ptr placer (new osgParticle::BoxPlacer); - placer->setXRange(-RAIN_WIDTH / 2, RAIN_WIDTH / 2); // Rain_Diameter - placer->setYRange(-RAIN_WIDTH / 2, RAIN_WIDTH / 2); + placer->setXRange(-rainRange.x() / 2, rainRange.x() / 2); // Rain_Diameter + placer->setYRange(-rainRange.y() / 2, rainRange.y() / 2); placer->setZRange(300, 300); emitter->setPlacer(placer); @@ -1631,19 +1638,14 @@ void SkyManager::setWeather(const WeatherResult& weather) SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor; mParticleEffect->accept(disableFreezeOnCullVisitor); - SceneUtil::FindByClassVisitor findEmitterVisitor(std::string("Emitter")); - mParticleEffect->accept(findEmitterVisitor); + SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem")); + mParticleEffect->accept(findPSVisitor); - for (unsigned int i = 0; i < findEmitterVisitor.mFoundNodes.size(); i++) + for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); i++) { - NifOsg::Emitter *emitter = (NifOsg::Emitter *) findEmitterVisitor.mFoundNodes[i]; - NifOsg::ParticleSystem *ps = (NifOsg::ParticleSystem *) emitter->getParticleSystem(); - - osg::BoundingBox box = ps->getBoundingBox(); - - osg::Vec3 wrapRange = osg::Vec3(box.xMax() - box.xMin(),box.yMax() - box.yMin(),box.zMax() - box.zMin()); - - ps->setDrawCallback(new WeatherParticleDrawCallback(wrapRange)); + osgParticle::ParticleSystem *ps = static_cast(findPSVisitor.mFoundNodes[i]); + osg::Vec3 weatherRange = osg::Vec3(1024,1024,800); + ps->setDrawCallback(new WeatherParticleDrawCallback(weatherRange)); } } } diff --git a/components/nifosg/particle.cpp b/components/nifosg/particle.cpp index 547b71034..62360b9d6 100644 --- a/components/nifosg/particle.cpp +++ b/components/nifosg/particle.cpp @@ -250,11 +250,6 @@ void Emitter::setPlacer(osgParticle::Placer *placer) mPlacer = placer; } -osgParticle::Placer *Emitter::getPlacer() -{ - return mPlacer; -} - void Emitter::setCounter(osgParticle::Counter *counter) { mCounter = counter; diff --git a/components/nifosg/particle.hpp b/components/nifosg/particle.hpp index df93d5ced..7a2377f9d 100644 --- a/components/nifosg/particle.hpp +++ b/components/nifosg/particle.hpp @@ -225,7 +225,6 @@ namespace NifOsg void setShooter(osgParticle::Shooter* shooter); void setPlacer(osgParticle::Placer* placer); - osgParticle::Placer *getPlacer(); void setCounter(osgParticle::Counter* counter); private: From af6eeddbe551ac8ba7eb58f2be5085900908bc1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Sat, 14 Oct 2017 18:45:29 +0200 Subject: [PATCH 14/35] use operator instead of drawcallback --- apps/openmw/mwrender/renderingmanager.cpp | 1 + apps/openmw/mwrender/sky.cpp | 122 +++++++++++++--------- apps/openmw/mwrender/sky.hpp | 9 ++ 3 files changed, 81 insertions(+), 51 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 3826fd5f6..aa7b35b44 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -256,6 +256,7 @@ namespace MWRender mRootNode->getOrCreateStateSet()->addUniform(mUniformRainIntensity); mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager())); + mSky->setCamera(mViewer->getCamera()); source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index eaa93ab88..1338a127c 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -18,8 +18,6 @@ #include #include -#include - #include #include #include @@ -27,6 +25,9 @@ #include #include +#include +#include + #include #include @@ -1094,6 +1095,7 @@ private: SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager) : mSceneManager(sceneManager) + , mCamera(NULL) , mAtmosphereNightRoll(0.f) , mCreated(false) , mIsStorm(false) @@ -1338,76 +1340,85 @@ protected: osg::Uniform* mRainIntensityUniform; }; -class WeatherParticleDrawCallback : public osg::Drawable::DrawCallback +void SkyManager::setCamera(osg::Camera *camera) +{ + mCamera = camera; +} + +class WrapAroundOperator : public osgParticle::Operator { public: - WeatherParticleDrawCallback(osg::Vec3 &wrapRange) : osg::Drawable::DrawCallback() + WrapAroundOperator(osg::Camera *camera, const osg::Vec3 &wrapRange): osgParticle::Operator() { + mCamera = camera; mWrapRange = wrapRange; + mHalfWrapRange = mWrapRange / 2.0; + mPreviousCameraPosition = getCameraPosition(); } - virtual void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable *drawable) const + virtual osg::Object *cloneType() const override { + return NULL; + } - osgParticle::ParticleSystem *ps = (osgParticle::ParticleSystem *) drawable; + virtual osg::Object *clone(const osg::CopyOp &op) const override + { + return NULL; + } - osgParticle::ParticleSystem::ScopedReadLock *lock = new osgParticle::ParticleSystem::ScopedReadLock(*ps->getReadWriteMutex()); + virtual void operate(osgParticle::Particle *P, double dt) override + { + } - osg::Vec3 cameraPos = renderInfo.getCurrentCamera()->getInverseViewMatrix().getTrans(); - - osg::Vec3 cameraOffset = osg::Vec3( - fmod(cameraPos.x(), mWrapRange.x()), - fmod(cameraPos.y(), mWrapRange.y()), - fmod(cameraPos.z(), mWrapRange.z())); - - std::vector positionBackups; + virtual void operateParticles(osgParticle::ParticleSystem *ps, double dt) override + { + osg::Vec3 position = getCameraPosition(); + osg::Vec3 positionDifference = position - mPreviousCameraPosition; osg::Matrix toWorld, toLocal; - std::vector worldMatrices = drawable->getWorldMatrices(); - + std::vector worldMatrices = ps->getWorldMatrices(); + if (!worldMatrices.empty()) { toWorld = worldMatrices[0]; toLocal.invert(toWorld); } - for (int i = 0; i < ps->numParticles(); i++) + for (int i = 0; i < ps->numParticles(); ++i) { - osgParticle::Particle *particle = ps->getParticle(i); - positionBackups.push_back(particle->getPosition()); - particle->setPosition(toWorld.preMult(particle->getPosition())); - particle->setPosition(particle->getPosition() - cameraOffset); + osgParticle::Particle *p = ps->getParticle(i); + p->setPosition(toWorld.preMult(p->getPosition())); + p->setPosition(p->getPosition() - positionDifference); - for (int j = 0; j < 3; j++) // wrap-around effect in all 3 directions - { - osg::Vec3 newPosition = particle->getPosition(); + for (int j = 0; j < 3; ++j) // wrap-around in all 3 dimensions + { + osg::Vec3 pos = p->getPosition(); - if (particle->getPosition()[j] > mWrapRange[j] / 2.0) - newPosition[j] -= mWrapRange[j]; - else if (particle->getPosition()[j] < -mWrapRange[j] / 2.0) - newPosition[j] += mWrapRange[j]; + if (pos[j] < -mHalfWrapRange[j]) + pos[j] = mHalfWrapRange[j] + fmod(pos[j] - mHalfWrapRange[j],mWrapRange[j]); + else if (pos[j] > mHalfWrapRange[j]) + pos[j] = fmod(pos[j] + mHalfWrapRange[j],mWrapRange[j]) - mHalfWrapRange[j]; - particle->setPosition(newPosition); - } + p->setPosition(pos); + } - particle->setPosition(toLocal.preMult(particle->getPosition())); + p->setPosition(toLocal.preMult(p->getPosition())); } - delete lock; // unlock the mutex as ps will try to lock it in the following command - - ps->drawImplementation(renderInfo); - - lock = new osgParticle::ParticleSystem::ScopedReadLock(*ps->getReadWriteMutex()); - - for (int i = 0; i < ps->numParticles(); i++) // restore positions - ps->getParticle(i)->setPosition(positionBackups[i]); - - delete lock; + mPreviousCameraPosition = position; } protected: + osg::Camera *mCamera; + osg::Vec3 mPreviousCameraPosition; osg::Vec3 mWrapRange; + osg::Vec3 mHalfWrapRange; + + osg::Vec3 getCameraPosition() + { + return mCamera->getInverseViewMatrix().getTrans(); + } }; void SkyManager::createRain() @@ -1419,12 +1430,10 @@ void SkyManager::createRain() mRainParticleSystem = new osgParticle::ParticleSystem; osg::Vec3 rainRange = osg::Vec3(600,600,600); - mRainParticleSystem->setDrawCallback(new WeatherParticleDrawCallback(rainRange)); mRainParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED); mRainParticleSystem->setAlignVectorX(osg::Vec3f(0.1,0,0)); mRainParticleSystem->setAlignVectorY(osg::Vec3f(0,0,1)); - mRainParticleSystem->setCullingActive(false); osg::ref_ptr stateset (mRainParticleSystem->getOrCreateStateSet()); @@ -1463,6 +1472,11 @@ void SkyManager::createRain() osg::ref_ptr updater (new osgParticle::ParticleSystemUpdater); updater->addParticleSystem(mRainParticleSystem); + osg::ref_ptr program (new osgParticle::ModularProgram); + program->addOperator(new WrapAroundOperator(mCamera,rainRange)); + program->setParticleSystem(mRainParticleSystem); + mRainNode->addChild(program); + mRainNode->addChild(emitter); mRainNode->addChild(mRainParticleSystem); mRainNode->addChild(updater); @@ -1638,14 +1652,20 @@ void SkyManager::setWeather(const WeatherResult& weather) SceneUtil::DisableFreezeOnCullVisitor disableFreezeOnCullVisitor; mParticleEffect->accept(disableFreezeOnCullVisitor); - SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem")); - mParticleEffect->accept(findPSVisitor); - - for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); i++) + if (!weather.mIsStorm) { - osgParticle::ParticleSystem *ps = static_cast(findPSVisitor.mFoundNodes[i]); - osg::Vec3 weatherRange = osg::Vec3(1024,1024,800); - ps->setDrawCallback(new WeatherParticleDrawCallback(weatherRange)); + SceneUtil::FindByClassVisitor findPSVisitor(std::string("ParticleSystem")); + mParticleEffect->accept(findPSVisitor); + + for (unsigned int i = 0; i < findPSVisitor.mFoundNodes.size(); ++i) + { + osgParticle::ParticleSystem *ps = static_cast(findPSVisitor.mFoundNodes[i]); + + osg::ref_ptr program (new osgParticle::ModularProgram); + program->addOperator(new WrapAroundOperator(mCamera,osg::Vec3(1024,1024,800))); + program->setParticleSystem(ps); + mParticleNode->addChild(program); + } } } } diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 59a8ddc4e..097405b24 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -9,6 +9,11 @@ #include #include +namespace osg +{ + class Camera; +} + namespace osg { class Group; @@ -161,6 +166,8 @@ namespace MWRender void listAssetsToPreload(std::vector& models, std::vector& textures); + void setCamera(osg::Camera *camera); + private: void create(); ///< no need to call this, automatically done on first enable() @@ -171,6 +178,8 @@ namespace MWRender Resource::SceneManager* mSceneManager; + osg::Camera* mCamera; + osg::ref_ptr mRootNode; osg::ref_ptr mEarlyRenderBinRoot; From 28ff677337f9e6231a6be62cc4ec79aca6d3dd73 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 15 Oct 2017 00:07:46 +0100 Subject: [PATCH 15/35] Save 'data=...' lines correctly when exiting the wizard --- components/config/gamesettings.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index a897806c2..a1b5cc99e 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -152,9 +152,31 @@ bool Config::GameSettings::writeFile(QTextStream &stream) while (i.hasPrevious()) { i.previous(); + // 'data=...' lines need quotes and ampersands escaping to match how boost::filesystem::path uses boost::io::quoted + if (i.key() == QLatin1String("data")) + { + stream << i.key() << "="; + + // The following is based on boost::io::detail::quoted_manip.hpp, but calling this function did not work as there are too may QStrings involved + QChar delim = '\"'; + QChar escape = '&'; + QString string = i.value(); + + stream << delim; + for (QString::const_iterator it = string.begin(); it != string.end(); ++it) + { + if (*it == delim || *it == escape) + stream << escape; + stream << *it; + } + stream << delim; + + stream << '\n'; + continue; + } + // Quote paths with spaces - if (i.key() == QLatin1String("data") - || i.key() == QLatin1String("data-local") + if (i.key() == QLatin1String("data-local") || i.key() == QLatin1String("resources")) { if (i.value().contains(QChar(' '))) From 7329e6a9ef528c086f5169e570d46ed5567224f7 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 15 Oct 2017 01:59:21 +0100 Subject: [PATCH 16/35] Load 'data=...' lines correctly when starting the wizard or launcher, and save them correctly when exiting the launcher. --- components/config/gamesettings.cpp | 51 ++++++++++++++++++++--- components/files/configurationmanager.cpp | 2 - 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index a1b5cc99e..62aa034ee 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -55,7 +55,6 @@ void Config::GameSettings::validatePaths() for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { QString path = QString::fromUtf8(it->string().c_str()); - path.remove(QChar('\"')); QDir dir(path); if (dir.exists()) @@ -64,6 +63,11 @@ void Config::GameSettings::validatePaths() // Do the same for data-local QString local = mSettings.value(QString("data-local")); + if (local.at(0) == QChar('\"')) + { + local.remove(0, 1); + local.chop(1); + } if (local.isEmpty()) return; @@ -76,7 +80,6 @@ void Config::GameSettings::validatePaths() if (!dataDirs.empty()) { QString path = QString::fromUtf8(dataDirs.front().string().c_str()); - path.remove(QChar('\"')); QDir dir(path); if (dir.exists()) @@ -120,6 +123,27 @@ bool Config::GameSettings::readFile(QTextStream &stream, QMap // Don't remove existing data entries if (key != QLatin1String("data")) settings.remove(key); + else + { + // 'data=...' line, so needs processing to deal with ampersands and quotes + QChar delim = '\"'; + QChar escape = '&'; + + if (value.at(0) == delim) + { + QString valueOriginal = value; + value = ""; + + for (QString::const_iterator it = valueOriginal.begin() + 1; it != valueOriginal.end(); ++it) + { + if (*it == escape) + ++it; + else if (*it == delim) + break; + value += *it; + } + } + } QStringList values = cache.values(key); values.append(settings.values(key)); @@ -157,7 +181,7 @@ bool Config::GameSettings::writeFile(QTextStream &stream) { stream << i.key() << "="; - // The following is based on boost::io::detail::quoted_manip.hpp, but calling this function did not work as there are too may QStrings involved + // The following is based on boost::io::detail::quoted_manip.hpp, but calling those functions did not work as there are too may QStrings involved QChar delim = '\"'; QChar escape = '&'; QString string = i.value(); @@ -380,9 +404,26 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) { it.previous(); + if (it.key() == QLatin1String("data")) + { + settingLine = it.key() + "="; + + // The following is based on boost::io::detail::quoted_manip.hpp, but calling those functions did not work as there are too may QStrings involved + QChar delim = '\"'; + QChar escape = '&'; + QString string = it.value(); + + settingLine += delim; + for (QString::const_iterator iter = string.begin(); iter != string.end(); ++iter) + { + if (*iter == delim || *iter == escape) + settingLine += escape; + settingLine += *iter; + } + settingLine += delim; + } // Quote paths with spaces - if ((it.key() == QLatin1String("data") - || it.key() == QLatin1String("data-local") + else if ((it.key() == QLatin1String("data-local") || it.key() == QLatin1String("resources")) && it.value().contains(QChar(' '))) { QString stripped = it.value(); diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index 5316255ad..7c3956a29 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -75,8 +75,6 @@ void ConfigurationManager::processPaths(Files::PathContainer& dataDirs, bool cre for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) { path = it->string(); - boost::erase_all(path, "\""); - *it = boost::filesystem::path(path); // Check if path contains a token if (!path.empty() && *path.begin() == '?') From 49dbb4a9ca16ebb3d9f6d585b6a3d975d8608313 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Sun, 15 Oct 2017 02:05:22 +0100 Subject: [PATCH 17/35] Add a third copy of a comment where I felt clarification was missing --- components/config/gamesettings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/components/config/gamesettings.cpp b/components/config/gamesettings.cpp index 62aa034ee..0ea28dceb 100644 --- a/components/config/gamesettings.cpp +++ b/components/config/gamesettings.cpp @@ -126,6 +126,7 @@ bool Config::GameSettings::readFile(QTextStream &stream, QMap else { // 'data=...' line, so needs processing to deal with ampersands and quotes + // The following is based on boost::io::detail::quoted_manip.hpp, but calling those functions did not work as there are too may QStrings involved QChar delim = '\"'; QChar escape = '&'; From 8f255a6b726cc92c45690c313e0065df7723ec9d Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 15 Oct 2017 11:03:02 +0400 Subject: [PATCH 18/35] Handle Trespassing crime differently from Theft (bug #4158) --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 2c7b6a500..dfbcf0ea2 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1123,6 +1123,10 @@ namespace MWMechanics if (playerFollowers.find(*it) != playerFollowers.end()) continue; + // NPC will complain about theft even if he will do nothing about it + if (type == OT_Theft || type == OT_Pickpocket) + MWBase::Environment::get().getDialogueManager()->say(*it, "thief"); + crimeSeen = true; } } @@ -1243,9 +1247,7 @@ namespace MWMechanics { reported = true; - if (type == OT_Theft || type == OT_Pickpocket) - MWBase::Environment::get().getDialogueManager()->say(*it, "thief"); - else if (type == OT_Trespassing) + if (type == OT_Trespassing) MWBase::Environment::get().getDialogueManager()->say(*it, "intruder"); } From 4c174ecd12b98ec3d31fb00ee28434385f2a679b Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 15 Oct 2017 17:06:34 +0200 Subject: [PATCH 19/35] Merge changes to coverity scan script --- .travis.yml | 4 ++-- extern/osg-ffmpeg-videoplayer/License.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6606b0290..d173ef6f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,8 +41,8 @@ addons: project: name: "OpenMW/openmw" description: "" - notification_email: scrawl@baseoftrash.de - build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE" + notification_email: 720642+scrawl@users.noreply.github.com + build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE -DBUILD_OPENCS=FALSE -DBUILD_BSATOOL=FALSE -DBUILD_ESMTOOL=FALSE -DBUILD_MWINIIMPORTER=FALSE -DBUILD_LAUNCHER=FALSE" build_command: "make -j3" branch_pattern: coverity_scan matrix: diff --git a/extern/osg-ffmpeg-videoplayer/License.txt b/extern/osg-ffmpeg-videoplayer/License.txt index 49f534065..bb70d7d37 100644 --- a/extern/osg-ffmpeg-videoplayer/License.txt +++ b/extern/osg-ffmpeg-videoplayer/License.txt @@ -1,4 +1,4 @@ -Copyright (c) 2014 Jannik Heller , Chris Robinson +Copyright (c) 2014 scrawl, Chris Robinson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: From 50d7eb8e5470d02bec3224ec9b8df2ab1a35f29c Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 15 Oct 2017 17:01:18 +0200 Subject: [PATCH 20/35] Fix crash when adding a NULL object to the cache --- components/resource/bulletshapemanager.cpp | 6 ++---- components/resource/multiobjectcache.cpp | 5 +++++ components/resource/objectcache.cpp | 5 +++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/components/resource/bulletshapemanager.cpp b/components/resource/bulletshapemanager.cpp index c1a7eb8f3..53b08b8be 100644 --- a/components/resource/bulletshapemanager.cpp +++ b/components/resource/bulletshapemanager.cpp @@ -141,10 +141,7 @@ osg::ref_ptr BulletShapeManager::getShape(const std::string & node->accept(visitor); shape = visitor.getShape(); if (!shape) - { - mCache->addEntryToObjectCache(normalized, NULL); return osg::ref_ptr(); - } } mCache->addEntryToObjectCache(normalized, shape); @@ -158,7 +155,8 @@ osg::ref_ptr BulletShapeManager::cacheInstance(const std::s mVFS->normalizeFilename(normalized); osg::ref_ptr instance = createInstance(normalized); - mInstanceCache->addEntryToObjectCache(normalized, instance.get()); + if (instance) + mInstanceCache->addEntryToObjectCache(normalized, instance.get()); return instance; } diff --git a/components/resource/multiobjectcache.cpp b/components/resource/multiobjectcache.cpp index 266139f3c..d6639d3ae 100644 --- a/components/resource/multiobjectcache.cpp +++ b/components/resource/multiobjectcache.cpp @@ -51,6 +51,11 @@ namespace Resource void MultiObjectCache::addEntryToObjectCache(const std::string &filename, osg::Object *object) { + if (!object) + { + OSG_ALWAYS << " trying to add NULL object to cache for " << filename << std::endl; + return; + } OpenThreads::ScopedLock lock(_objectCacheMutex); _objectCache.insert(std::make_pair(filename, object)); } diff --git a/components/resource/objectcache.cpp b/components/resource/objectcache.cpp index de0fa7a40..e8c082f91 100644 --- a/components/resource/objectcache.cpp +++ b/components/resource/objectcache.cpp @@ -34,6 +34,11 @@ ObjectCache::~ObjectCache() void ObjectCache::addEntryToObjectCache(const std::string& filename, osg::Object* object, double timestamp) { + if (!object) + { + OSG_ALWAYS << " trying to add NULL object to cache for " << filename << std::endl; + return; + } OpenThreads::ScopedLock lock(_objectCacheMutex); _objectCache[filename]=ObjectTimeStampPair(object,timestamp); } From 624046c5581ba21c0da55e582e9b92cc8730a175 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 15 Oct 2017 17:01:57 +0200 Subject: [PATCH 21/35] Fix unused event handler --- apps/openmw/mwgui/savegamedialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index 6a290bef1..43e511144 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -84,6 +84,7 @@ namespace MWGui dialog->eventOkClicked.clear(); dialog->eventOkClicked += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteSlotConfirmed); dialog->eventCancelClicked.clear(); + dialog->eventCancelClicked += MyGUI::newDelegate(this, &SaveGameDialog::onDeleteSlotCancel); } void SaveGameDialog::onDeleteSlotConfirmed() From 64d02f577e83f9bc3405c9a4ba25bf9d6d016d64 Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 15 Oct 2017 17:02:36 +0200 Subject: [PATCH 22/35] Fix missing null check --- apps/openmw/mwphysics/physicssystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 887189a85..7f880d716 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -1046,7 +1046,7 @@ namespace MWPhysics bool PhysicsSystem::isOnGround(const MWWorld::Ptr &actor) { Actor* physactor = getActor(actor); - return physactor->getOnGround(); + return physactor && physactor->getOnGround(); } bool PhysicsSystem::canMoveToWaterSurface(const MWWorld::ConstPtr &actor, const float waterlevel) From 03554b2f4bfedd27b9dca83c2147f299098a081b Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 15 Oct 2017 17:03:11 +0200 Subject: [PATCH 23/35] Fix some style issues flagged by cppcheck --- apps/openmw/mwgui/dialogue.hpp | 2 -- apps/openmw/mwgui/hud.cpp | 1 - apps/openmw/mwgui/hud.hpp | 1 - apps/openmw/mwgui/spellbuyingwindow.hpp | 2 +- apps/openmw/mwgui/statswindow.cpp | 2 +- apps/openmw/mwmechanics/aiwander.cpp | 6 ++---- apps/openmw/mwmechanics/combat.cpp | 20 -------------------- apps/openmw/mwmechanics/combat.hpp | 4 ---- apps/openmw/mwphysics/physicssystem.cpp | 2 -- components/nifbullet/bulletnifloader.cpp | 2 +- components/nifbullet/bulletnifloader.hpp | 2 +- components/nifosg/nifloader.cpp | 4 ++-- components/resource/bulletshapemanager.cpp | 12 +++++------- components/sceneutil/util.cpp | 9 --------- components/sceneutil/util.hpp | 2 -- components/sceneutil/workqueue.cpp | 1 + 16 files changed, 14 insertions(+), 58 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.hpp b/apps/openmw/mwgui/dialogue.hpp index 97a0e8b37..5e362e9b5 100644 --- a/apps/openmw/mwgui/dialogue.hpp +++ b/apps/openmw/mwgui/dialogue.hpp @@ -155,8 +155,6 @@ namespace MWGui void restock(); void deleteLater(); - bool mEnabled; - bool mIsCompanion; std::list mKeywords; diff --git a/apps/openmw/mwgui/hud.cpp b/apps/openmw/mwgui/hud.cpp index 1db2691f4..23eb499de 100644 --- a/apps/openmw/mwgui/hud.cpp +++ b/apps/openmw/mwgui/hud.cpp @@ -80,7 +80,6 @@ namespace MWGui , mSpellStatus(NULL) , mEffectBox(NULL) , mMinimap(NULL) - , mCompass(NULL) , mCrosshair(NULL) , mCellNameBox(NULL) , mDrowningFrame(NULL) diff --git a/apps/openmw/mwgui/hud.hpp b/apps/openmw/mwgui/hud.hpp index 3542f3ebf..73428c034 100644 --- a/apps/openmw/mwgui/hud.hpp +++ b/apps/openmw/mwgui/hud.hpp @@ -69,7 +69,6 @@ namespace MWGui MyGUI::Widget *mEffectBox, *mMinimapBox; MyGUI::Button* mMinimapButton; MyGUI::ScrollView* mMinimap; - MyGUI::ImageBox* mCompass; MyGUI::ImageBox* mCrosshair; MyGUI::TextBox* mCellNameBox; MyGUI::TextBox* mWeaponSpellBox; diff --git a/apps/openmw/mwgui/spellbuyingwindow.hpp b/apps/openmw/mwgui/spellbuyingwindow.hpp index 649aab3f2..3414c1b94 100644 --- a/apps/openmw/mwgui/spellbuyingwindow.hpp +++ b/apps/openmw/mwgui/spellbuyingwindow.hpp @@ -46,7 +46,7 @@ namespace MWGui void onMouseWheel(MyGUI::Widget* _sender, int _rel); void addSpell(const ESM::Spell& spell); void clearSpells(); - int mLastPos,mCurrentY; + int mCurrentY; static const int sLineHeight; diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index bf505b00f..d3d487579 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -105,7 +105,7 @@ namespace MWGui std::stringstream out; out << val << "/" << max; - setText(tname, out.str().c_str()); + setText(tname, out.str()); pt->setProgressRange(std::max(0, max)); pt->setProgressPosition(std::max(0, val)); diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 7f412b4d2..255874d88 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -451,11 +451,10 @@ namespace MWMechanics // Check if an idle actor is too close to a door - if so start walking storage.mDoorCheckDuration += duration; - static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); - if (storage.mDoorCheckDuration >= DOOR_CHECK_INTERVAL) { storage.mDoorCheckDuration = 0; // restart timer + static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); if (mDistance && // actor is not intended to be stationary proximityToDoor(actor, distance*1.6f)) { @@ -531,11 +530,10 @@ namespace MWMechanics void AiWander::evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage, float duration, ESM::Position& pos) { - static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); - if (mObstacleCheck.isEvading()) { // first check if we're walking into a door + static float distance = MWBase::Environment::get().getWorld()->getMaxActivationDistance(); if (proximityToDoor(actor, distance)) { // remove allowed points then select another random destination diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index 54ad75135..13cd4232d 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -424,26 +424,6 @@ namespace MWMechanics } } - bool isEnvironmentCompatible(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim) - { - const MWWorld::Class& attackerClass = attacker.getClass(); - MWBase::World* world = MWBase::Environment::get().getWorld(); - - // If attacker is fish, victim must be in water - if (attackerClass.isPureWaterCreature(attacker)) - { - return world->isWading(victim); - } - - // If attacker can't swim, victim must not be in water - if (!attackerClass.canSwim(attacker)) - { - return !world->isSwimming(victim); - } - - return true; - } - float getFightDistanceBias(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2) { osg::Vec3f pos1 (actor1.getRefData().getPosition().asVec3()); diff --git a/apps/openmw/mwmechanics/combat.hpp b/apps/openmw/mwmechanics/combat.hpp index 12961dc4b..8b93ca204 100644 --- a/apps/openmw/mwmechanics/combat.hpp +++ b/apps/openmw/mwmechanics/combat.hpp @@ -39,10 +39,6 @@ void getHandToHandDamage (const MWWorld::Ptr& attacker, const MWWorld::Ptr& vict /// Apply the fatigue loss incurred by attacking with the given weapon (weapon may be empty = hand-to-hand) void applyFatigueLoss(const MWWorld::Ptr& attacker, const MWWorld::Ptr& weapon, float attackStrength); -/// Can attacker operate in victim's environment? -/// e.g. If attacker is a fish, is victim in water? Or, if attacker can't swim, is victim on land? -bool isEnvironmentCompatible(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim); - float getFightDistanceBias(const MWWorld::Ptr& actor1, const MWWorld::Ptr& actor2); } diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 7f880d716..34932e360 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -702,8 +702,6 @@ namespace MWPhysics const char* env = getenv("OPENMW_PHYSICS_FPS"); if (env) { - std::string str(env); - float physFramerate = std::atof(env); if (physFramerate > 0) { diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 3865b17a5..9e9fe3759 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -49,7 +49,7 @@ BulletNifLoader::~BulletNifLoader() { } -osg::ref_ptr BulletNifLoader::load(const Nif::NIFFilePtr nif) +osg::ref_ptr BulletNifLoader::load(const Nif::NIFFilePtr& nif) { mShape = new Resource::BulletShape; diff --git a/components/nifbullet/bulletnifloader.hpp b/components/nifbullet/bulletnifloader.hpp index a30bf8fdf..fff51933f 100644 --- a/components/nifbullet/bulletnifloader.hpp +++ b/components/nifbullet/bulletnifloader.hpp @@ -50,7 +50,7 @@ public: abort(); } - osg::ref_ptr load(const Nif::NIFFilePtr file); + osg::ref_ptr load(const Nif::NIFFilePtr& file); private: bool findBoundingBox(const Nif::Node* node, int flags = 0); diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 8810f171a..a3b81338e 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -1191,8 +1191,8 @@ namespace NifOsg if (pixelData->mipmaps.empty()) return NULL; - unsigned int width = 0; - unsigned int height = 0; + int width = 0; + int height = 0; std::vector mipmapVector; for (unsigned int i=0; imipmaps.size()-3; ++i) diff --git a/components/resource/bulletshapemanager.cpp b/components/resource/bulletshapemanager.cpp index 53b08b8be..a3d09311a 100644 --- a/components/resource/bulletshapemanager.cpp +++ b/components/resource/bulletshapemanager.cpp @@ -63,7 +63,7 @@ class NodeToShapeVisitor : public osg::NodeVisitor public: NodeToShapeVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) - , mTriangleMesh(NULL) + , mTriangleMesh(nullptr) { } @@ -71,11 +71,11 @@ public: virtual void apply(osg::Drawable &drawable) { if (!mTriangleMesh) - mTriangleMesh = new btTriangleMesh; + mTriangleMesh.reset(new btTriangleMesh); osg::Matrixf worldMat = osg::computeLocalToWorld(getNodePath()); osg::TriangleFunctor functor; - functor.setTriMesh(mTriangleMesh); + functor.setTriMesh(mTriangleMesh.get()); functor.setMatrix(worldMat); drawable.accept(functor); } @@ -86,14 +86,12 @@ public: return osg::ref_ptr(); osg::ref_ptr shape (new BulletShape); - TriangleMeshShape* meshShape = new TriangleMeshShape(mTriangleMesh, true); - shape->mCollisionShape = meshShape; - mTriangleMesh = NULL; + shape->mCollisionShape = new TriangleMeshShape(mTriangleMesh.release(), true); return shape; } private: - btTriangleMesh* mTriangleMesh; + std::unique_ptr mTriangleMesh; }; BulletShapeManager::BulletShapeManager(const VFS::Manager* vfs, SceneManager* sceneMgr, NifFileManager* nifFileManager) diff --git a/components/sceneutil/util.cpp b/components/sceneutil/util.cpp index 3add3bb23..eec302965 100644 --- a/components/sceneutil/util.cpp +++ b/components/sceneutil/util.cpp @@ -42,13 +42,4 @@ osg::Vec4f colourFromRGB(unsigned int clr) return colour; } -osg::Vec4f colourFromRGBA(unsigned int clr) -{ - osg::Vec4f colour(((clr >> 0) & 0xFF) / 255.0f, - ((clr >> 8) & 0xFF) / 255.0f, - ((clr >> 16) & 0xFF) / 255.0f, - ((clr >> 24) & 0xFF) / 255.0f); - return colour; -} - } diff --git a/components/sceneutil/util.hpp b/components/sceneutil/util.hpp index d8fefdb29..109099740 100644 --- a/components/sceneutil/util.hpp +++ b/components/sceneutil/util.hpp @@ -15,8 +15,6 @@ namespace SceneUtil osg::Vec4f colourFromRGB (unsigned int clr); - osg::Vec4f colourFromRGBA (unsigned int clr); - } #endif diff --git a/components/sceneutil/workqueue.cpp b/components/sceneutil/workqueue.cpp index cc40506f0..2cd1ec806 100644 --- a/components/sceneutil/workqueue.cpp +++ b/components/sceneutil/workqueue.cpp @@ -119,6 +119,7 @@ unsigned int WorkQueue::getNumActiveThreads() const WorkThread::WorkThread(WorkQueue *workQueue) : mWorkQueue(workQueue) + , mActive(false) { } From 136ef1f738b84db1be424be412e45532fdeecf8b Mon Sep 17 00:00:00 2001 From: scrawl <720642+scrawl@users.noreply.github.com> Date: Sun, 15 Oct 2017 17:24:23 +0200 Subject: [PATCH 24/35] Fix incomplete settings in recreateShaders() --- components/resource/scenemanager.cpp | 35 +++++++++++++++------------- components/resource/scenemanager.hpp | 3 +++ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/components/resource/scenemanager.cpp b/components/resource/scenemanager.cpp index ab801ab82..9c5a2a14e 100644 --- a/components/resource/scenemanager.cpp +++ b/components/resource/scenemanager.cpp @@ -244,12 +244,9 @@ namespace Resource void SceneManager::recreateShaders(osg::ref_ptr node) { - Shader::ShaderVisitor shaderVisitor(*mShaderManager.get(), *mImageManager, "objects_vertex.glsl", "objects_fragment.glsl"); - shaderVisitor.setForceShaders(mForceShaders); - shaderVisitor.setClampLighting(mClampLighting); - shaderVisitor.setForcePerPixelLighting(mForcePerPixelLighting); - shaderVisitor.setAllowedToModifyStateSets(false); - node->accept(shaderVisitor); + osg::ref_ptr shaderVisitor(createShaderVisitor()); + shaderVisitor->setAllowedToModifyStateSets(false); + node->accept(*shaderVisitor); } void SceneManager::setClampLighting(bool clamp) @@ -516,16 +513,8 @@ namespace Resource SetFilterSettingsControllerVisitor setFilterSettingsControllerVisitor(mMinFilter, mMagFilter, mMaxAnisotropy); loaded->accept(setFilterSettingsControllerVisitor); - Shader::ShaderVisitor shaderVisitor(*mShaderManager.get(), *mImageManager, "objects_vertex.glsl", "objects_fragment.glsl"); - shaderVisitor.setForceShaders(mForceShaders); - shaderVisitor.setClampLighting(mClampLighting); - shaderVisitor.setForcePerPixelLighting(mForcePerPixelLighting); - shaderVisitor.setAutoUseNormalMaps(mAutoUseNormalMaps); - shaderVisitor.setNormalMapPattern(mNormalMapPattern); - shaderVisitor.setNormalHeightMapPattern(mNormalHeightMapPattern); - shaderVisitor.setAutoUseSpecularMaps(mAutoUseSpecularMaps); - shaderVisitor.setSpecularMapPattern(mSpecularMapPattern); - loaded->accept(shaderVisitor); + osg::ref_ptr shaderVisitor (createShaderVisitor()); + loaded->accept(*shaderVisitor); // share state // do this before optimizing so the optimizer will be able to combine nodes more aggressively @@ -748,4 +737,18 @@ namespace Resource stats->setAttribute(frameNumber, "Node Instance", mInstanceCache->getCacheSize()); } + Shader::ShaderVisitor *SceneManager::createShaderVisitor() + { + Shader::ShaderVisitor* shaderVisitor = new Shader::ShaderVisitor(*mShaderManager.get(), *mImageManager, "objects_vertex.glsl", "objects_fragment.glsl"); + shaderVisitor->setForceShaders(mForceShaders); + shaderVisitor->setClampLighting(mClampLighting); + shaderVisitor->setForcePerPixelLighting(mForcePerPixelLighting); + shaderVisitor->setAutoUseNormalMaps(mAutoUseNormalMaps); + shaderVisitor->setNormalMapPattern(mNormalMapPattern); + shaderVisitor->setNormalHeightMapPattern(mNormalHeightMapPattern); + shaderVisitor->setAutoUseSpecularMaps(mAutoUseSpecularMaps); + shaderVisitor->setSpecularMapPattern(mSpecularMapPattern); + return shaderVisitor; + } + } diff --git a/components/resource/scenemanager.hpp b/components/resource/scenemanager.hpp index b223353c2..4f1523ece 100644 --- a/components/resource/scenemanager.hpp +++ b/components/resource/scenemanager.hpp @@ -31,6 +31,7 @@ namespace osgDB namespace Shader { class ShaderManager; + class ShaderVisitor; } namespace Resource @@ -149,6 +150,8 @@ namespace Resource private: + Shader::ShaderVisitor* createShaderVisitor(); + std::unique_ptr mShaderManager; bool mForceShaders; bool mClampLighting; From 654bd401fb9e005fef5bc2c243386616e2dc2123 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 16 Oct 2017 15:38:17 +0100 Subject: [PATCH 25/35] Switch openmw-cs to the escape versions of option types --- apps/opencs/editor.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 86c87962d..334674aa7 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -90,16 +90,16 @@ std::pair > CS::Editor::readConfi boost::program_options::options_description desc("Syntax: openmw-cs \nAllowed options"); desc.add_options() - ("data", boost::program_options::value()->default_value(Files::PathContainer(), "data")->multitoken()->composing()) - ("data-local", boost::program_options::value()->default_value("")) + ("data", boost::program_options::value()->default_value(Files::EscapePathContainer(), "data")->multitoken()->composing()) + ("data-local", boost::program_options::value()->default_value("")) ("fs-strict", boost::program_options::value()->implicit_value(true)->default_value(false)) - ("encoding", boost::program_options::value()->default_value("win1252")) - ("resources", boost::program_options::value()->default_value("resources")) - ("fallback-archive", boost::program_options::value >()-> - default_value(std::vector(), "fallback-archive")->multitoken()) + ("encoding", boost::program_options::value()->default_value("win1252")) + ("resources", boost::program_options::value()->default_value("resources")) + ("fallback-archive", boost::program_options::value()-> + default_value(Files::EscapeStringVector(), "fallback-archive")->multitoken()) ("fallback", boost::program_options::value()->default_value(FallbackMap(), "") ->multitoken()->composing(), "fallback values") - ("script-blacklist", boost::program_options::value >()->default_value(std::vector(), "") + ("script-blacklist", boost::program_options::value()->default_value(Files::EscapeStringVector(), "") ->multitoken(), "exclude specified script from the verifier (if the use of the blacklist is enabled)") ("script-blacklist-use", boost::program_options::value()->implicit_value(true) ->default_value(true), "enable script blacklisting"); @@ -109,24 +109,24 @@ std::pair > CS::Editor::readConfi mCfgMgr.readConfiguration(variables, desc, quiet); mDocumentManager.setEncoding ( - ToUTF8::calculateEncoding (variables["encoding"].as())); + ToUTF8::calculateEncoding (variables["encoding"].as().toStdString())); - mDocumentManager.setResourceDir (mResources = variables["resources"].as()); + mDocumentManager.setResourceDir (mResources = variables["resources"].as().toStdString()); mDocumentManager.setFallbackMap (variables["fallback"].as().mMap); if (variables["script-blacklist-use"].as()) mDocumentManager.setBlacklistedScripts ( - variables["script-blacklist"].as >()); + variables["script-blacklist"].as().toStdStringVector()); mFsStrict = variables["fs-strict"].as(); Files::PathContainer dataDirs, dataLocal; if (!variables["data"].empty()) { - dataDirs = Files::PathContainer(variables["data"].as()); + dataDirs = Files::PathContainer(Files::EscapePath::toPathContainer(variables["data"].as())); } - std::string local = variables["data-local"].as(); + std::string local = variables["data-local"].as().toStdString(); if (!local.empty()) { dataLocal.push_back(Files::PathContainer::value_type(local)); } @@ -157,7 +157,7 @@ std::pair > CS::Editor::readConfi mFileDialog.addFiles(path); } - return std::make_pair (dataDirs, variables["fallback-archive"].as >()); + return std::make_pair (dataDirs, variables["fallback-archive"].as().toStdStringVector()); } void CS::Editor::createGame() From 6d7a24224b489c6fee804fc3d05350e615c77046 Mon Sep 17 00:00:00 2001 From: Kyle Cooley Date: Mon, 16 Oct 2017 12:52:13 -0400 Subject: [PATCH 26/35] Add documentation. --- apps/opencs/model/tools/mergestages.hpp | 6 ++++-- apps/opencs/model/world/commands.hpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/mergestages.hpp b/apps/opencs/model/tools/mergestages.hpp index 9a16e03ab..4b41c5a04 100644 --- a/apps/opencs/model/tools/mergestages.hpp +++ b/apps/opencs/model/tools/mergestages.hpp @@ -147,7 +147,8 @@ namespace CSMTools ///< Messages resulting from this stage will be appended to \a messages. }; - /// Flattens the added land and land texture records. + /// During this stage, the complex process of combining LandTextures from + /// potentially multiple plugins is undertaken. class FixLandsAndLandTexturesMergeStage : public CSMDoc::Stage { MergeState& mState; @@ -163,7 +164,8 @@ namespace CSMTools ///< Messages resulting from this stage will be appended to \a messages. }; - // Removes base LandTexture records. + /// Removes base LandTexture records. This gets rid of the base records previously + /// needed in FixLandsAndLandTexturesMergeStage. class CleanupLandTexturesMergeStage : public CSMDoc::Stage { MergeState& mState; diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index be86dd508..58a1b1d1c 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -44,6 +44,15 @@ namespace CSMWorld bool mChanged; }; + /// \brief Adds LandTexture records and modifies texture indices as needed. + /// + /// LandTexture records are different from other types of records, because + /// they only effect the current plugin. Thus, when modifying or copying + /// a Land record, all of the LandTexture records referenced need to be + /// added to the current plugin. Since these newly added LandTextures could + /// have indices that conflict with pre-existing LandTextures in the current + /// plugin, the indices might have to be changed, both for the newly added + /// LandRecord and within the Land record. class ImportLandTexturesCommand : public QUndoCommand { public: @@ -71,6 +80,9 @@ namespace CSMWorld std::vector mCreatedTextures; }; + /// \brief This command is used to fix LandTexture records and texture + /// indices after cloning a Land. See ImportLandTexturesCommand for + /// details. class CopyLandTexturesCommand : public ImportLandTexturesCommand { public: @@ -90,6 +102,9 @@ namespace CSMWorld std::string mDestId; }; + /// \brief This command brings a land record into the current plugin, adding + /// LandTexture records and modifying texture indices as needed. + /// \note See ImportLandTextures for more details. class TouchLandCommand : public ImportLandTexturesCommand { public: From da4765362593c80bed5c39b9333e6eec48e1500c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Mon, 16 Oct 2017 19:47:08 +0200 Subject: [PATCH 27/35] move rain intensity uniform to water node --- apps/openmw/mwrender/renderingmanager.cpp | 9 +++------ apps/openmw/mwrender/renderingmanager.hpp | 1 - apps/openmw/mwrender/sky.cpp | 13 ++++++++++--- apps/openmw/mwrender/sky.hpp | 6 +++++- apps/openmw/mwrender/water.cpp | 11 ++++++++++- apps/openmw/mwrender/water.hpp | 5 +++++ 6 files changed, 33 insertions(+), 12 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index aa7b35b44..7585ee32a 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -251,12 +251,9 @@ namespace MWRender sceneRoot->setNodeMask(Mask_Scene); sceneRoot->setName("Scene Root"); - mUniformRainIntensity = new osg::Uniform("rainIntensity",(float) 0.0); - - mRootNode->getOrCreateStateSet()->addUniform(mUniformRainIntensity); - mSky.reset(new SkyManager(sceneRoot, resourceSystem->getSceneManager())); mSky->setCamera(mViewer->getCamera()); + mSky->setRainIntensityUniform(mWater->getRainIntensityUniform()); source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON); @@ -506,7 +503,7 @@ namespace MWRender } if (!mSky->isEnabled() || !mSky->hasRain()) - clearRainRipples(); + clearRainRipples(); mCamera->update(dt, paused); @@ -811,7 +808,7 @@ namespace MWRender void RenderingManager::clearRainRipples() { - mUniformRainIntensity->set((float) 0.0); + mWater->getRainIntensityUniform()->set((float) 0.0); } void RenderingManager::clear() diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 43059ab6d..f9e98b269 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -85,7 +85,6 @@ namespace MWRender osg::Uniform* mUniformNear; osg::Uniform* mUniformFar; - osg::Uniform* mUniformRainIntensity; void preloadCommonAssets(); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 1338a127c..cffa9909a 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1096,6 +1096,7 @@ private: SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager) : mSceneManager(sceneManager) , mCamera(NULL) + , mRainIntensityUniform(NULL) , mAtmosphereNightRoll(0.f) , mCreated(false) , mIsStorm(false) @@ -1138,6 +1139,11 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana mUnderwaterSwitch = new UnderwaterSwitchCallback(skyroot); } +void SkyManager::setRainIntensityUniform(osg::Uniform *uniform) +{ + mRainIntensityUniform = uniform; +} + void SkyManager::create() { assert(!mCreated); @@ -1315,7 +1321,6 @@ protected: class RainFader : public AlphaFader { public: - RainFader(osg::Uniform *rainIntensityUniform): AlphaFader() { mRainIntensityUniform = rainIntensityUniform; @@ -1481,7 +1486,7 @@ void SkyManager::createRain() mRainNode->addChild(mRainParticleSystem); mRainNode->addChild(updater); - mRainFader = new RainFader(mRootNode->getParent(0)->getParent(0)->getStateSet()->getUniform("rainIntensity")); + mRainFader = new RainFader(mRainIntensityUniform); mRainNode->addUpdateCallback(mRainFader); mRainNode->addCullCallback(mUnderwaterSwitch); mRainNode->setNodeMask(Mask_WeatherParticles); @@ -1742,7 +1747,8 @@ void SkyManager::setWeather(const WeatherResult& weather) mSun->adjustTransparency(weather.mGlareView * weather.mSunDiscColor.a()); float nextStarsOpacity = weather.mNightFade * weather.mGlareView; - if(weather.mNight && mStarsOpacity != nextStarsOpacity) + + if (weather.mNight && mStarsOpacity != nextStarsOpacity) { mStarsOpacity = nextStarsOpacity; @@ -1753,6 +1759,7 @@ void SkyManager::setWeather(const WeatherResult& weather) if (mRainFader) mRainFader->setAlpha(weather.mEffectFade * 0.6); // * Rain_Threshold? + for (std::vector >::const_iterator it = mParticleFaders.begin(); it != mParticleFaders.end(); ++it) (*it)->setAlpha(weather.mEffectFade); } diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 097405b24..816dbf798 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -8,6 +8,7 @@ #include #include +#include namespace osg { @@ -168,6 +169,8 @@ namespace MWRender void setCamera(osg::Camera *camera); + void setRainIntensityUniform(osg::Uniform *uniform); + private: void create(); ///< no need to call this, automatically done on first enable() @@ -178,7 +181,8 @@ namespace MWRender Resource::SceneManager* mSceneManager; - osg::Camera* mCamera; + osg::Camera *mCamera; + osg::Uniform *mRainIntensityUniform; osg::ref_ptr mRootNode; osg::ref_ptr mEarlyRenderBinRoot; diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 68c07c1ab..8935eb37a 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -411,14 +411,20 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem createSimpleWaterStateSet(geom2, mFallback->getFallbackFloat("Water_Map_Alpha")); geom2->setNodeMask(Mask_SimpleWater); mWaterNode->addChild(geom2); - + mSceneRoot->addChild(mWaterNode); setHeight(mTop); + mRainIntensityUniform = NULL; updateWaterMaterial(); } +osg::Uniform *Water::getRainIntensityUniform() +{ + return mRainIntensityUniform; +} + void Water::updateWaterMaterial() { if (mReflection) @@ -550,6 +556,9 @@ void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, R program->addShader(fragmentShader); shaderStateset->setAttributeAndModes(program, osg::StateAttribute::ON); + mRainIntensityUniform = new osg::Uniform("rainIntensity",(float) 0.0); + shaderStateset->addUniform(mRainIntensityUniform); + node->setStateSet(shaderStateset); node->setUpdateCallback(NULL); } diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 33b314c51..6c7adac37 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -6,6 +6,7 @@ #include #include +#include #include @@ -50,6 +51,8 @@ namespace MWRender { static const int CELL_SIZE = 8192; + osg::Uniform* mRainIntensityUniform; + osg::ref_ptr mParent; osg::ref_ptr mSceneRoot; osg::ref_ptr mWaterNode; @@ -110,6 +113,8 @@ namespace MWRender void update(float dt); void processChangedSettings(const Settings::CategorySettingVector& settings); + + osg::Uniform *getRainIntensityUniform(); }; } From 797e407269b2e4aef6cba8e521f07a7f7819276f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Mon, 16 Oct 2017 20:23:56 +0200 Subject: [PATCH 28/35] make snow create water ripples --- apps/openmw/mwrender/sky.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index cffa9909a..05937742f 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1245,9 +1245,11 @@ private: class AlphaFader : public SceneUtil::StateSetUpdater { public: - AlphaFader() + /// @param rainIntensityUniform rain uniform to update along with alpha, can be NULL + AlphaFader(osg::Uniform *rainIntensityUniform=NULL) : mAlpha(1.f) { + mRainIntensityUniform = rainIntensityUniform; } void setAlpha(float alpha) @@ -1266,15 +1268,19 @@ public: { osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha)); + + if (mRainIntensityUniform) + mRainIntensityUniform->set((float) mAlpha); } // Helper for adding AlphaFaders to a subgraph class SetupVisitor : public osg::NodeVisitor { public: - SetupVisitor() + SetupVisitor(osg::Uniform *rainIntensityUniform) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) { + mRainIntensityUniform = rainIntensityUniform; } virtual void apply(osg::Node &node) @@ -1285,14 +1291,16 @@ public: { SceneUtil::CompositeStateSetUpdater* composite = NULL; osg::Callback* callback = node.getUpdateCallback(); + while (callback) { if ((composite = dynamic_cast(callback))) break; + callback = callback->getNestedCallback(); } - osg::ref_ptr alphaFader (new AlphaFader); + osg::ref_ptr alphaFader (new AlphaFader(mRainIntensityUniform)); if (composite) composite->addController(alphaFader); @@ -1312,10 +1320,12 @@ public: private: std::vector > mAlphaFaders; + osg::Uniform *mRainIntensityUniform; }; protected: float mAlpha; + osg::Uniform *mRainIntensityUniform; }; class RainFader : public AlphaFader @@ -1645,12 +1655,16 @@ void SkyManager::setWeather(const WeatherResult& weather) mParticleNode->setNodeMask(Mask_WeatherParticles); mRootNode->addChild(mParticleNode); } + mParticleEffect = mSceneManager->getInstance(mCurrentParticleEffect, mParticleNode); SceneUtil::AssignControllerSourcesVisitor assignVisitor(std::shared_ptr(new SceneUtil::FrameTimeSource)); mParticleEffect->accept(assignVisitor); - AlphaFader::SetupVisitor alphaFaderSetupVisitor; + osg::Uniform *rainUniform = weather.mIsStorm ? NULL : mRainIntensityUniform; + + AlphaFader::SetupVisitor alphaFaderSetupVisitor(rainUniform); + mParticleEffect->accept(alphaFaderSetupVisitor); mParticleFaders = alphaFaderSetupVisitor.getAlphaFaders(); From 8a1e0e74fd7f35ee4be220ab3796995fed0fbc2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Mon, 16 Oct 2017 23:56:03 +0200 Subject: [PATCH 29/35] update uniform from one place --- apps/openmw/mwrender/renderingmanager.cpp | 9 ----- apps/openmw/mwrender/renderingmanager.hpp | 2 - apps/openmw/mwrender/sky.cpp | 46 ++++++++++++----------- apps/openmw/mwrender/sky.hpp | 2 + 4 files changed, 27 insertions(+), 32 deletions(-) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 7585ee32a..6c4cc802b 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -502,9 +502,6 @@ namespace MWRender mWater->update(dt); } - if (!mSky->isEnabled() || !mSky->hasRain()) - clearRainRipples(); - mCamera->update(dt, paused); osg::Vec3f focal, cameraPos; @@ -803,12 +800,6 @@ namespace MWRender void RenderingManager::notifyWorldSpaceChanged() { mEffectManager->clear(); - mWater->clearRipples(); - } - - void RenderingManager::clearRainRipples() - { - mWater->getRainIntensityUniform()->set((float) 0.0); } void RenderingManager::clear() diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index f9e98b269..f0087e43d 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -159,8 +159,6 @@ namespace MWRender /// Clear all worldspace-specific data void notifyWorldSpaceChanged(); - void clearRainRipples(); - void update(float dt, bool paused); Animation* getAnimation(const MWWorld::Ptr& ptr); diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 05937742f..97633a6b9 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1245,11 +1245,11 @@ private: class AlphaFader : public SceneUtil::StateSetUpdater { public: - /// @param rainIntensityUniform rain uniform to update along with alpha, can be NULL - AlphaFader(osg::Uniform *rainIntensityUniform=NULL) + /// @param alphaUpdate variable which to update with alpha value + AlphaFader(float *alphaUpdate) : mAlpha(1.f) { - mRainIntensityUniform = rainIntensityUniform; + mAlphaUpdate = alphaUpdate; } void setAlpha(float alpha) @@ -1269,18 +1269,18 @@ public: osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,mAlpha)); - if (mRainIntensityUniform) - mRainIntensityUniform->set((float) mAlpha); + if (mAlphaUpdate) + *mAlphaUpdate = mAlpha; } // Helper for adding AlphaFaders to a subgraph class SetupVisitor : public osg::NodeVisitor { public: - SetupVisitor(osg::Uniform *rainIntensityUniform) + SetupVisitor(float *alphaUpdate) : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN) { - mRainIntensityUniform = rainIntensityUniform; + mAlphaUpdate = alphaUpdate; } virtual void apply(osg::Node &node) @@ -1300,7 +1300,7 @@ public: callback = callback->getNestedCallback(); } - osg::ref_ptr alphaFader (new AlphaFader(mRainIntensityUniform)); + osg::ref_ptr alphaFader (new AlphaFader(mAlphaUpdate)); if (composite) composite->addController(alphaFader); @@ -1310,6 +1310,7 @@ public: mAlphaFaders.push_back(alphaFader); } } + traverse(node); } @@ -1320,20 +1321,19 @@ public: private: std::vector > mAlphaFaders; - osg::Uniform *mRainIntensityUniform; + float *mAlphaUpdate; }; protected: float mAlpha; - osg::Uniform *mRainIntensityUniform; + float *mAlphaUpdate; }; class RainFader : public AlphaFader { public: - RainFader(osg::Uniform *rainIntensityUniform): AlphaFader() + RainFader(float *alphaUpdate): AlphaFader(alphaUpdate) { - mRainIntensityUniform = rainIntensityUniform; } virtual void setDefaults(osg::StateSet* stateset) @@ -1348,11 +1348,8 @@ public: virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv) { AlphaFader::apply(stateset,nv); - mRainIntensityUniform->set((float) (mAlpha * 2.0)); // mAlpha is limited to 0.6 so multiply by 2 to reach full intensity + *mAlphaUpdate = mAlpha * 2.0; // mAlpha is limited to 0.6 so multiply by 2 to reach full intensity } - -protected: - osg::Uniform* mRainIntensityUniform; }; void SkyManager::setCamera(osg::Camera *camera) @@ -1496,7 +1493,7 @@ void SkyManager::createRain() mRainNode->addChild(mRainParticleSystem); mRainNode->addChild(updater); - mRainFader = new RainFader(mRainIntensityUniform); + mRainFader = new RainFader(&mWeatherAlpha); mRainNode->addUpdateCallback(mRainFader); mRainNode->addCullCallback(mUnderwaterSwitch); mRainNode->setNodeMask(Mask_WeatherParticles); @@ -1549,7 +1546,16 @@ bool SkyManager::hasRain() void SkyManager::update(float duration) { - if (!mEnabled) return; + if (!mEnabled) + { + mRainIntensityUniform->set((float) 0.0); + return; + } + + if (mIsStorm || (!hasRain() && !mParticleNode)) + mRainIntensityUniform->set((float) 0.0); + else + mRainIntensityUniform->set((float) mWeatherAlpha); if (mIsStorm) { @@ -1661,9 +1667,7 @@ void SkyManager::setWeather(const WeatherResult& weather) SceneUtil::AssignControllerSourcesVisitor assignVisitor(std::shared_ptr(new SceneUtil::FrameTimeSource)); mParticleEffect->accept(assignVisitor); - osg::Uniform *rainUniform = weather.mIsStorm ? NULL : mRainIntensityUniform; - - AlphaFader::SetupVisitor alphaFaderSetupVisitor(rainUniform); + AlphaFader::SetupVisitor alphaFaderSetupVisitor(&mWeatherAlpha); mParticleEffect->accept(alphaFaderSetupVisitor); mParticleFaders = alphaFaderSetupVisitor.getAlphaFaders(); diff --git a/apps/openmw/mwrender/sky.hpp b/apps/openmw/mwrender/sky.hpp index 816dbf798..4357d468c 100644 --- a/apps/openmw/mwrender/sky.hpp +++ b/apps/openmw/mwrender/sky.hpp @@ -252,6 +252,8 @@ namespace MWRender bool mEnabled; bool mSunEnabled; + float mWeatherAlpha; + osg::Vec4f mMoonScriptColor; }; } From a7cad65aab97f00757ef421452ba14ddd229cecd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Tue, 17 Oct 2017 00:13:55 +0200 Subject: [PATCH 30/35] fix water shader switching bug --- apps/openmw/mwrender/sky.cpp | 15 ++++++++++----- apps/openmw/mwrender/water.cpp | 6 +++--- apps/openmw/mwrender/water.hpp | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/apps/openmw/mwrender/sky.cpp b/apps/openmw/mwrender/sky.cpp index 97633a6b9..6c599fc3f 100644 --- a/apps/openmw/mwrender/sky.cpp +++ b/apps/openmw/mwrender/sky.cpp @@ -1548,14 +1548,19 @@ void SkyManager::update(float duration) { if (!mEnabled) { - mRainIntensityUniform->set((float) 0.0); + if (mRainIntensityUniform) + mRainIntensityUniform->set((float) 0.0); + return; } - if (mIsStorm || (!hasRain() && !mParticleNode)) - mRainIntensityUniform->set((float) 0.0); - else - mRainIntensityUniform->set((float) mWeatherAlpha); + if (mRainIntensityUniform) + { + if (mIsStorm || (!hasRain() && !mParticleNode)) + mRainIntensityUniform->set((float) 0.0); + else + mRainIntensityUniform->set((float) mWeatherAlpha); + } if (mIsStorm) { diff --git a/apps/openmw/mwrender/water.cpp b/apps/openmw/mwrender/water.cpp index 8935eb37a..52b659984 100644 --- a/apps/openmw/mwrender/water.cpp +++ b/apps/openmw/mwrender/water.cpp @@ -416,13 +416,14 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem setHeight(mTop); - mRainIntensityUniform = NULL; updateWaterMaterial(); + + mRainIntensityUniform = new osg::Uniform("rainIntensity",(float) 0.0); } osg::Uniform *Water::getRainIntensityUniform() { - return mRainIntensityUniform; + return mRainIntensityUniform.get(); } void Water::updateWaterMaterial() @@ -556,7 +557,6 @@ void Water::createShaderWaterStateSet(osg::Node* node, Reflection* reflection, R program->addShader(fragmentShader); shaderStateset->setAttributeAndModes(program, osg::StateAttribute::ON); - mRainIntensityUniform = new osg::Uniform("rainIntensity",(float) 0.0); shaderStateset->addUniform(mRainIntensityUniform); node->setStateSet(shaderStateset); diff --git a/apps/openmw/mwrender/water.hpp b/apps/openmw/mwrender/water.hpp index 6c7adac37..a4fd1ed36 100644 --- a/apps/openmw/mwrender/water.hpp +++ b/apps/openmw/mwrender/water.hpp @@ -51,7 +51,7 @@ namespace MWRender { static const int CELL_SIZE = 8192; - osg::Uniform* mRainIntensityUniform; + osg::ref_ptr mRainIntensityUniform; osg::ref_ptr mParent; osg::ref_ptr mSceneRoot; From 4d4d247565338db653111fe92deb23c099966d3a Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 17 Oct 2017 23:26:55 +0400 Subject: [PATCH 31/35] Use SwimTurnLeft/Right animations correctly --- apps/openmw/mwmechanics/character.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index ec65255bc..03acfdaf2 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1874,7 +1874,7 @@ void CharacterController::update(float duration) : (sneak ? CharState_SneakBack : (isrunning ? CharState_RunBack : CharState_WalkBack))); } - else if(rot.z() != 0.0f && !inwater && !sneak && !(mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson())) + else if(rot.z() != 0.0f && !sneak && !(mPtr == getPlayer() && MWBase::Environment::get().getWorld()->isFirstPerson())) { if(rot.z() > 0.0f) movestate = inwater ? CharState_SwimTurnRight : CharState_TurnRight; From 1f77f9654bba0e286ada5d3d593c1f4bf43ac781 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Wed, 18 Oct 2017 01:42:11 +0100 Subject: [PATCH 32/35] Strip quotes from the data-local setting if present (because for whatever reason it's a string, not a boost::filesystem::path) --- apps/openmw/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index 9e44f237e..ac891b980 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -194,6 +194,9 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat std::string local(variables["data-local"].as().toStdString()); if (!local.empty()) { + if (local.front() == '\"') + local = local.substr(1, local.length() - 2); + dataDirs.push_back(Files::PathContainer::value_type(local)); } From 43e9e955c88aaade0b68bd00d7ce00e7c5f65bf9 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Wed, 18 Oct 2017 02:04:48 +0100 Subject: [PATCH 33/35] Do the same for the CS --- apps/opencs/editor.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 334674aa7..35ce51337 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -127,7 +127,11 @@ std::pair > CS::Editor::readConfi } std::string local = variables["data-local"].as().toStdString(); - if (!local.empty()) { + if (!local.empty()) + { + if (local.front() == '\"') + local = local.substr(1, local.length() - 2); + dataLocal.push_back(Files::PathContainer::value_type(local)); } From 9571cd8754d88be35623eddeb19dd79c9d5c2173 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Thu, 19 Oct 2017 00:50:57 +0100 Subject: [PATCH 34/35] Switch defaultfilters to be handled by a binary-friendly version of the resource macro --- CMakeLists.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bf2896da..b47678e7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -329,8 +329,9 @@ endif () configure_resource_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.cfg "${OpenMW_BINARY_DIR}" "openmw-cs.cfg") -configure_resource_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters - "${OpenMW_BINARY_DIR}" "resources/defaultfilters" COPYONLY) +# Needs the copy version because the configure version assumes the end of the file has been reached when a null character is reached and there are no CMake expressions to evaluate. +copy_resource_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters + "${OpenMW_BINARY_DIR}" "resources/defaultfilters") configure_resource_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt "${OpenMW_BINARY_DIR}" "gamecontrollerdb.txt") From 6d8666d80dc5ac58bd193ea4cf22ebac4034e959 Mon Sep 17 00:00:00 2001 From: Kyle Cooley Date: Wed, 18 Oct 2017 20:21:44 -0400 Subject: [PATCH 35/35] Force new project file when creating new project --- apps/opencs/model/doc/document.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 7257b2fe3..7a825ba39 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -288,7 +288,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, if (mContentFiles.empty()) throw std::runtime_error ("Empty content file sequence"); - if (!boost::filesystem::exists (mProjectPath)) + if (mNew || !boost::filesystem::exists (mProjectPath)) { boost::filesystem::path customFiltersPath (configuration.getUserDataPath()); customFiltersPath /= "defaultfilters";