mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-11-04 01:26:41 +00:00 
			
		
		
		
	waterculling for both terrain
This commit is contained in:
		
							parent
							
								
									e791e65684
								
							
						
					
					
						commit
						ed20d869b4
					
				
					 8 changed files with 129 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -282,8 +282,6 @@ namespace MWRender
 | 
			
		|||
 | 
			
		||||
        mEffectManager.reset(new EffectManager(sceneRoot, mResourceSystem));
 | 
			
		||||
 | 
			
		||||
        mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), resourcePath));
 | 
			
		||||
 | 
			
		||||
        DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog");
 | 
			
		||||
        DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog");
 | 
			
		||||
        DLUnderwaterFogStart = Settings::Manager::getFloat("distant underwater fog start", "Fog");
 | 
			
		||||
| 
						 | 
				
			
			@ -322,6 +320,9 @@ namespace MWRender
 | 
			
		|||
        mTerrain->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells"));
 | 
			
		||||
        mTerrain->setWorkQueue(mWorkQueue.get());
 | 
			
		||||
 | 
			
		||||
        // water goes after terrain for correct waterculling order
 | 
			
		||||
        mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), resourcePath));
 | 
			
		||||
 | 
			
		||||
        mCamera.reset(new Camera(mViewer->getCamera()));
 | 
			
		||||
 | 
			
		||||
        mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
 | 
			
		||||
| 
						 | 
				
			
			@ -541,6 +542,8 @@ namespace MWRender
 | 
			
		|||
 | 
			
		||||
    void RenderingManager::enableTerrain(bool enable)
 | 
			
		||||
    {
 | 
			
		||||
        if (!enable)
 | 
			
		||||
            mWater->setCullCallback(nullptr);
 | 
			
		||||
        mTerrain->enable(enable);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -740,6 +743,7 @@ namespace MWRender
 | 
			
		|||
 | 
			
		||||
    void RenderingManager::setWaterHeight(float height)
 | 
			
		||||
    {
 | 
			
		||||
        mWater->setCullCallback(mTerrain->getHeightCullCallback(height, Mask_Water));
 | 
			
		||||
        mWater->setHeight(height);
 | 
			
		||||
        mSky->setWaterHeight(height);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -436,6 +436,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
 | 
			
		|||
    , mToggled(true)
 | 
			
		||||
    , mTop(0)
 | 
			
		||||
    , mInterior(false)
 | 
			
		||||
    , mCullCallback(nullptr)
 | 
			
		||||
{
 | 
			
		||||
    mSimulation.reset(new RippleSimulation(mSceneRoot, resourceSystem));
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -466,6 +467,29 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
 | 
			
		|||
        ico->add(mWaterNode);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Water::setCullCallback(osg::Callback* callback)
 | 
			
		||||
{
 | 
			
		||||
    if (mCullCallback)
 | 
			
		||||
    {
 | 
			
		||||
        mWaterNode->removeCullCallback(mCullCallback);
 | 
			
		||||
        if (mReflection)
 | 
			
		||||
            mReflection->removeCullCallback(mCullCallback);
 | 
			
		||||
        if (mRefraction)
 | 
			
		||||
            mRefraction->removeCullCallback(mCullCallback);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mCullCallback = callback;
 | 
			
		||||
 | 
			
		||||
    if (callback)
 | 
			
		||||
    {
 | 
			
		||||
        mWaterNode->addCullCallback(callback);
 | 
			
		||||
        if (mReflection)
 | 
			
		||||
            mReflection->addCullCallback(callback);
 | 
			
		||||
        if (mRefraction)
 | 
			
		||||
            mRefraction->addCullCallback(callback);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
osg::Uniform *Water::getRainIntensityUniform()
 | 
			
		||||
{
 | 
			
		||||
    return mRainIntensityUniform.get();
 | 
			
		||||
| 
						 | 
				
			
			@ -491,6 +515,8 @@ void Water::updateWaterMaterial()
 | 
			
		|||
        mReflection = new Reflection(mInterior);
 | 
			
		||||
        mReflection->setWaterLevel(mTop);
 | 
			
		||||
        mReflection->setScene(mSceneRoot);
 | 
			
		||||
        if (mCullCallback)
 | 
			
		||||
            mReflection->addCullCallback(mCullCallback);
 | 
			
		||||
        mParent->addChild(mReflection);
 | 
			
		||||
 | 
			
		||||
        if (Settings::Manager::getBool("refraction", "Water"))
 | 
			
		||||
| 
						 | 
				
			
			@ -498,6 +524,8 @@ void Water::updateWaterMaterial()
 | 
			
		|||
            mRefraction = new Refraction;
 | 
			
		||||
            mRefraction->setWaterLevel(mTop);
 | 
			
		||||
            mRefraction->setScene(mSceneRoot);
 | 
			
		||||
            if (mCullCallback)
 | 
			
		||||
                mRefraction->addCullCallback(mCullCallback);
 | 
			
		||||
            mParent->addChild(mRefraction);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,6 +71,8 @@ namespace MWRender
 | 
			
		|||
        float mTop;
 | 
			
		||||
        bool mInterior;
 | 
			
		||||
 | 
			
		||||
        osg::Callback* mCullCallback;
 | 
			
		||||
 | 
			
		||||
        osg::Vec3f getSceneNodeCoordinates(int gridX, int gridY);
 | 
			
		||||
        void updateVisible();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +90,8 @@ namespace MWRender
 | 
			
		|||
              const std::string& resourcePath);
 | 
			
		||||
        ~Water();
 | 
			
		||||
 | 
			
		||||
        void setCullCallback(osg::Callback* callback);
 | 
			
		||||
 | 
			
		||||
        void listAssetsToPreload(std::vector<std::string>& textures);
 | 
			
		||||
 | 
			
		||||
        void setEnabled(bool enabled);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -307,6 +307,38 @@ void loadRenderingNode(ViewData::Entry& entry, ViewData* vd, int vertexLodMod, C
 | 
			
		|||
        entry.mRenderingNode = chunkManager->getChunk(entry.mNode->getSize(), entry.mNode->getCenter(), ourLod, entry.mLodFlags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void updateWaterCullingView(HeightCullCallback* callback, ViewData* vd, osgUtil::CullVisitor* cv, float cellworldsize, bool outofworld)
 | 
			
		||||
{
 | 
			
		||||
    if (!(cv->getTraversalMask() & callback->getCullMask()))
 | 
			
		||||
        return;
 | 
			
		||||
    float lowZ = FLT_MAX;
 | 
			
		||||
    float highZ = callback->getHighZ();
 | 
			
		||||
    if (cv->getEyePoint().z() <= highZ || outofworld)
 | 
			
		||||
    {
 | 
			
		||||
        callback->setLowZ(-FLT_MAX);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    cv->pushCurrentMask();
 | 
			
		||||
    for (unsigned int i=0; i<vd->getNumEntries(); ++i)
 | 
			
		||||
    {
 | 
			
		||||
        ViewData::Entry& entry = vd->getEntry(i);
 | 
			
		||||
        osg::BoundingBox bb = static_cast<osg::Drawable*>(entry.mRenderingNode->asGroup()->getChild(0))->getBoundingBox();
 | 
			
		||||
        float minZ = bb._min.z();
 | 
			
		||||
        if (minZ > highZ)
 | 
			
		||||
            continue;
 | 
			
		||||
        osg::Vec3f ofs (entry.mNode->getCenter().x()*cellworldsize, entry.mNode->getCenter().y()*cellworldsize, 0.f);
 | 
			
		||||
        bb._min += ofs; bb._max += ofs;
 | 
			
		||||
        bb._min.z() = highZ;
 | 
			
		||||
        bb._max.z() = highZ;
 | 
			
		||||
        if (cv->isCulled(bb))
 | 
			
		||||
            continue;
 | 
			
		||||
        lowZ = minZ;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    callback->setLowZ(lowZ);
 | 
			
		||||
    cv->popCurrentMask();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void QuadTreeWorld::accept(osg::NodeVisitor &nv)
 | 
			
		||||
{
 | 
			
		||||
    bool isCullVisitor = nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR;
 | 
			
		||||
| 
						 | 
				
			
			@ -384,6 +416,9 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)
 | 
			
		|||
        entry.mRenderingNode->accept(nv);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isCullVisitor)
 | 
			
		||||
        updateWaterCullingView(mHeightCullCallback, vd, static_cast<osgUtil::CullVisitor*>(&nv), mStorage->getCellWorldSize(), !mGrid.empty());
 | 
			
		||||
 | 
			
		||||
    if (!isCullVisitor)
 | 
			
		||||
        vd->clear(); // we can't reuse intersection views in the next frame because they only contain what is touched by the intersection ray.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include <osg/Group>
 | 
			
		||||
#include <osg/ComputeBoundsVisitor>
 | 
			
		||||
 | 
			
		||||
#include "chunkmanager.hpp"
 | 
			
		||||
#include "compositemaprenderer.hpp"
 | 
			
		||||
| 
						 | 
				
			
			@ -80,6 +81,7 @@ void TerrainGrid::loadCell(int x, int y)
 | 
			
		|||
    mTerrainRoot->addChild(terrainNode);
 | 
			
		||||
 | 
			
		||||
    mGrid[std::make_pair(x,y)] = terrainNode;
 | 
			
		||||
    updateWaterCulling();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TerrainGrid::unloadCell(int x, int y)
 | 
			
		||||
| 
						 | 
				
			
			@ -94,6 +96,15 @@ void TerrainGrid::unloadCell(int x, int y)
 | 
			
		|||
    mTerrainRoot->removeChild(terrainNode);
 | 
			
		||||
 | 
			
		||||
    mGrid.erase(it);
 | 
			
		||||
    updateWaterCulling();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TerrainGrid::updateWaterCulling()
 | 
			
		||||
{
 | 
			
		||||
    osg::ComputeBoundsVisitor computeBoundsVisitor;
 | 
			
		||||
    mTerrainRoot->accept(computeBoundsVisitor);
 | 
			
		||||
    float lowZ = computeBoundsVisitor.getBoundingBox()._min.z();
 | 
			
		||||
    mHeightCullCallback->setLowZ(lowZ);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
View *TerrainGrid::createView()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,8 +27,9 @@ namespace Terrain
 | 
			
		|||
 | 
			
		||||
        View* createView();
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
    protected:
 | 
			
		||||
        osg::ref_ptr<osg::Node> buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter);
 | 
			
		||||
        void updateWaterCulling();
 | 
			
		||||
 | 
			
		||||
        // split each ESM::Cell into mNumSplits*mNumSplits terrain chunks
 | 
			
		||||
        unsigned int mNumSplits;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSyst
 | 
			
		|||
    , mParent(parent)
 | 
			
		||||
    , mResourceSystem(resourceSystem)
 | 
			
		||||
    , mBorderVisible(false)
 | 
			
		||||
    , mHeightCullCallback(new HeightCullCallback)
 | 
			
		||||
{
 | 
			
		||||
    mTerrainRoot = new osg::Group;
 | 
			
		||||
    mTerrainRoot->setNodeMask(nodeMask);
 | 
			
		||||
| 
						 | 
				
			
			@ -120,4 +121,11 @@ void World::clearAssociatedCaches()
 | 
			
		|||
    mChunkManager->clearCache();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
osg::Callback* World::getHeightCullCallback(float highz, unsigned int mask)
 | 
			
		||||
{
 | 
			
		||||
    mHeightCullCallback->setHighZ(highz);
 | 
			
		||||
    mHeightCullCallback->setCullMask(mask);
 | 
			
		||||
    return mHeightCullCallback;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@
 | 
			
		|||
#include <osg/ref_ptr>
 | 
			
		||||
#include <osg/Referenced>
 | 
			
		||||
#include <osg/Vec3f>
 | 
			
		||||
#include <osg/NodeCallback>
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <memory>
 | 
			
		||||
| 
						 | 
				
			
			@ -39,6 +40,37 @@ namespace Terrain
 | 
			
		|||
    class ChunkManager;
 | 
			
		||||
    class CompositeMapRenderer;
 | 
			
		||||
 | 
			
		||||
class HeightCullCallback : public osg::NodeCallback
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    HeightCullCallback() : mLowZ(-FLT_MAX), mHighZ(FLT_MAX), mMask(~0) {}
 | 
			
		||||
 | 
			
		||||
    void setLowZ(float z)
 | 
			
		||||
    {
 | 
			
		||||
        mLowZ = z;
 | 
			
		||||
    }
 | 
			
		||||
    float getLowZ() const { return mLowZ; }
 | 
			
		||||
 | 
			
		||||
    void setHighZ(float highZ)
 | 
			
		||||
    {
 | 
			
		||||
        mHighZ = highZ;
 | 
			
		||||
    }
 | 
			
		||||
    float getHighZ() const { return mHighZ; }
 | 
			
		||||
 | 
			
		||||
    void setCullMask(unsigned int mask) { mMask = mask; }
 | 
			
		||||
    unsigned int getCullMask() const { return mMask; }
 | 
			
		||||
 | 
			
		||||
    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
 | 
			
		||||
    {
 | 
			
		||||
        if (mLowZ <= mHighZ)
 | 
			
		||||
            traverse(node, nv);
 | 
			
		||||
    }
 | 
			
		||||
private:
 | 
			
		||||
    float mLowZ;
 | 
			
		||||
    float mHighZ;
 | 
			
		||||
    unsigned int mMask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @brief A View is a collection of rendering objects that are visible from a given camera/intersection.
 | 
			
		||||
     * The base View class is part of the interface for usage in conjunction with preload feature.
 | 
			
		||||
| 
						 | 
				
			
			@ -116,6 +148,8 @@ namespace Terrain
 | 
			
		|||
 | 
			
		||||
        Storage* getStorage() { return mStorage; }
 | 
			
		||||
 | 
			
		||||
        osg::Callback* getHeightCullCallback(float highz, unsigned int mask);
 | 
			
		||||
 | 
			
		||||
    protected:
 | 
			
		||||
        Storage* mStorage;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +169,7 @@ namespace Terrain
 | 
			
		|||
        bool mBorderVisible;
 | 
			
		||||
 | 
			
		||||
        std::set<std::pair<int,int>> mLoadedCells;
 | 
			
		||||
        osg::ref_ptr<HeightCullCallback> mHeightCullCallback;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue