1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-04 02:41:19 +00:00
OpenMW/components/terrain/terraingrid.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

138 lines
4.3 KiB
C++
Raw Normal View History

#include "terraingrid.hpp"
2015-06-02 23:18:36 +00:00
#include <memory>
2019-06-13 13:37:00 +00:00
#include <osg/ComputeBoundsVisitor>
#include <osg/Group>
#include "chunkmanager.hpp"
#include "heightcull.hpp"
#include "storage.hpp"
#include "view.hpp"
#include <components/sceneutil/positionattitudetransform.hpp>
namespace Terrain
{
class MyView : public View
{
public:
osg::ref_ptr<osg::Node> mLoaded;
void reset() override {}
};
TerrainGrid::TerrainGrid(osg::Group* parent, osg::Group* compileRoot, Resource::ResourceSystem* resourceSystem,
Storage* storage, unsigned int nodeMask, ESM::RefId worldspace, double expiryDelay, unsigned int preCompileMask,
unsigned int borderMask)
: Terrain::World(
parent, compileRoot, resourceSystem, storage, nodeMask, preCompileMask, borderMask, worldspace, expiryDelay)
2020-01-12 07:42:47 +00:00
, mNumSplits(4)
{
}
TerrainGrid::TerrainGrid(osg::Group* parent, Storage* storage, ESM::RefId worldspace, unsigned int nodeMask)
: Terrain::World(parent, storage, nodeMask, worldspace)
2018-06-14 10:27:22 +00:00
, mNumSplits(4)
{
}
TerrainGrid::~TerrainGrid()
2016-02-09 19:57:30 +00:00
{
2018-10-09 06:21:12 +00:00
while (!mGrid.empty())
2022-09-22 18:26:05 +00:00
{
2018-10-09 06:21:12 +00:00
TerrainGrid::unloadCell(mGrid.begin()->first.first, mGrid.begin()->first.second);
2022-09-22 18:26:05 +00:00
}
2016-02-09 19:57:30 +00:00
}
void TerrainGrid::cacheCell(View* view, int x, int y)
{
osg::Vec2f center(x + 0.5f, y + 0.5f);
static_cast<MyView*>(view)->mLoaded = buildTerrain(nullptr, 1.f, center);
}
2022-09-22 18:26:05 +00:00
2018-10-09 06:21:12 +00:00
osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain(
osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter)
{
if (chunkSize * mNumSplits > 1.f)
2022-09-22 18:26:05 +00:00
{
// keep splitting
osg::ref_ptr<osg::Group> group(new osg::Group);
if (parent)
parent->addChild(group);
2022-09-22 18:26:05 +00:00
float newChunkSize = chunkSize / 2.f;
buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize / 2.f, newChunkSize / 2.f));
buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(newChunkSize / 2.f, -newChunkSize / 2.f));
buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(-newChunkSize / 2.f, newChunkSize / 2.f));
buildTerrain(group, newChunkSize, chunkCenter + osg::Vec2f(-newChunkSize / 2.f, -newChunkSize / 2.f));
return group;
2022-09-22 18:26:05 +00:00
}
else
{
osg::ref_ptr<osg::Node> node
= mChunkManager->getChunk(chunkSize, chunkCenter, 0, 0, false, osg::Vec3f(), true);
if (!node)
2018-10-09 06:21:12 +00:00
return nullptr;
2022-09-22 18:26:05 +00:00
const float cellWorldSize = mStorage->getCellWorldSize(mWorldspace);
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> pat = new SceneUtil::PositionAttitudeTransform;
pat->setPosition(osg::Vec3f(chunkCenter.x() * cellWorldSize, chunkCenter.y() * cellWorldSize, 0.f));
pat->addChild(node);
if (parent)
parent->addChild(pat);
return pat;
2022-09-22 18:26:05 +00:00
}
2015-06-02 23:18:36 +00:00
}
void TerrainGrid::loadCell(int x, int y)
{
if (mGrid.find(std::make_pair(x, y)) != mGrid.end())
return; // already loaded
osg::Vec2f center(x + 0.5f, y + 0.5f);
2018-10-09 06:21:12 +00:00
osg::ref_ptr<osg::Node> terrainNode = buildTerrain(nullptr, 1.f, center);
if (!terrainNode)
return; // no terrain defined
2018-06-14 10:27:22 +00:00
TerrainGrid::World::loadCell(x, y);
2018-06-12 23:48:31 +00:00
2016-02-09 19:23:53 +00:00
mTerrainRoot->addChild(terrainNode);
2016-02-09 19:23:53 +00:00
mGrid[std::make_pair(x, y)] = terrainNode;
2019-06-13 13:37:00 +00:00
updateWaterCulling();
}
2015-06-02 23:18:36 +00:00
void TerrainGrid::unloadCell(int x, int y)
{
CellBorder::CellGrid::iterator it = mGrid.find(std::make_pair(x, y));
if (it == mGrid.end())
2015-06-02 23:18:36 +00:00
return;
2018-06-14 10:27:22 +00:00
Terrain::World::unloadCell(x, y);
2018-06-14 10:01:09 +00:00
2016-02-09 19:57:30 +00:00
osg::ref_ptr<osg::Node> terrainNode = it->second;
2016-02-09 19:23:53 +00:00
mTerrainRoot->removeChild(terrainNode);
2015-06-02 23:18:36 +00:00
mGrid.erase(it);
2019-06-13 13:37:00 +00:00
updateWaterCulling();
}
void TerrainGrid::updateWaterCulling()
{
2020-01-12 07:42:47 +00:00
if (!mHeightCullCallback)
return;
2019-06-13 13:37:00 +00:00
osg::ComputeBoundsVisitor computeBoundsVisitor;
mTerrainRoot->accept(computeBoundsVisitor);
float lowZ = computeBoundsVisitor.getBoundingBox()._min.z();
mHeightCullCallback->setLowZ(lowZ);
}
View* TerrainGrid::createView()
{
return new MyView;
}
}