Add LOD stitches

0.6.1
scrawl 8 years ago
parent 6bd286d924
commit bb991850da

@ -31,10 +31,10 @@ ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, T
}
osg::ref_ptr<osg::Node> ChunkManager::getChunk(float size, const osg::Vec2f &center, int lod)
osg::ref_ptr<osg::Node> ChunkManager::getChunk(float size, const osg::Vec2f &center, int lod, unsigned int lodFlags)
{
std::ostringstream stream;
stream << size << " " << center.x() << " " << center.y();
stream << size << " " << center.x() << " " << center.y() << " " << lod << " " << lodFlags;
std::string id = stream.str();
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(id);
@ -42,7 +42,7 @@ osg::ref_ptr<osg::Node> ChunkManager::getChunk(float size, const osg::Vec2f &cen
return obj->asNode();
else
{
osg::ref_ptr<osg::Node> node = createChunk(size, center, lod);
osg::ref_ptr<osg::Node> node = createChunk(size, center, lod, lodFlags);
mCache->addEntryToObjectCache(id, node.get());
return node;
}
@ -156,7 +156,7 @@ std::vector<osg::ref_ptr<osg::StateSet> > ChunkManager::createPasses(float chunk
mSceneManager->getClampLighting(), &mSceneManager->getShaderManager(), layers, blendmapTextures, blendmapScale, blendmapScale);
}
osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter, int lod)
osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter, int lod, unsigned int lodFlags)
{
osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize();
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> transform (new SceneUtil::PositionAttitudeTransform);
@ -182,7 +182,7 @@ osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Ve
unsigned int numVerts = (mStorage->getCellVertices()-1) * chunkSize / (1 << lod) + 1;
geometry->addPrimitiveSet(mBufferCache.getIndexBuffer(numVerts, 0));
geometry->addPrimitiveSet(mBufferCache.getIndexBuffer(numVerts, lodFlags));
geometry->getBound();

@ -34,12 +34,12 @@ namespace Terrain
public:
ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer);
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, int lod);
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, int lod, unsigned int lodFlags);
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const;
private:
osg::ref_ptr<osg::Node> createChunk(float size, const osg::Vec2f& center, int lod);
osg::ref_ptr<osg::Node> createChunk(float size, const osg::Vec2f& center, int lod, unsigned int lodFlags);
osg::ref_ptr<osg::Group> createCompositeMapRTT(osg::ref_ptr<osg::Texture2D>& texture);

@ -80,6 +80,11 @@ QuadTreeNode *QuadTreeNode::getChild(unsigned int i)
return static_cast<QuadTreeNode*>(Group::getChild(i));
}
QuadTreeNode *QuadTreeNode::getNeighbour(Direction dir)
{
return mNeighbours[dir];
}
void QuadTreeNode::initNeighbours()
{
for (int i=0; i<4; ++i)

@ -255,6 +255,34 @@ void traverse(QuadTreeNode* node, ViewData* vd, osgUtil::CullVisitor* cv, bool v
}
}
unsigned int getLodFlags(QuadTreeNode* node, int ourLod, ViewData* vd)
{
unsigned int lodFlags = 0;
for (unsigned int i=0; i<4; ++i)
{
QuadTreeNode* neighbour = node->getNeighbour(static_cast<Direction>(i));
// If the neighbour isn't currently rendering itself,
// go up until we find one. NOTE: We don't need to go down,
// because in that case neighbour's detail would be higher than
// our detail and the neighbour would handle stitching by itself.
while (neighbour && !vd->contains(neighbour))
neighbour = neighbour->getParent();
int lod = 0;
if (neighbour)
lod = Log2(int(neighbour->getSize()));
if (lod <= ourLod) // We only need to worry about neighbours less detailed than we are -
lod = 0; // neighbours with more detail will do the stitching themselves
// Use 4 bits for each LOD delta
if (lod > 0)
{
lodFlags |= static_cast<unsigned int>(lod - ourLod) << (4*i);
}
}
return lodFlags;
}
void QuadTreeWorld::accept(osg::NodeVisitor &nv)
{
if (nv.getVisitorType() != osg::NodeVisitor::CULL_VISITOR)// && nv.getVisitorType() != osg::NodeVisitor::INTERSECTION_VISITOR)
@ -275,8 +303,9 @@ void QuadTreeWorld::accept(osg::NodeVisitor &nv)
ViewData::Entry& entry = vd->getEntry(i);
if (!entry.mRenderingNode)
{
int lod = Log2(int(entry.mNode->getSize()));
entry.mRenderingNode = mChunkManager->getChunk(entry.mNode->getSize(), entry.mNode->getCenter(), lod);
int ourLod = Log2(int(entry.mNode->getSize()));
unsigned int lodFlags = getLodFlags(entry.mNode, ourLod, vd);
entry.mRenderingNode = mChunkManager->getChunk(entry.mNode->getSize(), entry.mNode->getCenter(), ourLod, lodFlags);
}
if (entry.mVisible)

@ -47,7 +47,7 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
}
else
{
osg::ref_ptr<osg::Node> node = mChunkManager->getChunk(chunkSize, chunkCenter, 0);
osg::ref_ptr<osg::Node> node = mChunkManager->getChunk(chunkSize, chunkCenter, 0, 0);
if (!node)
return NULL;
if (parent)

@ -54,6 +54,14 @@ void ViewData::clear()
mFrameLastUsed = 0;
}
bool ViewData::contains(QuadTreeNode *node)
{
for (unsigned int i=0; i<mNumEntries; ++i)
if (mEntries[i].mNode == node)
return true;
return false;
}
ViewData::Entry::Entry()
: mNode(NULL)
, mVisible(true)

@ -22,6 +22,8 @@ namespace Terrain
void clear();
bool contains(QuadTreeNode* node);
struct Entry
{
Entry();

Loading…
Cancel
Save