From 340d626589c661724d3c03b12117d3bd0a1825bf Mon Sep 17 00:00:00 2001 From: bzzt lost a hitlab login Date: Mon, 11 May 2020 13:37:00 +0000 Subject: [PATCH] static moving support Signed-off-by: Bret Curtis --- apps/openmw/mwrender/objectpaging.cpp | 45 +++++++++++-- apps/openmw/mwrender/objectpaging.hpp | 6 +- apps/openmw/mwrender/renderingmanager.cpp | 13 +++- apps/openmw/mwrender/renderingmanager.hpp | 1 + apps/openmw/mwworld/cellstore.cpp | 6 ++ apps/openmw/mwworld/scene.cpp | 82 +++++++++++++---------- apps/openmw/mwworld/scene.hpp | 3 + apps/openmw/mwworld/worldimp.cpp | 29 +++++--- 8 files changed, 132 insertions(+), 53 deletions(-) diff --git a/apps/openmw/mwrender/objectpaging.cpp b/apps/openmw/mwrender/objectpaging.cpp index 9b3165d87a..4c8706caf8 100644 --- a/apps/openmw/mwrender/objectpaging.cpp +++ b/apps/openmw/mwrender/objectpaging.cpp @@ -389,8 +389,9 @@ namespace MWRender { OpenThreads::ScopedLock lock(mDisabledMutex); - for (auto disabled : mDisabled) - refs.erase(disabled); + if (activeGrid) + for (auto ref : mBlacklist) + refs.erase(ref); } osg::Vec2f minBound = (center - osg::Vec2f(size/2.f, size/2.f)); @@ -424,7 +425,9 @@ namespace MWRender continue; } + float d = (viewPoint - pos).length(); + if (!activeGrid) { OpenThreads::ScopedLock lock(mSizeCacheMutex); SizeCache::iterator found = mSizeCache.find(pair.first); @@ -450,6 +453,15 @@ namespace MWRender */ osg::ref_ptr cnode = mSceneManager->getTemplate(model, false); + if (activeGrid) + refnumSet->mRefnums.insert(pair.first); + + { + OpenThreads::ScopedLock lock(mDisabledMutex); + if (mDisabled.count(pair.first)) + continue; + } + float radius = cnode->getBound().radius() * ref.mScale; if (radius < d*minSize) { @@ -473,9 +485,6 @@ namespace MWRender else analyzeVisitor.addInstance(emplaced.first->second.mAnalyzeResult); emplaced.first->second.mInstances.push_back(&ref); - - if (activeGrid) - refnumSet->mRefnums.insert(pair.first); } osg::ref_ptr group = new osg::Group; @@ -614,6 +623,7 @@ namespace MWRender } bool intersects(ChunkId id, osg::Vec3f pos) { + if (mActiveGridOnly && !std::get<2>(id)) return false; pos /= ESM::Land::REAL_SIZE; osg::Vec2f center = std::get<0>(id); float halfSize = std::get<1>(id)/2; @@ -621,6 +631,7 @@ namespace MWRender } osg::Vec3f mPosition; std::set mToClear; + bool mActiveGridOnly = false; }; bool ObjectPaging::enableObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, bool enabled) @@ -642,13 +653,33 @@ namespace MWRender return true; } + bool ObjectPaging::blacklistObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos) + { + if (!typeFilter(type, false, true)) + return false; + + { + OpenThreads::ScopedLock lock(mDisabledMutex); + if (!mBlacklist.insert(refnum).second) return false; + } + + ClearCacheFunctor ccf; + ccf.mPosition = pos; + ccf.mActiveGridOnly = true; + mCache->call(ccf); + if (ccf.mToClear.empty()) return false; + for (auto chunk : ccf.mToClear) + mCache->removeFromObjectCache(chunk); + return true; + } + + void ObjectPaging::clear() { { OpenThreads::ScopedLock lock(mDisabledMutex); - if (mDisabled.empty()) - return; mDisabled.clear(); + mBlacklist.clear(); } mCache->clear(); } diff --git a/apps/openmw/mwrender/objectpaging.hpp b/apps/openmw/mwrender/objectpaging.hpp index 79591dcc41..4419cd86a9 100644 --- a/apps/openmw/mwrender/objectpaging.hpp +++ b/apps/openmw/mwrender/objectpaging.hpp @@ -33,9 +33,12 @@ namespace MWRender virtual unsigned int getNodeMask() override; - /// @return true if something changed + /// @return true if view needs rebuild bool enableObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos, bool enabled); + /// @return true if view needs rebuild + bool blacklistObject(int type, const ESM::RefNum & refnum, const osg::Vec3f& pos); + void clear(); void reportStats(unsigned int frameNumber, osg::Stats* stats) const override; @@ -53,6 +56,7 @@ namespace MWRender OpenThreads::Mutex mDisabledMutex; std::set mDisabled; + std::set mBlacklist; OpenThreads::Mutex mSizeCacheMutex; typedef std::map SizeCache; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 5523a69369..590c59302e 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -1483,15 +1483,24 @@ namespace MWRender } bool RenderingManager::pagingEnableObject(int type, const MWWorld::ConstPtr& ptr, bool enabled) { - if (!ptr.isInCell() || !ptr.getCell()->isExterior()) + if (!ptr.isInCell() || !ptr.getCell()->isExterior() || !mObjectPaging) return false; - if (mObjectPaging && mObjectPaging->enableObject(type, ptr.getCellRef().getRefNum(), ptr.getRefData().getPosition().asVec3(), enabled)) + if (mObjectPaging->enableObject(type, ptr.getCellRef().getRefNum(), ptr.getCellRef().getPosition().asVec3(), enabled)) { mTerrain->rebuildViews(); return true; } return false; } + void RenderingManager::pagingBlacklistObject(int type, const MWWorld::ConstPtr &ptr) + { + if (!ptr.isInCell() || !ptr.getCell()->isExterior() || !mObjectPaging) + return; + const ESM::RefNum & refnum = ptr.getCellRef().getRefNum(); + if (!refnum.hasContentFile()) return; + if (mObjectPaging->blacklistObject(type, refnum, ptr.getCellRef().getPosition().asVec3())) + mTerrain->rebuildViews(); + } void RenderingManager::getPagedRefnums(const osg::Vec4i &activeGrid, std::set &out) { if (mObjectPaging) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 3082866c43..c46c2f3434 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -242,6 +242,7 @@ namespace MWRender void setActiveGrid(const osg::Vec4i &grid); bool pagingEnableObject(int type, const MWWorld::ConstPtr& ptr, bool enabled); + void pagingBlacklistObject(int type, const MWWorld::ConstPtr &ptr); void getPagedRefnums(const osg::Vec4i &activeGrid, std::set &out); private: diff --git a/apps/openmw/mwworld/cellstore.cpp b/apps/openmw/mwworld/cellstore.cpp index 6b737f2029..36f568a5f7 100644 --- a/apps/openmw/mwworld/cellstore.cpp +++ b/apps/openmw/mwworld/cellstore.cpp @@ -141,7 +141,13 @@ namespace if (iter->mRef.getRefNum()==state.mRef.mRefNum && *iter->mRef.getRefIdPtr() == state.mRef.mRefID) { // overwrite existing reference + float oldscale = iter->mRef.getScale(); iter->load (state); + const ESM::Position & oldpos = iter->mRef.getPosition(); + const ESM::Position & newpos = iter->mData.getPosition(); + const MWWorld::Ptr ptr(&*iter, cellstore); + if ((oldscale != iter->mRef.getScale() || oldpos.asVec3() != newpos.asVec3() || oldpos.rot[0] != newpos.rot[0] || oldpos.rot[1] != newpos.rot[1] || oldpos.rot[2] != newpos.rot[2]) && !ptr.getClass().isActor()) + MWBase::Environment::get().getWorld()->moveObject(ptr, newpos.pos[0], newpos.pos[1], newpos.pos[2]); if (!iter->mData.isEnabled()) { iter->mData.enable(); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index bd9a92daee..a469866167 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -87,6 +87,19 @@ namespace ); } + std::string getModel(const MWWorld::Ptr &ptr, const VFS::Manager *vfs) + { + bool useAnim = ptr.getClass().useAnim(); + std::string model = ptr.getClass().getModel(ptr); + if (useAnim) + model = Misc::ResourceHelpers::correctActorModelPath(model, vfs); + + const std::string &id = ptr.getCellRef().getRefId(); + if (id == "prisonmarker" || id == "divinemarker" || id == "templemarker" || id == "northmarker") + model = ""; // marker objects that have a hardcoded function in the game logic, should be hidden from the player + return model; + } + void addObject(const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics, MWRender::RenderingManager& rendering, std::set& pagedRefs) { @@ -97,13 +110,7 @@ namespace } bool useAnim = ptr.getClass().useAnim(); - std::string model = ptr.getClass().getModel(ptr); - if (useAnim) - model = Misc::ResourceHelpers::correctActorModelPath(model, rendering.getResourceSystem()->getVFS()); - - std::string id = ptr.getCellRef().getRefId(); - if (id == "prisonmarker" || id == "divinemarker" || id == "templemarker" || id == "northmarker") - model = ""; // marker objects that have a hardcoded function in the game logic, should be hidden from the player + std::string model = getModel(ptr, rendering.getResourceSystem()->getVFS()); const ESM::RefNum& refnum = ptr.getCellRef().getRefNum(); if (!refnum.hasContentFile() || pagedRefs.find(refnum) == pagedRefs.end()) @@ -188,27 +195,6 @@ namespace } } - void updateObjectRotation (const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics, - MWRender::RenderingManager& rendering, RotationOrder order) - { - setNodeRotation(ptr, rendering, order); - physics.updateRotation(ptr); - } - - void updateObjectScale(const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics, - MWRender::RenderingManager& rendering) - { - if (ptr.getRefData().getBaseNode() != nullptr) - { - float scale = ptr.getCellRef().getScale(); - osg::Vec3f scaleVec (scale, scale, scale); - ptr.getClass().adjustScale(ptr, scaleVec, true); - rendering.scaleObject(ptr, scaleVec); - - physics.updateScale(ptr); - } - } - struct InsertVisitor { MWWorld::CellStore& mCell; @@ -281,23 +267,49 @@ namespace namespace MWWorld { - void Scene::updateObjectRotation(const Ptr& ptr, RotationOrder order) + void Scene::removeFromPagedRefs(const Ptr &ptr) { - ::updateObjectRotation(ptr, *mPhysics, mRendering, order); + const ESM::RefNum& refnum = ptr.getCellRef().getRefNum(); + if (refnum.hasContentFile() && mPagedRefs.erase(refnum)) + { + if (!ptr.getRefData().getBaseNode()) return; + ptr.getClass().insertObjectRendering(ptr, getModel(ptr, mRendering.getResourceSystem()->getVFS()), mRendering); + setNodeRotation(ptr, mRendering, RotationOrder::direct); + reloadTerrain(); + } + } + + void Scene::updateObjectPosition(const Ptr &ptr, const osg::Vec3f &pos, bool movePhysics) + { + mRendering.moveObject(ptr, pos); + if (movePhysics) + { + mPhysics->updatePosition(ptr); + } + } + + void Scene::updateObjectRotation(const Ptr &ptr, RotationOrder order) + { + setNodeRotation(ptr, mRendering, order); + mPhysics->updateRotation(ptr); } void Scene::updateObjectScale(const Ptr &ptr) { - ::updateObjectScale(ptr, *mPhysics, mRendering); + float scale = ptr.getCellRef().getScale(); + osg::Vec3f scaleVec (scale, scale, scale); + ptr.getClass().adjustScale(ptr, scaleVec, true); + mRendering.scaleObject(ptr, scaleVec); + mPhysics->updateScale(ptr); } void Scene::update (float duration, bool paused) { - mPreloadTimer += duration; - if (mPreloadTimer > 0.1f) + mPreloadTimer -= duration; + if (mPreloadTimer <= 0.f) { preloadCells(0.1f); - mPreloadTimer = 0.f; + mPreloadTimer = 0.1f; } mRendering.update (duration, paused); @@ -954,7 +966,6 @@ namespace MWWorld if (ptr.getClass().isActor()) mRendering.removeWaterRippleEmitter(ptr); ptr.getRefData().setBaseNode(nullptr); - mPagedRefs.erase(ptr.getCellRef().getRefNum()); } bool Scene::isCellActive(const CellStore &cell) @@ -1149,6 +1160,7 @@ namespace MWWorld void Scene::reloadTerrain() { + mPreloadTimer = 0; mPreloader->setTerrainPreloadPositions(std::vector()); } diff --git a/apps/openmw/mwworld/scene.hpp b/apps/openmw/mwworld/scene.hpp index b7aeafbfec..2fbbccf68f 100644 --- a/apps/openmw/mwworld/scene.hpp +++ b/apps/openmw/mwworld/scene.hpp @@ -155,8 +155,11 @@ namespace MWWorld void removeObjectFromScene (const Ptr& ptr); ///< Remove an object from the scene, but not from the world model. + void removeFromPagedRefs(const Ptr &ptr); + void updateObjectRotation(const Ptr& ptr, RotationOrder order); void updateObjectScale(const Ptr& ptr); + void updateObjectPosition(const Ptr &ptr, const osg::Vec3f &pos, bool movePhysics); bool isCellActive(const CellStore &cell); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 8392a827cf..2975240e78 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1204,20 +1204,22 @@ namespace MWWorld } if (haveToMove && newPtr.getRefData().getBaseNode()) { - mRendering->moveObject(newPtr, vec); + mWorldScene->updateObjectPosition(newPtr, vec, movePhysics); if (movePhysics) { - mPhysics->updatePosition(newPtr); - mPhysics->updatePtr(ptr, newPtr); - - if (const auto object = mPhysics->getObject(newPtr)) + if (const auto object = mPhysics->getObject(ptr)) updateNavigatorObject(object); } } + if (isPlayer) - { mWorldScene->playerMoved(vec); + else + { + mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr); + mWorldScene->removeFromPagedRefs(newPtr); } + return newPtr; } @@ -1246,9 +1248,15 @@ namespace MWWorld if (mPhysics->getActor(ptr)) mNavigator->removeAgent(getPathfindingHalfExtents(ptr)); - ptr.getCellRef().setScale(scale); + if (scale != ptr.getCellRef().getScale()) + { + ptr.getCellRef().setScale(scale); + mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr); + mWorldScene->removeFromPagedRefs(ptr); + } - mWorldScene->updateObjectScale(ptr); + if(ptr.getRefData().getBaseNode() != 0) + mWorldScene->updateObjectScale(ptr); if (mPhysics->getActor(ptr)) mNavigator->addAgent(getPathfindingHalfExtents(ptr)); @@ -1292,6 +1300,9 @@ namespace MWWorld ptr.getRefData().setPosition(pos); + mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr); + mWorldScene->removeFromPagedRefs(ptr); + if(ptr.getRefData().getBaseNode() != 0) { const auto order = flags & MWBase::RotationFlag_inverseOrder @@ -3565,6 +3576,8 @@ namespace MWWorld std::string World::exportSceneGraph(const Ptr &ptr) { std::string file = mUserDataPath + "/openmw.osgt"; + mRendering->pagingBlacklistObject(mStore.find(ptr.getCellRef().getRefId()), ptr); + mWorldScene->removeFromPagedRefs(ptr); mRendering->exportSceneGraph(ptr, file, "Ascii"); return file; }