From 48713915cb21b86f515fd5d1e95808d8ad56bf17 Mon Sep 17 00:00:00 2001 From: Bret Curtis Date: Thu, 23 Apr 2020 11:12:10 +0200 Subject: [PATCH] re-use bzzts waterplane overlay for debug; makes it easier to test. To use this, set the env OPENMW_WATER_CULLING_DEBUG=1; You will see blue rectangles corresponding to water outlines. Once there are no more outlines, water is culled. You can further see this by pressing F3 3 times to check the the amount of quads. Before culling it should be around 1600, after culling it should drop to 0. --- components/terrain/chunkmanager.cpp | 2 ++ components/terrain/quadtreeworld.cpp | 34 ++++++++++++++++++++++---- components/terrain/terraindrawable.cpp | 29 ++++++++++++++++++++++ components/terrain/terraindrawable.hpp | 8 ++++-- 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/components/terrain/chunkmanager.cpp b/components/terrain/chunkmanager.cpp index 3c76945d3..95c1ca491 100644 --- a/components/terrain/chunkmanager.cpp +++ b/components/terrain/chunkmanager.cpp @@ -227,6 +227,8 @@ osg::ref_ptr ChunkManager::createChunk(float chunkSize, const osg::Ve transform->addChild(geometry); transform->getBound(); + geometry->setupWaterBoundingBox(-1, chunkSize * mStorage->getCellWorldSize() / numVerts); + if (mSceneManager->getIncrementalCompileOperation()) { mSceneManager->getIncrementalCompileOperation()->add(geometry); diff --git a/components/terrain/quadtreeworld.cpp b/components/terrain/quadtreeworld.cpp index 56fa8b7f3..ae3656fd2 100644 --- a/components/terrain/quadtreeworld.cpp +++ b/components/terrain/quadtreeworld.cpp @@ -1,6 +1,8 @@ #include "quadtreeworld.hpp" #include +#include +#include #include #include @@ -13,6 +15,7 @@ #include "viewdata.hpp" #include "chunkmanager.hpp" #include "compositemaprenderer.hpp" +#include "terraindrawable.hpp" namespace { @@ -323,9 +326,8 @@ void updateWaterCullingView(HeightCullCallback* callback, ViewData* vd, osgUtil: for (unsigned int i=0; igetNumEntries(); ++i) { ViewData::Entry& entry = vd->getEntry(i); - osg::BoundingBox bb = static_cast(entry.mRenderingNode->asGroup()->getChild(0))->getBoundingBox(); - float minZ = bb._min.z(); - if (minZ > highZ) + osg::BoundingBox bb = static_cast(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; @@ -333,8 +335,30 @@ void updateWaterCullingView(HeightCullCallback* callback, ViewData* vd, osgUtil: bb._max.z() = highZ; if (cv->isCulled(bb)) continue; - lowZ = minZ; - break; + 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 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(); diff --git a/components/terrain/terraindrawable.cpp b/components/terrain/terraindrawable.cpp index c37074dac..9593687cf 100644 --- a/components/terrain/terraindrawable.cpp +++ b/components/terrain/terraindrawable.cpp @@ -10,6 +10,16 @@ namespace Terrain { +TerrainDrawable::TerrainDrawable() +{ + +} + +TerrainDrawable::~TerrainDrawable() +{ + +} + TerrainDrawable::TerrainDrawable(const TerrainDrawable ©, const osg::CopyOp ©op) : osg::Geometry(copy, copyop) , mPasses(copy.mPasses) @@ -118,6 +128,25 @@ void TerrainDrawable::setLightListCallback(SceneUtil::LightListCallback *lightLi mLightListCallback = lightListCallback; } +void TerrainDrawable::setupWaterBoundingBox(float waterheight, float margin) +{ + osg::Vec3Array* vertices = static_cast(getVertexArray()); + for (unsigned int i=0; isize(); ++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 { for (PassVector::const_iterator it = mPasses.begin(); it != mPasses.end(); ++it) diff --git a/components/terrain/terraindrawable.hpp b/components/terrain/terraindrawable.hpp index 516b1abdb..a84200f66 100644 --- a/components/terrain/terraindrawable.hpp +++ b/components/terrain/terraindrawable.hpp @@ -36,8 +36,8 @@ namespace Terrain virtual const char* className() const { return "TerrainDrawable"; } virtual const char* libraryName() const { return "Terrain"; } - TerrainDrawable() = default; - ~TerrainDrawable() = default; + TerrainDrawable(); + ~TerrainDrawable(); // has to be defined in the cpp file because we only forward declared some members. TerrainDrawable(const TerrainDrawable& copy, const osg::CopyOp& copyop); virtual void accept(osg::NodeVisitor &nv); @@ -52,10 +52,14 @@ namespace Terrain 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 setCompositeMapRenderer(CompositeMapRenderer* renderer) { mCompositeMapRenderer = renderer; } private: + osg::BoundingBox mWaterBoundingBox; PassVector mPasses; osg::ref_ptr mClusterCullingCallback;