Subdivide the composite maps

0.6.1
scrawl 8 years ago
parent c684860e3b
commit 0efc54c749

@ -31,7 +31,7 @@ ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, T
} }
osg::ref_ptr<osg::Node> ChunkManager::getChunk(float size, const osg::Vec2f &center) osg::ref_ptr<osg::Node> ChunkManager::getChunk(float size, const osg::Vec2f &center, int lod)
{ {
std::ostringstream stream; std::ostringstream stream;
stream << size << " " << center.x() << " " << center.y(); stream << size << " " << center.x() << " " << center.y();
@ -42,7 +42,7 @@ osg::ref_ptr<osg::Node> ChunkManager::getChunk(float size, const osg::Vec2f &cen
return obj->asNode(); return obj->asNode();
else else
{ {
osg::ref_ptr<osg::Node> node = createChunk(size, center); osg::ref_ptr<osg::Node> node = createChunk(size, center, lod);
mCache->addEntryToObjectCache(id, node.get()); mCache->addEntryToObjectCache(id, node.get());
return node; return node;
} }
@ -80,44 +80,44 @@ osg::ref_ptr<osg::Group> ChunkManager::createCompositeMapRTT(osg::ref_ptr<osg::T
return camera; return camera;
} }
osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter) void ChunkManager::createCompositeMapGeometry(float chunkSize, const osg::Vec2f& chunkCenter, const osg::Vec4f& texCoords, osg::Group* compositeMapNode)
{ {
osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize(); if (chunkSize > 1.f)
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> transform (new SceneUtil::PositionAttitudeTransform); {
transform->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f)); createCompositeMapGeometry(chunkSize/2.f, chunkCenter + osg::Vec2f(chunkSize/4.f, chunkSize/4.f), osg::Vec4f(texCoords.x() + texCoords.z()/2.f, texCoords.y(), texCoords.z()/2.f, texCoords.w()/2.f), compositeMapNode);
createCompositeMapGeometry(chunkSize/2.f, chunkCenter + osg::Vec2f(-chunkSize/4.f, chunkSize/4.f), osg::Vec4f(texCoords.x(), texCoords.y(), texCoords.z()/2.f, texCoords.w()/2.f), compositeMapNode);
osg::ref_ptr<osg::Vec3Array> positions (new osg::Vec3Array); createCompositeMapGeometry(chunkSize/2.f, chunkCenter + osg::Vec2f(chunkSize/4.f, -chunkSize/4.f), osg::Vec4f(texCoords.x() + texCoords.z()/2.f, texCoords.y()+texCoords.w()/2.f, texCoords.z()/2.f, texCoords.w()/2.f), compositeMapNode);
osg::ref_ptr<osg::Vec3Array> normals (new osg::Vec3Array); createCompositeMapGeometry(chunkSize/2.f, chunkCenter + osg::Vec2f(-chunkSize/4.f, -chunkSize/4.f), osg::Vec4f(texCoords.x(), texCoords.y()+ texCoords.w()/2.f, texCoords.z()/2.f, texCoords.w()/2.f), compositeMapNode);
osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array); }
else
osg::ref_ptr<osg::VertexBufferObject> vbo (new osg::VertexBufferObject); {
positions->setVertexBufferObject(vbo); float left = texCoords.x()*2.f-1;
normals->setVertexBufferObject(vbo); float top = texCoords.y()*2.f-1;
colors->setVertexBufferObject(vbo); float width = texCoords.z()*2.f;
float height = texCoords.w()*2.f;
unsigned int lod = 0;
mStorage->fillVertexBuffers(lod, chunkSize, chunkCenter, positions, normals, colors);
osg::ref_ptr<TerrainDrawable> geometry (new TerrainDrawable);
geometry->setVertexArray(positions);
geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
geometry->setUseDisplayList(false);
geometry->setUseVertexBufferObjects(true);
unsigned int numVerts = (mStorage->getCellVertices()-1) * chunkSize / (1 << lod) + 1;
geometry->addPrimitiveSet(mBufferCache.getIndexBuffer(numVerts, 0)); osg::ref_ptr<osg::Geometry> geom = osg::createTexturedQuadGeometry(osg::Vec3(left,top,0), osg::Vec3(width,0,0), osg::Vec3(0,height,0));
geom->setTexCoordArray(1, geom->getTexCoordArray(0), osg::Array::BIND_PER_VERTEX);
geometry->getBound(); std::vector<osg::ref_ptr<osg::StateSet> > passes = createPasses(chunkSize, chunkCenter, true);
for (std::vector<osg::ref_ptr<osg::StateSet> >::iterator it = passes.begin(); it != passes.end(); ++it)
{
osg::ref_ptr<osg::Group> group = new osg::Group;
group->setStateSet(*it);
group->addChild(geom);
compositeMapNode->addChild(group);
}
}
}
std::vector<osg::ref_ptr<osg::StateSet> > ChunkManager::createPasses(float chunkSize, const osg::Vec2f &chunkCenter, bool forCompositeMap)
{
std::vector<LayerInfo> layerList; std::vector<LayerInfo> layerList;
std::vector<osg::ref_ptr<osg::Image> > blendmaps; std::vector<osg::ref_ptr<osg::Image> > blendmaps;
mStorage->getBlendmaps(chunkSize, chunkCenter, false, blendmaps, layerList); mStorage->getBlendmaps(chunkSize, chunkCenter, false, blendmaps, layerList);
bool useShaders = mSceneManager->getForceShaders(); bool useShaders = mSceneManager->getForceShaders();
if (!mSceneManager->getClampLighting()) if (!mSceneManager->getClampLighting() && !forCompositeMap)
useShaders = true; // always use shaders when lighting is unclamped, this is to avoid lighting seams between a terrain chunk with normal maps and one without normal maps useShaders = true; // always use shaders when lighting is unclamped, this is to avoid lighting seams between a terrain chunk with normal maps and one without normal maps
std::vector<TextureLayer> layers; std::vector<TextureLayer> layers;
{ {
@ -129,7 +129,7 @@ osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Ve
textureLayer.mDiffuseMap = mTextureManager->getTexture(it->mDiffuseMap); textureLayer.mDiffuseMap = mTextureManager->getTexture(it->mDiffuseMap);
if (!it->mNormalMap.empty()) if (!forCompositeMap && !it->mNormalMap.empty())
textureLayer.mNormalMap = mTextureManager->getTexture(it->mNormalMap); textureLayer.mNormalMap = mTextureManager->getTexture(it->mNormalMap);
if (it->requiresShaders()) if (it->requiresShaders())
@ -150,29 +150,54 @@ osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Ve
blendmapTextures.push_back(texture); blendmapTextures.push_back(texture);
} }
// use texture coordinates for both texture units, the layer texture and blend texture
for (unsigned int i=0; i<2; ++i)
geometry->setTexCoordArray(i, mBufferCache.getUVBuffer(numVerts));
float blendmapScale = mStorage->getBlendmapScale(chunkSize); float blendmapScale = mStorage->getBlendmapScale(chunkSize);
Shader::ShaderManager* shaderManager = &mSceneManager->getShaderManager(); return ::Terrain::createPasses(useShaders, mSceneManager->getForcePerPixelLighting(),
mSceneManager->getClampLighting(), &mSceneManager->getShaderManager(), layers, blendmapTextures, blendmapScale, blendmapScale);
}
osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter, int lod)
{
osg::Vec2f worldCenter = chunkCenter*mStorage->getCellWorldSize();
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> transform (new SceneUtil::PositionAttitudeTransform);
transform->setPosition(osg::Vec3f(worldCenter.x(), worldCenter.y(), 0.f));
osg::ref_ptr<osg::Vec3Array> positions (new osg::Vec3Array);
osg::ref_ptr<osg::Vec3Array> normals (new osg::Vec3Array);
osg::ref_ptr<osg::Vec4Array> colors (new osg::Vec4Array);
osg::ref_ptr<osg::VertexBufferObject> vbo (new osg::VertexBufferObject);
positions->setVertexBufferObject(vbo);
normals->setVertexBufferObject(vbo);
colors->setVertexBufferObject(vbo);
mStorage->fillVertexBuffers(lod, chunkSize, chunkCenter, positions, normals, colors);
osg::ref_ptr<TerrainDrawable> geometry (new TerrainDrawable);
geometry->setVertexArray(positions);
geometry->setNormalArray(normals, osg::Array::BIND_PER_VERTEX);
geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);
geometry->setUseDisplayList(false);
geometry->setUseVertexBufferObjects(true);
if (1) // useCompositeMap unsigned int numVerts = (mStorage->getCellVertices()-1) * chunkSize / (1 << lod) + 1;
geometry->addPrimitiveSet(mBufferCache.getIndexBuffer(numVerts, 0));
geometry->getBound();
bool useCompositeMap = chunkSize >= 1.f;
unsigned int numUvSets = useCompositeMap ? 1 : 2;
for (unsigned int i=0; i<numUvSets; ++i)
geometry->setTexCoordArray(i, mBufferCache.getUVBuffer(numVerts));
if (useCompositeMap)
{ {
osg::ref_ptr<osg::Texture2D> compositeMap; osg::ref_ptr<osg::Texture2D> compositeMap;
osg::ref_ptr<osg::Group> compositeMapNode = createCompositeMapRTT(compositeMap); osg::ref_ptr<osg::Group> compositeMapNode = createCompositeMapRTT(compositeMap);
osg::ref_ptr<osg::Geometry> geom = osg::createTexturedQuadGeometry(osg::Vec3(-1,-1,0), osg::Vec3(2,0,0), osg::Vec3(0,2,0));
geom->setTexCoordArray(1, geom->getTexCoordArray(0), osg::Array::BIND_PER_VERTEX); createCompositeMapGeometry(chunkSize, chunkCenter, osg::Vec4f(0,0,1,1), compositeMapNode);
std::vector<osg::ref_ptr<osg::StateSet> > passes = createPasses(useShaders, mSceneManager->getForcePerPixelLighting(),
mSceneManager->getClampLighting(), shaderManager, layers, blendmapTextures, blendmapScale, blendmapScale, true);
for (std::vector<osg::ref_ptr<osg::StateSet> >::iterator it = passes.begin(); it != passes.end(); ++it)
{
osg::ref_ptr<osg::Group> group = new osg::Group;
group->setStateSet(*it);
group->addChild(geom);
compositeMapNode->addChild(group);
}
compositeMapNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); compositeMapNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
@ -185,8 +210,7 @@ osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Ve
} }
else else
{ {
geometry->setPasses(createPasses(useShaders, mSceneManager->getForcePerPixelLighting(), geometry->setPasses(createPasses(chunkSize, chunkCenter, false));
mSceneManager->getClampLighting(), shaderManager, layers, blendmapTextures, blendmapScale, blendmapScale));
} }
transform->addChild(geometry); transform->addChild(geometry);

@ -34,15 +34,19 @@ namespace Terrain
public: public:
ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer); ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager, CompositeMapRenderer* renderer);
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center); osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, int lod);
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const; virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) const;
private: private:
osg::ref_ptr<osg::Node> createChunk(float size, const osg::Vec2f& center); osg::ref_ptr<osg::Node> createChunk(float size, const osg::Vec2f& center, int lod);
osg::ref_ptr<osg::Group> createCompositeMapRTT(osg::ref_ptr<osg::Texture2D>& texture); osg::ref_ptr<osg::Group> createCompositeMapRTT(osg::ref_ptr<osg::Texture2D>& texture);
void createCompositeMapGeometry(float chunkSize, const osg::Vec2f& chunkCenter, const osg::Vec4f& texCoords, osg::Group* compositeMapNode);
std::vector<osg::ref_ptr<osg::StateSet> > createPasses(float chunkSize, const osg::Vec2f& chunkCenter, bool forCompositeMap);
Terrain::Storage* mStorage; Terrain::Storage* mStorage;
Resource::SceneManager* mSceneManager; Resource::SceneManager* mSceneManager;
TextureManager* mTextureManager; TextureManager* mTextureManager;

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

Loading…
Cancel
Save