mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-06 00:55:50 +00:00
Factor out terrain chunk loading/caching into a new resource manager
This commit is contained in:
parent
274690f790
commit
35d53acc65
@ -4,6 +4,7 @@
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
@ -914,8 +914,6 @@ namespace MWRender
|
||||
if (stats->collectStats("resource"))
|
||||
{
|
||||
stats->setAttribute(frameNumber, "UnrefQueue", mUnrefQueue->getNumItems());
|
||||
|
||||
mTerrain->reportStats(frameNumber, stats);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,24 +168,20 @@ namespace MWWorld
|
||||
class UpdateCacheItem : public SceneUtil::WorkItem
|
||||
{
|
||||
public:
|
||||
UpdateCacheItem(Resource::ResourceSystem* resourceSystem, Terrain::World* terrain, double referenceTime)
|
||||
UpdateCacheItem(Resource::ResourceSystem* resourceSystem, double referenceTime)
|
||||
: mReferenceTime(referenceTime)
|
||||
, mResourceSystem(resourceSystem)
|
||||
, mTerrain(terrain)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void doWork()
|
||||
{
|
||||
mResourceSystem->updateCache(mReferenceTime);
|
||||
|
||||
mTerrain->updateCache(mReferenceTime);
|
||||
}
|
||||
|
||||
private:
|
||||
double mReferenceTime;
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
Terrain::World* mTerrain;
|
||||
};
|
||||
|
||||
CellPreloader::CellPreloader(Resource::ResourceSystem* resourceSystem, Resource::BulletShapeManager* bulletShapeManager, Terrain::World* terrain, MWRender::LandManager* landManager)
|
||||
@ -313,7 +309,7 @@ namespace MWWorld
|
||||
if (timestamp - mLastResourceCacheUpdate > 1.0)
|
||||
{
|
||||
// the resource cache is cleared from the worker thread so that we're not holding up the main thread with delete operations
|
||||
mWorkQueue->addWorkItem(new UpdateCacheItem(mResourceSystem, mTerrain, timestamp), true);
|
||||
mWorkQueue->addWorkItem(new UpdateCacheItem(mResourceSystem, timestamp), true);
|
||||
mLastResourceCacheUpdate = timestamp;
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ add_component_dir (translation
|
||||
)
|
||||
|
||||
add_component_dir (terrain
|
||||
storage world buffercache defs terraingrid material terraindrawable texturemanager
|
||||
storage world buffercache defs terraingrid material terraindrawable texturemanager chunkmanager
|
||||
)
|
||||
|
||||
add_component_dir (loadinglistener
|
||||
|
@ -612,4 +612,9 @@ namespace ESMTerrain
|
||||
return ESM::Land::LAND_SIZE;
|
||||
}
|
||||
|
||||
int Storage::getBlendmapScale(float chunkSize)
|
||||
{
|
||||
return ESM::Land::LAND_TEXTURE_SIZE*chunkSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -99,6 +99,8 @@ namespace ESMTerrain
|
||||
/// Get the number of vertices on one side for each cell. Should be (power of two)+1
|
||||
virtual int getCellVertices();
|
||||
|
||||
virtual int getBlendmapScale(float chunkSize);
|
||||
|
||||
private:
|
||||
const VFS::Manager* mVFS;
|
||||
|
||||
|
@ -621,6 +621,11 @@ namespace Resource
|
||||
mIncrementalCompileOperation = ico;
|
||||
}
|
||||
|
||||
osgUtil::IncrementalCompileOperation *SceneManager::getIncrementalCompileOperation()
|
||||
{
|
||||
return mIncrementalCompileOperation.get();
|
||||
}
|
||||
|
||||
Resource::ImageManager* SceneManager::getImageManager()
|
||||
{
|
||||
return mImageManager;
|
||||
|
@ -121,6 +121,8 @@ namespace Resource
|
||||
/// Set up an IncrementalCompileOperation for background compiling of loaded scenes.
|
||||
void setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico);
|
||||
|
||||
osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation();
|
||||
|
||||
Resource::ImageManager* getImageManager();
|
||||
|
||||
/// @param mask The node mask to apply to loaded particle system nodes.
|
||||
|
@ -259,7 +259,7 @@ void StatsHandler::setUpScene(osgViewer::ViewerBase *viewer)
|
||||
_resourceStatsChildNum = _switch->getNumChildren();
|
||||
_switch->addChild(group, false);
|
||||
|
||||
const char* statNames[] = {"Compiling", "WorkQueue", "WorkThread", "", "Texture", "StateSet", "Node", "Node Instance", "Shape", "Shape Instance", "Image", "Nif", "Keyframe", "Terrain Cell", "Terrain Texture", "Land", "", "UnrefQueue"};
|
||||
const char* statNames[] = {"Compiling", "WorkQueue", "WorkThread", "", "Texture", "StateSet", "Node", "Node Instance", "Shape", "Shape Instance", "Image", "Nif", "Keyframe", "Terrain Chunk", "Terrain Texture", "Land", "", "UnrefQueue"};
|
||||
|
||||
int numLines = sizeof(statNames) / sizeof(statNames[0]);
|
||||
|
||||
|
180
components/terrain/chunkmanager.cpp
Normal file
180
components/terrain/chunkmanager.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
#include "chunkmanager.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <osg/Texture2D>
|
||||
|
||||
#include <osgUtil/IncrementalCompileOperation>
|
||||
|
||||
#include <components/resource/objectcache.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
|
||||
#include "terraindrawable.hpp"
|
||||
#include "material.hpp"
|
||||
#include "storage.hpp"
|
||||
#include "texturemanager.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class StaticBoundingBoxCallback : public osg::Drawable::ComputeBoundingBoxCallback
|
||||
{
|
||||
public:
|
||||
StaticBoundingBoxCallback(const osg::BoundingBox& bounds)
|
||||
: mBoundingBox(bounds)
|
||||
{
|
||||
}
|
||||
|
||||
virtual osg::BoundingBox computeBound(const osg::Drawable&) const
|
||||
{
|
||||
return mBoundingBox;
|
||||
}
|
||||
|
||||
private:
|
||||
osg::BoundingBox mBoundingBox;
|
||||
};
|
||||
}
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
|
||||
ChunkManager::ChunkManager(Storage *storage, Resource::SceneManager *sceneMgr, TextureManager* textureManager)
|
||||
: ResourceManager(NULL)
|
||||
, mStorage(storage)
|
||||
, mSceneManager(sceneMgr)
|
||||
, mTextureManager(textureManager)
|
||||
, mShaderManager(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> ChunkManager::getChunk(float size, const osg::Vec2f ¢er)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << size << " " << center.x() << " " << center.y();
|
||||
std::string id = stream.str();
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(id);
|
||||
if (obj)
|
||||
return obj->asNode();
|
||||
else
|
||||
{
|
||||
osg::ref_ptr<osg::Node> node = createChunk(size, center);
|
||||
mCache->addEntryToObjectCache(id, node.get());
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkManager::setShaderManager(Shader::ShaderManager *shaderManager)
|
||||
{
|
||||
mShaderManager = shaderManager;
|
||||
}
|
||||
|
||||
void ChunkManager::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||
{
|
||||
stats->setAttribute(frameNumber, "Terrain Chunk", mCache->getCacheSize());
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> ChunkManager::createChunk(float chunkSize, const osg::Vec2f &chunkCenter)
|
||||
{
|
||||
float minH, maxH;
|
||||
if (!mStorage->getMinMaxHeights(chunkSize, chunkCenter, minH, maxH))
|
||||
return NULL; // no terrain defined
|
||||
|
||||
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);
|
||||
|
||||
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));
|
||||
|
||||
|
||||
// we already know the bounding box, so no need to let OSG compute it.
|
||||
osg::Vec3f min(-0.5f*mStorage->getCellWorldSize()*chunkSize,
|
||||
-0.5f*mStorage->getCellWorldSize()*chunkSize,
|
||||
minH);
|
||||
osg::Vec3f max (0.5f*mStorage->getCellWorldSize()*chunkSize,
|
||||
0.5f*mStorage->getCellWorldSize()*chunkSize,
|
||||
maxH);
|
||||
osg::BoundingBox bounds(min, max);
|
||||
geometry->setComputeBoundingBoxCallback(new StaticBoundingBoxCallback(bounds));
|
||||
|
||||
std::vector<LayerInfo> layerList;
|
||||
std::vector<osg::ref_ptr<osg::Image> > blendmaps;
|
||||
mStorage->getBlendmaps(chunkSize, chunkCenter, false, blendmaps, layerList);
|
||||
|
||||
bool useShaders = mSceneManager->getForceShaders();
|
||||
if (!mSceneManager->getClampLighting())
|
||||
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;
|
||||
{
|
||||
for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it)
|
||||
{
|
||||
TextureLayer textureLayer;
|
||||
textureLayer.mParallax = it->mParallax;
|
||||
textureLayer.mSpecular = it->mSpecular;
|
||||
|
||||
textureLayer.mDiffuseMap = mTextureManager->getTexture(it->mDiffuseMap);
|
||||
|
||||
if (!it->mNormalMap.empty())
|
||||
textureLayer.mNormalMap = mTextureManager->getTexture(it->mNormalMap);
|
||||
|
||||
if (it->requiresShaders())
|
||||
useShaders = true;
|
||||
|
||||
layers.push_back(textureLayer);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<osg::ref_ptr<osg::Texture2D> > blendmapTextures;
|
||||
for (std::vector<osg::ref_ptr<osg::Image> >::const_iterator it = blendmaps.begin(); it != blendmaps.end(); ++it)
|
||||
{
|
||||
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D);
|
||||
texture->setImage(*it);
|
||||
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
||||
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
||||
texture->setResizeNonPowerOfTwoHint(false);
|
||||
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);
|
||||
|
||||
geometry->setPasses(createPasses(mShaderManager ? useShaders : false, mSceneManager->getForcePerPixelLighting(),
|
||||
mSceneManager->getClampLighting(), mShaderManager, layers, blendmapTextures, blendmapScale, blendmapScale));
|
||||
|
||||
transform->addChild(geometry);
|
||||
|
||||
if (mSceneManager->getIncrementalCompileOperation())
|
||||
{
|
||||
mSceneManager->getIncrementalCompileOperation()->add(geometry);
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
|
||||
}
|
59
components/terrain/chunkmanager.hpp
Normal file
59
components/terrain/chunkmanager.hpp
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef OPENMW_COMPONENTS_TERRAIN_CHUNKMANAGER_H
|
||||
#define OPENMW_COMPONENTS_TERRAIN_CHUNKMANAGER_H
|
||||
|
||||
#include <components/resource/resourcemanager.hpp>
|
||||
|
||||
#include "buffercache.hpp"
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Geometry;
|
||||
}
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
class PositionAttitudeTransform;
|
||||
}
|
||||
|
||||
namespace Resource
|
||||
{
|
||||
class SceneManager;
|
||||
}
|
||||
|
||||
namespace Shader
|
||||
{
|
||||
class ShaderManager;
|
||||
}
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
|
||||
class TextureManager;
|
||||
class Storage;
|
||||
|
||||
/// @brief Handles loading and caching of terrain chunks
|
||||
class ChunkManager : public Resource::ResourceManager
|
||||
{
|
||||
public:
|
||||
ChunkManager(Storage* storage, Resource::SceneManager* sceneMgr, TextureManager* textureManager);
|
||||
|
||||
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center);
|
||||
|
||||
// Optional
|
||||
void setShaderManager(Shader::ShaderManager* shaderManager);
|
||||
|
||||
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Node> createChunk(float size, const osg::Vec2f& center);
|
||||
|
||||
Terrain::Storage* mStorage;
|
||||
Resource::SceneManager* mSceneManager;
|
||||
TextureManager* mTextureManager;
|
||||
Shader::ShaderManager* mShaderManager;
|
||||
BufferCache mBufferCache;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -78,6 +78,8 @@ namespace Terrain
|
||||
|
||||
/// Get the number of vertices on one side for each cell. Should be (power of two)+1
|
||||
virtual int getCellVertices() = 0;
|
||||
|
||||
virtual int getBlendmapScale(float chunkSize) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -3,47 +3,12 @@
|
||||
#include <memory>
|
||||
|
||||
#include <osg/Material>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
|
||||
#include <osgUtil/IncrementalCompileOperation>
|
||||
|
||||
#include <OpenThreads/ScopedLock>
|
||||
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/resource/imagemanager.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
|
||||
#include <components/sceneutil/lightmanager.hpp>
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
#include <components/sceneutil/unrefqueue.hpp>
|
||||
|
||||
#include <components/esm/loadland.hpp>
|
||||
|
||||
|
||||
#include "material.hpp"
|
||||
#include "storage.hpp"
|
||||
#include "terraindrawable.hpp"
|
||||
#include "texturemanager.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class StaticBoundingBoxCallback : public osg::Drawable::ComputeBoundingBoxCallback
|
||||
{
|
||||
public:
|
||||
StaticBoundingBoxCallback(const osg::BoundingBox& bounds)
|
||||
: mBoundingBox(bounds)
|
||||
{
|
||||
}
|
||||
|
||||
virtual osg::BoundingBox computeBound(const osg::Drawable&) const
|
||||
{
|
||||
return mBoundingBox;
|
||||
}
|
||||
|
||||
private:
|
||||
osg::BoundingBox mBoundingBox;
|
||||
};
|
||||
}
|
||||
#include "chunkmanager.hpp"
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
@ -57,6 +22,8 @@ TerrainGrid::TerrainGrid(osg::Group* parent, Resource::ResourceSystem* resourceS
|
||||
osg::ref_ptr<osg::Material> material (new osg::Material);
|
||||
material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
||||
mTerrainRoot->getOrCreateStateSet()->setAttributeAndModes(material, osg::StateAttribute::ON);
|
||||
|
||||
mChunkManager->setShaderManager(mShaderManager);
|
||||
}
|
||||
|
||||
TerrainGrid::~TerrainGrid()
|
||||
@ -69,17 +36,8 @@ TerrainGrid::~TerrainGrid()
|
||||
|
||||
osg::ref_ptr<osg::Node> TerrainGrid::cacheCell(int x, int y)
|
||||
{
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
|
||||
Grid::iterator found = mGridCache.find(std::make_pair(x,y));
|
||||
if (found != mGridCache.end())
|
||||
return found->second;
|
||||
}
|
||||
osg::ref_ptr<osg::Node> node = buildTerrain(NULL, 1.f, osg::Vec2f(x+0.5, y+0.5));
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
|
||||
mGridCache.insert(std::make_pair(std::make_pair(x,y), node));
|
||||
return node;
|
||||
osg::Vec2f center(x+0.5f, y+0.5f);
|
||||
return buildTerrain(NULL, 1.f, center);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter)
|
||||
@ -100,106 +58,13 @@ osg::ref_ptr<osg::Node> TerrainGrid::buildTerrain (osg::Group* parent, float chu
|
||||
}
|
||||
else
|
||||
{
|
||||
float minH, maxH;
|
||||
if (!mStorage->getMinMaxHeights(chunkSize, chunkCenter, minH, maxH))
|
||||
return NULL; // no terrain defined
|
||||
|
||||
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::Node> node = mChunkManager->getChunk(chunkSize, chunkCenter);
|
||||
if (!node)
|
||||
return NULL;
|
||||
if (parent)
|
||||
parent->addChild(transform);
|
||||
parent->addChild(node);
|
||||
|
||||
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(0, 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;
|
||||
|
||||
geometry->addPrimitiveSet(mCache.getIndexBuffer(numVerts, 0));
|
||||
|
||||
// we already know the bounding box, so no need to let OSG compute it.
|
||||
osg::Vec3f min(-0.5f*mStorage->getCellWorldSize()*chunkSize,
|
||||
-0.5f*mStorage->getCellWorldSize()*chunkSize,
|
||||
minH);
|
||||
osg::Vec3f max (0.5f*mStorage->getCellWorldSize()*chunkSize,
|
||||
0.5f*mStorage->getCellWorldSize()*chunkSize,
|
||||
maxH);
|
||||
osg::BoundingBox bounds(min, max);
|
||||
geometry->setComputeBoundingBoxCallback(new StaticBoundingBoxCallback(bounds));
|
||||
|
||||
std::vector<LayerInfo> layerList;
|
||||
std::vector<osg::ref_ptr<osg::Image> > blendmaps;
|
||||
mStorage->getBlendmaps(chunkSize, chunkCenter, false, blendmaps, layerList);
|
||||
|
||||
bool useShaders = mResourceSystem->getSceneManager()->getForceShaders();
|
||||
if (!mResourceSystem->getSceneManager()->getClampLighting())
|
||||
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;
|
||||
{
|
||||
for (std::vector<LayerInfo>::const_iterator it = layerList.begin(); it != layerList.end(); ++it)
|
||||
{
|
||||
TextureLayer textureLayer;
|
||||
textureLayer.mParallax = it->mParallax;
|
||||
textureLayer.mSpecular = it->mSpecular;
|
||||
|
||||
textureLayer.mDiffuseMap = mTextureManager->getTexture(it->mDiffuseMap);
|
||||
|
||||
if (!it->mNormalMap.empty())
|
||||
{
|
||||
textureLayer.mNormalMap = mTextureManager->getTexture(it->mNormalMap);
|
||||
}
|
||||
|
||||
if (it->requiresShaders())
|
||||
useShaders = true;
|
||||
|
||||
layers.push_back(textureLayer);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<osg::ref_ptr<osg::Texture2D> > blendmapTextures;
|
||||
for (std::vector<osg::ref_ptr<osg::Image> >::const_iterator it = blendmaps.begin(); it != blendmaps.end(); ++it)
|
||||
{
|
||||
osg::ref_ptr<osg::Texture2D> texture (new osg::Texture2D);
|
||||
texture->setImage(*it);
|
||||
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
||||
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
||||
texture->setResizeNonPowerOfTwoHint(false);
|
||||
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, mCache.getUVBuffer(numVerts));
|
||||
|
||||
float blendmapScale = ESM::Land::LAND_TEXTURE_SIZE*chunkSize;
|
||||
|
||||
geometry->setPasses(createPasses(mShaderManager ? useShaders : false, mResourceSystem->getSceneManager()->getForcePerPixelLighting(),
|
||||
mResourceSystem->getSceneManager()->getClampLighting(), mShaderManager, layers, blendmapTextures, blendmapScale, blendmapScale));
|
||||
|
||||
transform->addChild(geometry);
|
||||
|
||||
if (mIncrementalCompileOperation)
|
||||
{
|
||||
mIncrementalCompileOperation->add(geometry);
|
||||
}
|
||||
|
||||
return transform;
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,27 +73,10 @@ void TerrainGrid::loadCell(int x, int y)
|
||||
if (mGrid.find(std::make_pair(x, y)) != mGrid.end())
|
||||
return; // already loaded
|
||||
|
||||
// try to get it from the cache
|
||||
osg::ref_ptr<osg::Node> terrainNode;
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
|
||||
Grid::const_iterator found = mGridCache.find(std::make_pair(x,y));
|
||||
if (found != mGridCache.end())
|
||||
{
|
||||
terrainNode = found->second;
|
||||
if (!terrainNode)
|
||||
return; // no terrain defined
|
||||
}
|
||||
}
|
||||
|
||||
// didn't find in cache, build it
|
||||
osg::Vec2f center(x+0.5f, y+0.5f);
|
||||
osg::ref_ptr<osg::Node> terrainNode = buildTerrain(NULL, 1.f, center);
|
||||
if (!terrainNode)
|
||||
{
|
||||
osg::Vec2f center(x+0.5f, y+0.5f);
|
||||
terrainNode = buildTerrain(NULL, 1.f, center);
|
||||
if (!terrainNode)
|
||||
return; // no terrain defined
|
||||
}
|
||||
return; // no terrain defined
|
||||
|
||||
mTerrainRoot->addChild(terrainNode);
|
||||
|
||||
@ -250,31 +98,9 @@ void TerrainGrid::unloadCell(int x, int y)
|
||||
mGrid.erase(it);
|
||||
}
|
||||
|
||||
void TerrainGrid::updateCache(double referenceTime)
|
||||
{
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
|
||||
for (Grid::iterator it = mGridCache.begin(); it != mGridCache.end();)
|
||||
{
|
||||
if (it->second->referenceCount() <= 1)
|
||||
mGridCache.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainGrid::updateTextureFiltering()
|
||||
{
|
||||
mTextureManager->updateTextureFiltering();
|
||||
}
|
||||
|
||||
void TerrainGrid::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||
{
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mGridCacheMutex);
|
||||
stats->setAttribute(frameNumber, "Terrain Cell", mGridCache.size());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef COMPONENTS_TERRAIN_TERRAINGRID_H
|
||||
#define COMPONENTS_TERRAIN_TERRAINGRID_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include <osg/Vec2f>
|
||||
|
||||
#include "world.hpp"
|
||||
@ -41,16 +43,10 @@ namespace Terrain
|
||||
/// @note Not thread safe.
|
||||
virtual void unloadCell(int x, int y);
|
||||
|
||||
/// Clear cached objects that are no longer referenced
|
||||
/// @note Thread safe.
|
||||
void updateCache(double referenceTime);
|
||||
|
||||
/// Apply the scene manager's texture filtering settings to all cached textures.
|
||||
/// @note Thread safe.
|
||||
void updateTextureFiltering();
|
||||
|
||||
void reportStats(unsigned int frameNumber, osg::Stats *stats);
|
||||
|
||||
private:
|
||||
osg::ref_ptr<osg::Node> buildTerrain (osg::Group* parent, float chunkSize, const osg::Vec2f& chunkCenter);
|
||||
|
||||
@ -60,11 +56,6 @@ namespace Terrain
|
||||
typedef std::map<std::pair<int, int>, osg::ref_ptr<osg::Node> > Grid;
|
||||
Grid mGrid;
|
||||
|
||||
Grid mGridCache;
|
||||
OpenThreads::Mutex mGridCacheMutex;
|
||||
|
||||
BufferCache mCache;
|
||||
|
||||
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
||||
|
||||
Shader::ShaderManager* mShaderManager;
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "storage.hpp"
|
||||
#include "texturemanager.hpp"
|
||||
#include "chunkmanager.hpp"
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
@ -26,13 +27,16 @@ World::World(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUt
|
||||
mParent->addChild(mTerrainRoot);
|
||||
|
||||
mTextureManager.reset(new TextureManager(mResourceSystem->getSceneManager()));
|
||||
|
||||
mResourceSystem->addResourceManager(mTextureManager.get());
|
||||
|
||||
mChunkManager.reset(new ChunkManager(mStorage, mResourceSystem->getSceneManager(), mTextureManager.get()));
|
||||
mResourceSystem->addResourceManager(mChunkManager.get());
|
||||
}
|
||||
|
||||
World::~World()
|
||||
{
|
||||
mResourceSystem->removeResourceManager(mTextureManager.get());
|
||||
mResourceSystem->removeResourceManager(mChunkManager.get());
|
||||
|
||||
mParent->removeChild(mTerrainRoot);
|
||||
|
||||
|
@ -2,16 +2,17 @@
|
||||
#define COMPONENTS_TERRAIN_WORLD_H
|
||||
|
||||
#include <osg/ref_ptr>
|
||||
#include <osg/Vec3f>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "defs.hpp"
|
||||
#include "buffercache.hpp"
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Group;
|
||||
class Stats;
|
||||
class Node;
|
||||
}
|
||||
|
||||
namespace osgUtil
|
||||
@ -29,6 +30,7 @@ namespace Terrain
|
||||
class Storage;
|
||||
|
||||
class TextureManager;
|
||||
class ChunkManager;
|
||||
|
||||
/**
|
||||
* @brief The basic interface for a terrain world. How the terrain chunks are paged and displayed
|
||||
@ -46,10 +48,6 @@ namespace Terrain
|
||||
|
||||
virtual void updateTextureFiltering() {}
|
||||
|
||||
virtual void updateCache(double referenceTime) {}
|
||||
|
||||
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats) {}
|
||||
|
||||
float getHeightAt (const osg::Vec3f& worldPos);
|
||||
|
||||
virtual osg::ref_ptr<osg::Node> cacheCell(int x, int y) {return NULL;}
|
||||
@ -71,6 +69,7 @@ namespace Terrain
|
||||
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
|
||||
|
||||
std::auto_ptr<TextureManager> mTextureManager;
|
||||
std::auto_ptr<ChunkManager> mChunkManager;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user