mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 17:59:56 +00:00
Merge branch 'bzzt_1_waterculling' into 'master'
waterculling See merge request OpenMW/openmw!184
This commit is contained in:
commit
3b9a51b8ac
11 changed files with 194 additions and 5 deletions
|
@ -282,8 +282,6 @@ namespace MWRender
|
||||||
|
|
||||||
mEffectManager.reset(new EffectManager(sceneRoot, mResourceSystem));
|
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");
|
DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog");
|
||||||
DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog");
|
DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog");
|
||||||
DLUnderwaterFogStart = Settings::Manager::getFloat("distant underwater fog start", "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->setTargetFrameRate(Settings::Manager::getFloat("target framerate", "Cells"));
|
||||||
mTerrain->setWorkQueue(mWorkQueue.get());
|
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()));
|
mCamera.reset(new Camera(mViewer->getCamera()));
|
||||||
|
|
||||||
mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
|
mViewer->setLightingMode(osgViewer::View::NO_LIGHT);
|
||||||
|
@ -541,6 +542,8 @@ namespace MWRender
|
||||||
|
|
||||||
void RenderingManager::enableTerrain(bool enable)
|
void RenderingManager::enableTerrain(bool enable)
|
||||||
{
|
{
|
||||||
|
if (!enable)
|
||||||
|
mWater->setCullCallback(nullptr);
|
||||||
mTerrain->enable(enable);
|
mTerrain->enable(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,6 +743,7 @@ namespace MWRender
|
||||||
|
|
||||||
void RenderingManager::setWaterHeight(float height)
|
void RenderingManager::setWaterHeight(float height)
|
||||||
{
|
{
|
||||||
|
mWater->setCullCallback(mTerrain->getHeightCullCallback(height, Mask_Water));
|
||||||
mWater->setHeight(height);
|
mWater->setHeight(height);
|
||||||
mSky->setWaterHeight(height);
|
mSky->setWaterHeight(height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -436,6 +436,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
|
||||||
, mToggled(true)
|
, mToggled(true)
|
||||||
, mTop(0)
|
, mTop(0)
|
||||||
, mInterior(false)
|
, mInterior(false)
|
||||||
|
, mCullCallback(nullptr)
|
||||||
{
|
{
|
||||||
mSimulation.reset(new RippleSimulation(mSceneRoot, resourceSystem));
|
mSimulation.reset(new RippleSimulation(mSceneRoot, resourceSystem));
|
||||||
|
|
||||||
|
@ -466,6 +467,29 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
|
||||||
ico->add(mWaterNode);
|
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()
|
osg::Uniform *Water::getRainIntensityUniform()
|
||||||
{
|
{
|
||||||
return mRainIntensityUniform.get();
|
return mRainIntensityUniform.get();
|
||||||
|
@ -491,6 +515,8 @@ void Water::updateWaterMaterial()
|
||||||
mReflection = new Reflection(mInterior);
|
mReflection = new Reflection(mInterior);
|
||||||
mReflection->setWaterLevel(mTop);
|
mReflection->setWaterLevel(mTop);
|
||||||
mReflection->setScene(mSceneRoot);
|
mReflection->setScene(mSceneRoot);
|
||||||
|
if (mCullCallback)
|
||||||
|
mReflection->addCullCallback(mCullCallback);
|
||||||
mParent->addChild(mReflection);
|
mParent->addChild(mReflection);
|
||||||
|
|
||||||
if (Settings::Manager::getBool("refraction", "Water"))
|
if (Settings::Manager::getBool("refraction", "Water"))
|
||||||
|
@ -498,6 +524,8 @@ void Water::updateWaterMaterial()
|
||||||
mRefraction = new Refraction;
|
mRefraction = new Refraction;
|
||||||
mRefraction->setWaterLevel(mTop);
|
mRefraction->setWaterLevel(mTop);
|
||||||
mRefraction->setScene(mSceneRoot);
|
mRefraction->setScene(mSceneRoot);
|
||||||
|
if (mCullCallback)
|
||||||
|
mRefraction->addCullCallback(mCullCallback);
|
||||||
mParent->addChild(mRefraction);
|
mParent->addChild(mRefraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,8 @@ namespace MWRender
|
||||||
float mTop;
|
float mTop;
|
||||||
bool mInterior;
|
bool mInterior;
|
||||||
|
|
||||||
|
osg::Callback* mCullCallback;
|
||||||
|
|
||||||
osg::Vec3f getSceneNodeCoordinates(int gridX, int gridY);
|
osg::Vec3f getSceneNodeCoordinates(int gridX, int gridY);
|
||||||
void updateVisible();
|
void updateVisible();
|
||||||
|
|
||||||
|
@ -88,6 +90,8 @@ namespace MWRender
|
||||||
const std::string& resourcePath);
|
const std::string& resourcePath);
|
||||||
~Water();
|
~Water();
|
||||||
|
|
||||||
|
void setCullCallback(osg::Callback* callback);
|
||||||
|
|
||||||
void listAssetsToPreload(std::vector<std::string>& textures);
|
void listAssetsToPreload(std::vector<std::string>& textures);
|
||||||
|
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
|
|
|
@ -227,6 +227,8 @@ osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Ve
|
||||||
transform->addChild(geometry);
|
transform->addChild(geometry);
|
||||||
transform->getBound();
|
transform->getBound();
|
||||||
|
|
||||||
|
geometry->setupWaterBoundingBox(-1, chunkSize * mStorage->getCellWorldSize() / numVerts);
|
||||||
|
|
||||||
if (mSceneManager->getIncrementalCompileOperation())
|
if (mSceneManager->getIncrementalCompileOperation())
|
||||||
{
|
{
|
||||||
mSceneManager->getIncrementalCompileOperation()->add(geometry);
|
mSceneManager->getIncrementalCompileOperation()->add(geometry);
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#include "quadtreeworld.hpp"
|
#include "quadtreeworld.hpp"
|
||||||
|
|
||||||
#include <osgUtil/CullVisitor>
|
#include <osgUtil/CullVisitor>
|
||||||
|
#include <osg/ShapeDrawable>
|
||||||
|
#include <osg/PolygonMode>
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
|
@ -12,6 +15,7 @@
|
||||||
#include "viewdata.hpp"
|
#include "viewdata.hpp"
|
||||||
#include "chunkmanager.hpp"
|
#include "chunkmanager.hpp"
|
||||||
#include "compositemaprenderer.hpp"
|
#include "compositemaprenderer.hpp"
|
||||||
|
#include "terraindrawable.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -307,6 +311,59 @@ void loadRenderingNode(ViewData::Entry& entry, ViewData* vd, int vertexLodMod, C
|
||||||
entry.mRenderingNode = chunkManager->getChunk(entry.mNode->getSize(), entry.mNode->getCenter(), ourLod, entry.mLodFlags);
|
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 = std::numeric_limits<float>::max();
|
||||||
|
float highZ = callback->getHighZ();
|
||||||
|
if (cv->getEyePoint().z() <= highZ || outofworld)
|
||||||
|
{
|
||||||
|
callback->setLowZ(-std::numeric_limits<float>::max());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cv->pushCurrentMask();
|
||||||
|
for (unsigned int i=0; i<vd->getNumEntries(); ++i)
|
||||||
|
{
|
||||||
|
ViewData::Entry& entry = vd->getEntry(i);
|
||||||
|
osg::BoundingBox bb = static_cast<TerrainDrawable*>(entry.mRenderingNode->asGroup()->getChild(0))->getWaterBoundingBox();
|
||||||
|
if (!bb.valid())
|
||||||
|
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 = bb._min.z();
|
||||||
|
|
||||||
|
static bool debug = getenv("OPENMW_WATER_CULLING_DEBUG") != nullptr;
|
||||||
|
if (!debug)
|
||||||
|
break;
|
||||||
|
osg::Box* b = new osg::Box;
|
||||||
|
b->set(bb.center(), bb._max - bb.center());
|
||||||
|
osg::ShapeDrawable* drw = new osg::ShapeDrawable(b);
|
||||||
|
static osg::ref_ptr<osg::StateSet> stateset = nullptr;
|
||||||
|
if (!stateset)
|
||||||
|
{
|
||||||
|
stateset = new osg::StateSet;
|
||||||
|
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||||
|
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||||
|
stateset->setAttributeAndModes(new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE), osg::StateAttribute::ON);
|
||||||
|
osg::Material* m = new osg::Material;
|
||||||
|
m->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,1,1));
|
||||||
|
m->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,1));
|
||||||
|
m->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(0,0,0,1));
|
||||||
|
stateset->setAttributeAndModes(m, osg::StateAttribute::ON);
|
||||||
|
stateset->setRenderBinDetails(100,"RenderBin");
|
||||||
|
}
|
||||||
|
drw->setStateSet(stateset);
|
||||||
|
drw->accept(*cv);
|
||||||
|
}
|
||||||
|
callback->setLowZ(lowZ);
|
||||||
|
cv->popCurrentMask();
|
||||||
|
}
|
||||||
|
|
||||||
void QuadTreeWorld::accept(osg::NodeVisitor &nv)
|
void QuadTreeWorld::accept(osg::NodeVisitor &nv)
|
||||||
{
|
{
|
||||||
bool isCullVisitor = nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR;
|
bool isCullVisitor = nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR;
|
||||||
|
@ -384,6 +441,9 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)
|
||||||
entry.mRenderingNode->accept(nv);
|
entry.mRenderingNode->accept(nv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isCullVisitor)
|
||||||
|
updateWaterCullingView(mHeightCullCallback, vd, static_cast<osgUtil::CullVisitor*>(&nv), mStorage->getCellWorldSize(), !isGridEmpty());
|
||||||
|
|
||||||
if (!isCullVisitor)
|
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.
|
vd->clear(); // we can't reuse intersection views in the next frame because they only contain what is touched by the intersection ray.
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,16 @@
|
||||||
namespace Terrain
|
namespace Terrain
|
||||||
{
|
{
|
||||||
|
|
||||||
|
TerrainDrawable::TerrainDrawable()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TerrainDrawable::~TerrainDrawable()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
TerrainDrawable::TerrainDrawable(const TerrainDrawable ©, const osg::CopyOp ©op)
|
TerrainDrawable::TerrainDrawable(const TerrainDrawable ©, const osg::CopyOp ©op)
|
||||||
: osg::Geometry(copy, copyop)
|
: osg::Geometry(copy, copyop)
|
||||||
, mPasses(copy.mPasses)
|
, mPasses(copy.mPasses)
|
||||||
|
@ -118,6 +128,25 @@ void TerrainDrawable::setLightListCallback(SceneUtil::LightListCallback *lightLi
|
||||||
mLightListCallback = lightListCallback;
|
mLightListCallback = lightListCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerrainDrawable::setupWaterBoundingBox(float waterheight, float margin)
|
||||||
|
{
|
||||||
|
osg::Vec3Array* vertices = static_cast<osg::Vec3Array*>(getVertexArray());
|
||||||
|
for (unsigned int i=0; i<vertices->size(); ++i)
|
||||||
|
{
|
||||||
|
const osg::Vec3f& vertex = (*vertices)[i];
|
||||||
|
if (vertex.z() <= waterheight)
|
||||||
|
mWaterBoundingBox.expandBy(vertex);
|
||||||
|
}
|
||||||
|
if (mWaterBoundingBox.valid())
|
||||||
|
{
|
||||||
|
const osg::BoundingBox& bb = getBoundingBox();
|
||||||
|
mWaterBoundingBox.xMin() = std::max(bb.xMin(), mWaterBoundingBox.xMin() - margin);
|
||||||
|
mWaterBoundingBox.yMin() = std::max(bb.yMin(), mWaterBoundingBox.yMin() - margin);
|
||||||
|
mWaterBoundingBox.xMax() = std::min(bb.xMax(), mWaterBoundingBox.xMax() + margin);
|
||||||
|
mWaterBoundingBox.xMax() = std::min(bb.xMax(), mWaterBoundingBox.xMax() + margin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TerrainDrawable::compileGLObjects(osg::RenderInfo &renderInfo) const
|
void TerrainDrawable::compileGLObjects(osg::RenderInfo &renderInfo) const
|
||||||
{
|
{
|
||||||
for (PassVector::const_iterator it = mPasses.begin(); it != mPasses.end(); ++it)
|
for (PassVector::const_iterator it = mPasses.begin(); it != mPasses.end(); ++it)
|
||||||
|
|
|
@ -36,8 +36,8 @@ namespace Terrain
|
||||||
virtual const char* className() const { return "TerrainDrawable"; }
|
virtual const char* className() const { return "TerrainDrawable"; }
|
||||||
virtual const char* libraryName() const { return "Terrain"; }
|
virtual const char* libraryName() const { return "Terrain"; }
|
||||||
|
|
||||||
TerrainDrawable() = default;
|
TerrainDrawable();
|
||||||
~TerrainDrawable() = default;
|
~TerrainDrawable(); // has to be defined in the cpp file because we only forward declared some members.
|
||||||
TerrainDrawable(const TerrainDrawable& copy, const osg::CopyOp& copyop);
|
TerrainDrawable(const TerrainDrawable& copy, const osg::CopyOp& copyop);
|
||||||
|
|
||||||
virtual void accept(osg::NodeVisitor &nv);
|
virtual void accept(osg::NodeVisitor &nv);
|
||||||
|
@ -52,10 +52,14 @@ namespace Terrain
|
||||||
|
|
||||||
virtual void compileGLObjects(osg::RenderInfo& renderInfo) const;
|
virtual void compileGLObjects(osg::RenderInfo& renderInfo) const;
|
||||||
|
|
||||||
|
void setupWaterBoundingBox(float waterheight, float margin);
|
||||||
|
const osg::BoundingBox& getWaterBoundingBox() const { return mWaterBoundingBox; }
|
||||||
|
|
||||||
void setCompositeMap(CompositeMap* map) { mCompositeMap = map; }
|
void setCompositeMap(CompositeMap* map) { mCompositeMap = map; }
|
||||||
void setCompositeMapRenderer(CompositeMapRenderer* renderer) { mCompositeMapRenderer = renderer; }
|
void setCompositeMapRenderer(CompositeMapRenderer* renderer) { mCompositeMapRenderer = renderer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
osg::BoundingBox mWaterBoundingBox;
|
||||||
PassVector mPasses;
|
PassVector mPasses;
|
||||||
|
|
||||||
osg::ref_ptr<osg::ClusterCullingCallback> mClusterCullingCallback;
|
osg::ref_ptr<osg::ClusterCullingCallback> mClusterCullingCallback;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <osg/Group>
|
#include <osg/Group>
|
||||||
|
#include <osg/ComputeBoundsVisitor>
|
||||||
|
|
||||||
#include "chunkmanager.hpp"
|
#include "chunkmanager.hpp"
|
||||||
#include "compositemaprenderer.hpp"
|
#include "compositemaprenderer.hpp"
|
||||||
|
@ -80,6 +81,7 @@ void TerrainGrid::loadCell(int x, int y)
|
||||||
mTerrainRoot->addChild(terrainNode);
|
mTerrainRoot->addChild(terrainNode);
|
||||||
|
|
||||||
mGrid[std::make_pair(x,y)] = terrainNode;
|
mGrid[std::make_pair(x,y)] = terrainNode;
|
||||||
|
updateWaterCulling();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainGrid::unloadCell(int x, int y)
|
void TerrainGrid::unloadCell(int x, int y)
|
||||||
|
@ -94,6 +96,15 @@ void TerrainGrid::unloadCell(int x, int y)
|
||||||
mTerrainRoot->removeChild(terrainNode);
|
mTerrainRoot->removeChild(terrainNode);
|
||||||
|
|
||||||
mGrid.erase(it);
|
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()
|
View *TerrainGrid::createView()
|
||||||
|
|
|
@ -27,8 +27,12 @@ namespace Terrain
|
||||||
|
|
||||||
View* createView();
|
View* createView();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool isGridEmpty() const { return mGrid.empty(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::Node> buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter);
|
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
|
// split each ESM::Cell into mNumSplits*mNumSplits terrain chunks
|
||||||
unsigned int mNumSplits;
|
unsigned int mNumSplits;
|
||||||
|
|
|
@ -19,6 +19,7 @@ World::World(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSyst
|
||||||
, mParent(parent)
|
, mParent(parent)
|
||||||
, mResourceSystem(resourceSystem)
|
, mResourceSystem(resourceSystem)
|
||||||
, mBorderVisible(false)
|
, mBorderVisible(false)
|
||||||
|
, mHeightCullCallback(new HeightCullCallback)
|
||||||
{
|
{
|
||||||
mTerrainRoot = new osg::Group;
|
mTerrainRoot = new osg::Group;
|
||||||
mTerrainRoot->setNodeMask(nodeMask);
|
mTerrainRoot->setNodeMask(nodeMask);
|
||||||
|
@ -120,4 +121,11 @@ void World::clearAssociatedCaches()
|
||||||
mChunkManager->clearCache();
|
mChunkManager->clearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::Callback* World::getHeightCullCallback(float highz, unsigned int mask)
|
||||||
|
{
|
||||||
|
mHeightCullCallback->setHighZ(highz);
|
||||||
|
mHeightCullCallback->setCullMask(mask);
|
||||||
|
return mHeightCullCallback;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,12 @@
|
||||||
#include <osg/ref_ptr>
|
#include <osg/ref_ptr>
|
||||||
#include <osg/Referenced>
|
#include <osg/Referenced>
|
||||||
#include <osg/Vec3f>
|
#include <osg/Vec3f>
|
||||||
|
#include <osg/NodeCallback>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#include "defs.hpp"
|
#include "defs.hpp"
|
||||||
#include "cellborder.hpp"
|
#include "cellborder.hpp"
|
||||||
|
@ -39,6 +40,37 @@ namespace Terrain
|
||||||
class ChunkManager;
|
class ChunkManager;
|
||||||
class CompositeMapRenderer;
|
class CompositeMapRenderer;
|
||||||
|
|
||||||
|
class HeightCullCallback : public osg::NodeCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HeightCullCallback() : mLowZ(-std::numeric_limits<float>::max()), mHighZ(std::numeric_limits<float>::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.
|
* @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.
|
* 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; }
|
Storage* getStorage() { return mStorage; }
|
||||||
|
|
||||||
|
osg::Callback* getHeightCullCallback(float highz, unsigned int mask);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Storage* mStorage;
|
Storage* mStorage;
|
||||||
|
|
||||||
|
@ -135,6 +169,7 @@ namespace Terrain
|
||||||
bool mBorderVisible;
|
bool mBorderVisible;
|
||||||
|
|
||||||
std::set<std::pair<int,int>> mLoadedCells;
|
std::set<std::pair<int,int>> mLoadedCells;
|
||||||
|
osg::ref_ptr<HeightCullCallback> mHeightCullCallback;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue