forked from teamnwah/openmw-tes3coop
Add LOD stitches
This commit is contained in:
parent
6bd286d924
commit
bb991850da
7 changed files with 54 additions and 10 deletions
|
@ -31,10 +31,10 @@ ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, T
|
|||
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> ChunkManager::getChunk(float size, const osg::Vec2f ¢er, int lod)
|
||||
osg::ref_ptr<osg::Node> ChunkManager::getChunk(float size, const osg::Vec2f ¢er, 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…
Reference in a new issue