mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-06 00:55:50 +00:00
Add resource manager for ESM::Land to allow data to be unloaded when no longer required
This commit is contained in:
parent
b898315962
commit
9a3a64f0c4
@ -9,7 +9,7 @@ namespace CSVRender
|
||||
{
|
||||
}
|
||||
|
||||
const ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
|
||||
osg::ref_ptr<const ESMTerrain::LandObject> TerrainStorage::getLand(int cellX, int cellY)
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "#" << cellX << " " << cellY;
|
||||
@ -23,7 +23,7 @@ namespace CSVRender
|
||||
const ESM::Land& land = mData.getLand().getRecord(index).get();
|
||||
int mask = ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX;
|
||||
land.loadData (mask);
|
||||
return &land;
|
||||
return new ESMTerrain::LandObject(&land, 0);
|
||||
}
|
||||
|
||||
const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin)
|
||||
|
@ -18,7 +18,7 @@ namespace CSVRender
|
||||
private:
|
||||
const CSMWorld::Data& mData;
|
||||
|
||||
virtual const ESM::Land* getLand (int cellX, int cellY);
|
||||
virtual osg::ref_ptr<const ESMTerrain::LandObject> getLand (int cellX, int cellY);
|
||||
virtual const ESM::LandTexture* getLandTexture(int index, short plugin);
|
||||
|
||||
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY);
|
||||
|
@ -23,7 +23,7 @@ add_openmw_dir (mwrender
|
||||
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
||||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
||||
renderbin actoranimation
|
||||
renderbin actoranimation landmanager
|
||||
)
|
||||
|
||||
add_openmw_dir (mwinput
|
||||
|
@ -516,7 +516,7 @@ namespace MWPhysics
|
||||
class HeightField
|
||||
{
|
||||
public:
|
||||
HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts)
|
||||
HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, const osg::Object* holdObject)
|
||||
{
|
||||
// find the minimum and maximum heights (needed for bullet)
|
||||
float minh = heights[0];
|
||||
@ -544,6 +544,8 @@ namespace MWPhysics
|
||||
mCollisionObject = new btCollisionObject;
|
||||
mCollisionObject->setCollisionShape(mShape);
|
||||
mCollisionObject->setWorldTransform(transform);
|
||||
|
||||
mHoldObject = holdObject;
|
||||
}
|
||||
~HeightField()
|
||||
{
|
||||
@ -558,6 +560,7 @@ namespace MWPhysics
|
||||
private:
|
||||
btHeightfieldTerrainShape* mShape;
|
||||
btCollisionObject* mCollisionObject;
|
||||
osg::ref_ptr<const osg::Object> mHoldObject;
|
||||
|
||||
void operator=(const HeightField&);
|
||||
HeightField(const HeightField&);
|
||||
@ -1140,9 +1143,9 @@ namespace MWPhysics
|
||||
return MovementSolver::traceDown(ptr, position, found->second, mCollisionWorld, maxHeight);
|
||||
}
|
||||
|
||||
void PhysicsSystem::addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts)
|
||||
void PhysicsSystem::addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, const osg::Object* holdObject)
|
||||
{
|
||||
HeightField *heightfield = new HeightField(heights, x, y, triSize, sqrtVerts);
|
||||
HeightField *heightfield = new HeightField(heights, x, y, triSize, sqrtVerts, holdObject);
|
||||
mHeightFields[std::make_pair(x,y)] = heightfield;
|
||||
|
||||
mCollisionWorld->addCollisionObject(heightfield->getCollisionObject(), CollisionType_HeightMap,
|
||||
|
@ -15,6 +15,7 @@
|
||||
namespace osg
|
||||
{
|
||||
class Group;
|
||||
class Object;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
@ -80,7 +81,7 @@ namespace MWPhysics
|
||||
void updatePosition (const MWWorld::Ptr& ptr);
|
||||
|
||||
|
||||
void addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts);
|
||||
void addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, const osg::Object* holdObject);
|
||||
|
||||
void removeHeightField (int x, int y);
|
||||
|
||||
|
48
apps/openmw/mwrender/landmanager.cpp
Normal file
48
apps/openmw/mwrender/landmanager.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "landmanager.hpp"
|
||||
|
||||
#include <osg/Stats>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <components/resource/objectcache.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
LandManager::LandManager(int loadFlags)
|
||||
: ResourceManager(NULL)
|
||||
, mLoadFlags(loadFlags)
|
||||
{
|
||||
}
|
||||
|
||||
osg::ref_ptr<ESMTerrain::LandObject> LandManager::getLand(int x, int y)
|
||||
{
|
||||
std::ostringstream id;
|
||||
id << x << " " << y;
|
||||
std::string idstr = id.str();
|
||||
|
||||
osg::ref_ptr<osg::Object> obj = mCache->getRefFromObjectCache(idstr);
|
||||
if (obj)
|
||||
return static_cast<ESMTerrain::LandObject*>(obj.get());
|
||||
else
|
||||
{
|
||||
const ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search(x,y);
|
||||
if (!land)
|
||||
return NULL;
|
||||
osg::ref_ptr<ESMTerrain::LandObject> landObj (new ESMTerrain::LandObject(land, mLoadFlags));
|
||||
mCache->addEntryToObjectCache(idstr, landObj.get());
|
||||
return landObj;
|
||||
}
|
||||
}
|
||||
|
||||
void LandManager::reportStats(unsigned int frameNumber, osg::Stats *stats)
|
||||
{
|
||||
stats->setAttribute(frameNumber, "Land", mCache->getCacheSize());
|
||||
}
|
||||
|
||||
|
||||
}
|
33
apps/openmw/mwrender/landmanager.hpp
Normal file
33
apps/openmw/mwrender/landmanager.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef OPENMW_COMPONENTS_ESMTERRAIN_LANDMANAGER_H
|
||||
#define OPENMW_COMPONENTS_ESMTERRAIN_LANDMANAGER_H
|
||||
|
||||
#include <osg/Object>
|
||||
|
||||
#include <components/resource/resourcemanager.hpp>
|
||||
#include <components/esmterrain/storage.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct Land;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
class LandManager : public Resource::ResourceManager
|
||||
{
|
||||
public:
|
||||
LandManager(int loadFlags);
|
||||
|
||||
/// @note Will return NULL if not found.
|
||||
osg::ref_ptr<ESMTerrain::LandObject> getLand(int x, int y);
|
||||
|
||||
virtual void reportStats(unsigned int frameNumber, osg::Stats* stats);
|
||||
|
||||
private:
|
||||
int mLoadFlags;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -212,11 +212,13 @@ namespace MWRender
|
||||
|
||||
mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath));
|
||||
|
||||
|
||||
|
||||
mTerrainStorage = new TerrainStorage(mResourceSystem, Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getString("normal height map pattern", "Shaders"),
|
||||
Settings::Manager::getBool("auto use terrain normal maps", "Shaders"),
|
||||
Settings::Manager::getString("terrain specular map pattern", "Shaders"), Settings::Manager::getBool("auto use terrain specular maps", "Shaders"));
|
||||
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(),
|
||||
new TerrainStorage(mResourceSystem->getVFS(), Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getString("normal height map pattern", "Shaders"),
|
||||
Settings::Manager::getBool("auto use terrain normal maps", "Shaders"),
|
||||
Settings::Manager::getString("terrain specular map pattern", "Shaders"), Settings::Manager::getBool("auto use terrain specular maps", "Shaders")),
|
||||
Mask_Terrain, &mResourceSystem->getSceneManager()->getShaderManager(), mUnrefQueue.get()));
|
||||
mTerrainStorage, Mask_Terrain, &mResourceSystem->getSceneManager()->getShaderManager(), mUnrefQueue.get()));
|
||||
|
||||
mCamera.reset(new Camera(mViewer->getCamera()));
|
||||
|
||||
@ -1055,4 +1057,10 @@ namespace MWRender
|
||||
SceneUtil::writeScene(node, filename, format);
|
||||
}
|
||||
|
||||
LandManager *RenderingManager::getLandManager() const
|
||||
{
|
||||
return mTerrainStorage->getLandManager();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ namespace MWRender
|
||||
class Pathgrid;
|
||||
class Camera;
|
||||
class Water;
|
||||
class TerrainStorage;
|
||||
class LandManager;
|
||||
|
||||
class RenderingManager : public MWRender::RenderingInterface
|
||||
{
|
||||
@ -190,6 +192,8 @@ namespace MWRender
|
||||
|
||||
void exportSceneGraph(const MWWorld::Ptr& ptr, const std::string& filename, const std::string& format);
|
||||
|
||||
LandManager* getLandManager() const;
|
||||
|
||||
private:
|
||||
void updateProjectionMatrix();
|
||||
void updateTextureFiltering();
|
||||
@ -212,6 +216,7 @@ namespace MWRender
|
||||
std::auto_ptr<Objects> mObjects;
|
||||
std::auto_ptr<Water> mWater;
|
||||
std::auto_ptr<Terrain::World> mTerrain;
|
||||
TerrainStorage* mTerrainStorage;
|
||||
std::auto_ptr<SkyManager> mSky;
|
||||
std::auto_ptr<EffectManager> mEffectManager;
|
||||
osg::ref_ptr<NpcAnimation> mPlayerAnimation;
|
||||
|
@ -6,12 +6,22 @@
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "landmanager.hpp"
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
TerrainStorage::TerrainStorage(const VFS::Manager* vfs, const std::string& normalMapPattern, const std::string& normalHeightMapPattern, bool autoUseNormalMaps, const std::string& specularMapPattern, bool autoUseSpecularMaps)
|
||||
: ESMTerrain::Storage(vfs, normalMapPattern, normalHeightMapPattern, autoUseNormalMaps, specularMapPattern, autoUseSpecularMaps)
|
||||
TerrainStorage::TerrainStorage(Resource::ResourceSystem* resourceSystem, const std::string& normalMapPattern, const std::string& normalHeightMapPattern, bool autoUseNormalMaps, const std::string& specularMapPattern, bool autoUseSpecularMaps)
|
||||
: ESMTerrain::Storage(resourceSystem->getVFS(), normalMapPattern, normalHeightMapPattern, autoUseNormalMaps, specularMapPattern, autoUseSpecularMaps)
|
||||
, mLandManager(new LandManager(ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX))
|
||||
, mResourceSystem(resourceSystem)
|
||||
{
|
||||
mResourceSystem->addResourceManager(mLandManager.get());
|
||||
}
|
||||
|
||||
TerrainStorage::~TerrainStorage()
|
||||
{
|
||||
mResourceSystem->removeResourceManager(mLandManager.get());
|
||||
}
|
||||
|
||||
void TerrainStorage::getBounds(float& minX, float& maxX, float& minY, float& maxY)
|
||||
@ -39,22 +49,14 @@ namespace MWRender
|
||||
maxY += 1;
|
||||
}
|
||||
|
||||
const ESM::Land* TerrainStorage::getLand(int cellX, int cellY)
|
||||
LandManager *TerrainStorage::getLandManager() const
|
||||
{
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
return mLandManager.get();
|
||||
}
|
||||
|
||||
const ESM::Land* land = esmStore.get<ESM::Land>().search(cellX, cellY);
|
||||
if (!land)
|
||||
return NULL;
|
||||
|
||||
const int flags = ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX;
|
||||
if (!land->isDataLoaded(flags))
|
||||
land->loadData(flags);
|
||||
|
||||
// TODO: unload land data when it's no longer needed
|
||||
|
||||
return land;
|
||||
osg::ref_ptr<const ESMTerrain::LandObject> TerrainStorage::getLand(int cellX, int cellY)
|
||||
{
|
||||
return mLandManager->getLand(cellX, cellY);
|
||||
}
|
||||
|
||||
const ESM::LandTexture* TerrainStorage::getLandTexture(int index, short plugin)
|
||||
@ -64,4 +66,5 @@ namespace MWRender
|
||||
return esmStore.get<ESM::LandTexture>().search(index, plugin);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,23 +1,37 @@
|
||||
#ifndef MWRENDER_TERRAINSTORAGE_H
|
||||
#define MWRENDER_TERRAINSTORAGE_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <components/esmterrain/storage.hpp>
|
||||
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
|
||||
class LandManager;
|
||||
|
||||
/// @brief Connects the ESM Store used in OpenMW with the ESMTerrain storage.
|
||||
class TerrainStorage : public ESMTerrain::Storage
|
||||
{
|
||||
private:
|
||||
virtual const ESM::Land* getLand (int cellX, int cellY);
|
||||
virtual const ESM::LandTexture* getLandTexture(int index, short plugin);
|
||||
public:
|
||||
|
||||
TerrainStorage(const VFS::Manager* vfs, const std::string& normalMapPattern = "", const std::string& normalHeightMapPatteern = "", bool autoUseNormalMaps = false, const std::string& specularMapPattern = "", bool autoUseSpecularMaps = false);
|
||||
TerrainStorage(Resource::ResourceSystem* resourceSystem, const std::string& normalMapPattern = "", const std::string& normalHeightMapPatteern = "", bool autoUseNormalMaps = false, const std::string& specularMapPattern = "", bool autoUseSpecularMaps = false);
|
||||
~TerrainStorage();
|
||||
|
||||
virtual osg::ref_ptr<const ESMTerrain::LandObject> getLand (int cellX, int cellY);
|
||||
virtual const ESM::LandTexture* getLandTexture(int index, short plugin);
|
||||
|
||||
/// Get bounds of the whole terrain in cell units
|
||||
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY);
|
||||
|
||||
LandManager* getLandManager() const;
|
||||
|
||||
private:
|
||||
std::auto_ptr<LandManager> mLandManager;
|
||||
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/nifosg/nifloader.hpp>
|
||||
#include <components/terrain/world.hpp>
|
||||
#include <components/esmterrain/storage.hpp>
|
||||
#include <components/sceneutil/unrefqueue.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
@ -16,6 +17,7 @@
|
||||
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwrender/landmanager.hpp"
|
||||
|
||||
#include "cellstore.hpp"
|
||||
#include "manualref.hpp"
|
||||
@ -46,7 +48,7 @@ namespace MWWorld
|
||||
{
|
||||
public:
|
||||
/// Constructor to be called from the main thread.
|
||||
PreloadItem(MWWorld::CellStore* cell, Resource::SceneManager* sceneManager, Resource::BulletShapeManager* bulletShapeManager, Resource::KeyframeManager* keyframeManager, Terrain::World* terrain, bool preloadInstances)
|
||||
PreloadItem(MWWorld::CellStore* cell, Resource::SceneManager* sceneManager, Resource::BulletShapeManager* bulletShapeManager, Resource::KeyframeManager* keyframeManager, Terrain::World* terrain, MWRender::LandManager* landManager, bool preloadInstances)
|
||||
: mIsExterior(cell->getCell()->isExterior())
|
||||
, mX(cell->getCell()->getGridX())
|
||||
, mY(cell->getCell()->getGridY())
|
||||
@ -54,6 +56,7 @@ namespace MWWorld
|
||||
, mBulletShapeManager(bulletShapeManager)
|
||||
, mKeyframeManager(keyframeManager)
|
||||
, mTerrain(terrain)
|
||||
, mLandManager(landManager)
|
||||
, mPreloadInstances(preloadInstances)
|
||||
, mAbort(false)
|
||||
{
|
||||
@ -90,6 +93,7 @@ namespace MWWorld
|
||||
try
|
||||
{
|
||||
mPreloadedObjects.push_back(mTerrain->cacheCell(mX, mY));
|
||||
mPreloadedObjects.push_back(mLandManager->getLand(mX, mY));
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
@ -151,6 +155,7 @@ namespace MWWorld
|
||||
Resource::BulletShapeManager* mBulletShapeManager;
|
||||
Resource::KeyframeManager* mKeyframeManager;
|
||||
Terrain::World* mTerrain;
|
||||
MWRender::LandManager* mLandManager;
|
||||
bool mPreloadInstances;
|
||||
|
||||
volatile bool mAbort;
|
||||
@ -183,10 +188,11 @@ namespace MWWorld
|
||||
Terrain::World* mTerrain;
|
||||
};
|
||||
|
||||
CellPreloader::CellPreloader(Resource::ResourceSystem* resourceSystem, Resource::BulletShapeManager* bulletShapeManager, Terrain::World* terrain)
|
||||
CellPreloader::CellPreloader(Resource::ResourceSystem* resourceSystem, Resource::BulletShapeManager* bulletShapeManager, Terrain::World* terrain, MWRender::LandManager* landManager)
|
||||
: mResourceSystem(resourceSystem)
|
||||
, mBulletShapeManager(bulletShapeManager)
|
||||
, mTerrain(terrain)
|
||||
, mLandManager(landManager)
|
||||
, mExpiryDelay(0.0)
|
||||
, mMinCacheSize(0)
|
||||
, mMaxCacheSize(0)
|
||||
@ -251,7 +257,7 @@ namespace MWWorld
|
||||
return;
|
||||
}
|
||||
|
||||
osg::ref_ptr<PreloadItem> item (new PreloadItem(cell, mResourceSystem->getSceneManager(), mBulletShapeManager, mResourceSystem->getKeyframeManager(), mTerrain, mPreloadInstances));
|
||||
osg::ref_ptr<PreloadItem> item (new PreloadItem(cell, mResourceSystem->getSceneManager(), mBulletShapeManager, mResourceSystem->getKeyframeManager(), mTerrain, mLandManager, mPreloadInstances));
|
||||
mWorkQueue->addWorkItem(item);
|
||||
|
||||
mPreloadCells[cell] = PreloadEntry(timestamp, item);
|
||||
|
@ -21,6 +21,11 @@ namespace SceneUtil
|
||||
class UnrefQueue;
|
||||
}
|
||||
|
||||
namespace MWRender
|
||||
{
|
||||
class LandManager;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
class CellStore;
|
||||
@ -28,7 +33,7 @@ namespace MWWorld
|
||||
class CellPreloader
|
||||
{
|
||||
public:
|
||||
CellPreloader(Resource::ResourceSystem* resourceSystem, Resource::BulletShapeManager* bulletShapeManager, Terrain::World* terrain);
|
||||
CellPreloader(Resource::ResourceSystem* resourceSystem, Resource::BulletShapeManager* bulletShapeManager, Terrain::World* terrain, MWRender::LandManager* landManager);
|
||||
~CellPreloader();
|
||||
|
||||
/// Ask a background thread to preload rendering meshes and collision shapes for objects in this cell.
|
||||
@ -64,6 +69,7 @@ namespace MWWorld
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
Resource::BulletShapeManager* mBulletShapeManager;
|
||||
Terrain::World* mTerrain;
|
||||
MWRender::LandManager* mLandManager;
|
||||
osg::ref_ptr<SceneUtil::WorkQueue> mWorkQueue;
|
||||
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
||||
double mExpiryDelay;
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "../mwrender/renderingmanager.hpp"
|
||||
#include "../mwrender/landmanager.hpp"
|
||||
|
||||
#include "../mwphysics/physicssystem.hpp"
|
||||
|
||||
@ -271,26 +272,19 @@ namespace MWWorld
|
||||
// Load terrain physics first...
|
||||
if (cell->getCell()->isExterior())
|
||||
{
|
||||
const ESM::Land* land =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Land>().search(
|
||||
cell->getCell()->getGridX(),
|
||||
cell->getCell()->getGridY()
|
||||
);
|
||||
if (land && land->mDataTypes&ESM::Land::DATA_VHGT) {
|
||||
// Actually only VHGT is needed here, but we'll need the rest for rendering anyway.
|
||||
// Load everything now to reduce IO overhead.
|
||||
const int flags = ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX;
|
||||
|
||||
const ESM::Land::LandData *data = land->getLandData (flags);
|
||||
mPhysics->addHeightField (data->mHeights, cell->getCell()->getGridX(), cell->getCell()->getGridY(),
|
||||
worldsize / (verts-1), verts);
|
||||
int cellX = cell->getCell()->getGridX();
|
||||
int cellY = cell->getCell()->getGridY();
|
||||
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellX, cellY);
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : 0;
|
||||
if (data)
|
||||
{
|
||||
mPhysics->addHeightField (data->mHeights, cellX, cell->getCell()->getGridY(), worldsize / (verts-1), verts, land.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
static std::vector<float> defaultHeight;
|
||||
defaultHeight.resize(verts*verts, ESM::Land::DEFAULT_HEIGHT);
|
||||
mPhysics->addHeightField (&defaultHeight[0], cell->getCell()->getGridX(), cell->getCell()->getGridY(),
|
||||
worldsize / (verts-1), verts);
|
||||
mPhysics->addHeightField (&defaultHeight[0], cell->getCell()->getGridX(), cell->getCell()->getGridY(), worldsize / (verts-1), verts, land.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -487,7 +481,7 @@ namespace MWWorld
|
||||
, mPreloadDoors(Settings::Manager::getBool("preload doors", "Cells"))
|
||||
, mPreloadFastTravel(Settings::Manager::getBool("preload fast travel", "Cells"))
|
||||
{
|
||||
mPreloader.reset(new CellPreloader(rendering.getResourceSystem(), physics->getShapeManager(), rendering.getTerrain()));
|
||||
mPreloader.reset(new CellPreloader(rendering.getResourceSystem(), physics->getShapeManager(), rendering.getTerrain(), rendering.getLandManager()));
|
||||
mPreloader->setWorkQueue(mRendering.getWorkQueue());
|
||||
|
||||
mPreloader->setUnrefQueue(rendering.getUnrefQueue());
|
||||
|
@ -16,6 +16,39 @@
|
||||
namespace ESMTerrain
|
||||
{
|
||||
|
||||
|
||||
LandObject::LandObject()
|
||||
{
|
||||
}
|
||||
|
||||
LandObject::LandObject(const ESM::Land *land, int loadFlags)
|
||||
: mLand(land)
|
||||
, mLoadFlags(loadFlags)
|
||||
{
|
||||
mLand->loadData(mLoadFlags);
|
||||
}
|
||||
|
||||
LandObject::LandObject(const LandObject ©, const osg::CopyOp ©op)
|
||||
{
|
||||
}
|
||||
|
||||
LandObject::~LandObject()
|
||||
{
|
||||
if (mLand && mLoadFlags) // only unload if we were responsible for loading to begin with.
|
||||
mLand->unloadData();
|
||||
}
|
||||
|
||||
const ESM::Land::LandData *LandObject::getData(int flags) const
|
||||
{
|
||||
return mLand->getLandData(flags);
|
||||
}
|
||||
|
||||
int LandObject::getPlugin() const
|
||||
{
|
||||
return mLand->mPlugin;
|
||||
}
|
||||
|
||||
|
||||
const float defaultHeight = ESM::Land::DEFAULT_HEIGHT;
|
||||
|
||||
Storage::Storage(const VFS::Manager *vfs, const std::string& normalMapPattern, const std::string& normalHeightMapPattern, bool autoUseNormalMaps, const std::string& specularMapPattern, bool autoUseSpecularMaps)
|
||||
@ -28,14 +61,6 @@ namespace ESMTerrain
|
||||
{
|
||||
}
|
||||
|
||||
const ESM::Land::LandData *Storage::getLandData (int cellX, int cellY, int flags)
|
||||
{
|
||||
if (const ESM::Land *land = getLand (cellX, cellY))
|
||||
return land->getLandData (flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Storage::getMinMaxHeights(float size, const osg::Vec2f ¢er, float &min, float &max)
|
||||
{
|
||||
assert (size <= 1 && "Storage::getMinMaxHeights, chunk size should be <= 1 cell");
|
||||
@ -53,7 +78,9 @@ namespace ESMTerrain
|
||||
int endRow = startRow + size * (ESM::Land::LAND_SIZE-1) + 1;
|
||||
int endColumn = startColumn + size * (ESM::Land::LAND_SIZE-1) + 1;
|
||||
|
||||
if (const ESM::Land::LandData *data = getLandData (cellX, cellY, ESM::Land::DATA_VHGT))
|
||||
osg::ref_ptr<const LandObject> land = getLand (cellX, cellY);
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : 0;
|
||||
if (data)
|
||||
{
|
||||
min = std::numeric_limits<float>::max();
|
||||
max = -std::numeric_limits<float>::max();
|
||||
@ -99,7 +126,9 @@ namespace ESMTerrain
|
||||
row += ESM::Land::LAND_SIZE-1;
|
||||
}
|
||||
|
||||
if (const ESM::Land::LandData *data = getLandData (cellX, cellY, ESM::Land::DATA_VNML))
|
||||
osg::ref_ptr<const LandObject> land = getLand(cellX, cellY);
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VNML) : 0;
|
||||
if (data)
|
||||
{
|
||||
normal.x() = data->mNormals[col*ESM::Land::LAND_SIZE*3+row*3];
|
||||
normal.y() = data->mNormals[col*ESM::Land::LAND_SIZE*3+row*3+1];
|
||||
@ -134,7 +163,9 @@ namespace ESMTerrain
|
||||
row = 0;
|
||||
}
|
||||
|
||||
if (const ESM::Land::LandData *data = getLandData (cellX, cellY, ESM::Land::DATA_VCLR))
|
||||
osg::ref_ptr<const LandObject> land = getLand(cellX, cellY);
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VCLR) : 0;
|
||||
if (data)
|
||||
{
|
||||
color.r() = data->mColours[col*ESM::Land::LAND_SIZE*3+row*3] / 255.f;
|
||||
color.g() = data->mColours[col*ESM::Land::LAND_SIZE*3+row*3+1] / 255.f;
|
||||
@ -146,7 +177,6 @@ namespace ESMTerrain
|
||||
color.g() = 1;
|
||||
color.b() = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Storage::fillVertexBuffers (int lodLevel, float size, const osg::Vec2f& center,
|
||||
@ -180,9 +210,16 @@ namespace ESMTerrain
|
||||
float vertX_ = 0; // of current cell corner
|
||||
for (int cellX = startCellX; cellX < startCellX + std::ceil(size); ++cellX)
|
||||
{
|
||||
const ESM::Land::LandData *heightData = getLandData (cellX, cellY, ESM::Land::DATA_VHGT);
|
||||
const ESM::Land::LandData *normalData = getLandData (cellX, cellY, ESM::Land::DATA_VNML);
|
||||
const ESM::Land::LandData *colourData = getLandData (cellX, cellY, ESM::Land::DATA_VCLR);
|
||||
osg::ref_ptr<const LandObject> land = getLand(cellX, cellY);
|
||||
const ESM::Land::LandData *heightData = 0;
|
||||
const ESM::Land::LandData *normalData = 0;
|
||||
const ESM::Land::LandData *colourData = 0;
|
||||
if (land)
|
||||
{
|
||||
heightData = land->getData(ESM::Land::DATA_VHGT);
|
||||
normalData = land->getData(ESM::Land::DATA_VNML);
|
||||
colourData = land->getData(ESM::Land::DATA_VCLR);
|
||||
}
|
||||
|
||||
int rowStart = 0;
|
||||
int colStart = 0;
|
||||
@ -298,15 +335,16 @@ namespace ESMTerrain
|
||||
assert(x<ESM::Land::LAND_TEXTURE_SIZE);
|
||||
assert(y<ESM::Land::LAND_TEXTURE_SIZE);
|
||||
|
||||
if (const ESM::Land::LandData *data = getLandData (cellX, cellY, ESM::Land::DATA_VTEX))
|
||||
osg::ref_ptr<const LandObject> land = getLand(cellX, cellY);
|
||||
const ESM::Land::LandData *data = land ? land->getData(ESM::Land::DATA_VTEX) : 0;
|
||||
if (data)
|
||||
{
|
||||
int tex = data->mTextures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
|
||||
if (tex == 0)
|
||||
return std::make_pair(0,0); // vtex 0 is always the base texture, regardless of plugin
|
||||
return std::make_pair(tex, getLand (cellX, cellY)->mPlugin);
|
||||
return std::make_pair(tex, land->getPlugin());
|
||||
}
|
||||
else
|
||||
return std::make_pair(0,0);
|
||||
return std::make_pair(0,0);
|
||||
}
|
||||
|
||||
std::string Storage::getTextureName(UniqueTextureId id)
|
||||
@ -421,8 +459,12 @@ namespace ESMTerrain
|
||||
int cellX = static_cast<int>(std::floor(worldPos.x() / 8192.f));
|
||||
int cellY = static_cast<int>(std::floor(worldPos.y() / 8192.f));
|
||||
|
||||
const ESM::Land* land = getLand(cellX, cellY);
|
||||
if (!land || !(land->mDataTypes&ESM::Land::DATA_VHGT))
|
||||
osg::ref_ptr<const LandObject> land = getLand(cellX, cellY);
|
||||
if (!land)
|
||||
return defaultHeight;
|
||||
|
||||
const ESM::Land::LandData* data = land->getData(ESM::Land::DATA_VHGT);
|
||||
if (!data)
|
||||
return defaultHeight;
|
||||
|
||||
// Mostly lifted from Ogre::Terrain::getHeightAtTerrainPosition
|
||||
@ -461,10 +503,10 @@ namespace ESMTerrain
|
||||
*/
|
||||
|
||||
// Build all 4 positions in normalized cell space, using point-sampled height
|
||||
osg::Vec3f v0 (startXTS, startYTS, getVertexHeight(land, startX, startY) / 8192.f);
|
||||
osg::Vec3f v1 (endXTS, startYTS, getVertexHeight(land, endX, startY) / 8192.f);
|
||||
osg::Vec3f v2 (endXTS, endYTS, getVertexHeight(land, endX, endY) / 8192.f);
|
||||
osg::Vec3f v3 (startXTS, endYTS, getVertexHeight(land, startX, endY) / 8192.f);
|
||||
osg::Vec3f v0 (startXTS, startYTS, getVertexHeight(data, startX, startY) / 8192.f);
|
||||
osg::Vec3f v1 (endXTS, startYTS, getVertexHeight(data, endX, startY) / 8192.f);
|
||||
osg::Vec3f v2 (endXTS, endYTS, getVertexHeight(data, endX, endY) / 8192.f);
|
||||
osg::Vec3f v3 (startXTS, endYTS, getVertexHeight(data, startX, endY) / 8192.f);
|
||||
// define this plane in terrain space
|
||||
osg::Plane plane;
|
||||
// FIXME: deal with differing triangle alignment
|
||||
@ -496,11 +538,11 @@ namespace ESMTerrain
|
||||
|
||||
}
|
||||
|
||||
float Storage::getVertexHeight(const ESM::Land *land, int x, int y)
|
||||
float Storage::getVertexHeight(const ESM::Land::LandData* data, int x, int y)
|
||||
{
|
||||
assert(x < ESM::Land::LAND_SIZE);
|
||||
assert(y < ESM::Land::LAND_SIZE);
|
||||
return land->getLandData()->mHeights[y * ESM::Land::LAND_SIZE + x];
|
||||
return data->mHeights[y * ESM::Land::LAND_SIZE + x];
|
||||
}
|
||||
|
||||
Terrain::LayerInfo Storage::getLayerInfo(const std::string& texture)
|
||||
|
@ -16,25 +16,36 @@ namespace VFS
|
||||
namespace ESMTerrain
|
||||
{
|
||||
|
||||
/// @brief Wrapper around ESM::Land with reference counting. The wrapper needs to be held as long as the data is still in use
|
||||
/// Data will be unloaded when wrapper object is deleted
|
||||
class LandObject : public osg::Object
|
||||
{
|
||||
private:
|
||||
const ESM::Land* mLand;
|
||||
int mLoadFlags;
|
||||
|
||||
public:
|
||||
META_Object(ESMTerrain, LandObject)
|
||||
|
||||
const ESM::Land::LandData* getData(int flags) const;
|
||||
int getPlugin() const;
|
||||
|
||||
LandObject();
|
||||
LandObject(const ESM::Land* land, int loadFlags);
|
||||
LandObject(const LandObject& copy, const osg::CopyOp& copyop);
|
||||
virtual ~LandObject();
|
||||
};
|
||||
|
||||
/// @brief Feeds data from ESM terrain records (ESM::Land, ESM::LandTexture)
|
||||
/// into the terrain component, converting it on the fly as needed.
|
||||
class Storage : public Terrain::Storage
|
||||
{
|
||||
private:
|
||||
|
||||
// Not implemented in this class, because we need different Store implementations for game and editor
|
||||
virtual const ESM::Land* getLand (int cellX, int cellY)= 0;
|
||||
virtual const ESM::LandTexture* getLandTexture(int index, short plugin) = 0;
|
||||
|
||||
public:
|
||||
Storage(const VFS::Manager* vfs, const std::string& normalMapPattern = "", const std::string& normalHeightMapPattern = "", bool autoUseNormalMaps = false, const std::string& specularMapPattern = "", bool autoUseSpecularMaps = false);
|
||||
|
||||
/// Data is loaded first, if necessary. Will return a 0-pointer if there is no data for
|
||||
/// any of the data types specified via \a flags. Will also return a 0-pointer if there
|
||||
/// is no land record for the coordinates \a cellX / \a cellY.
|
||||
const ESM::Land::LandData *getLandData (int cellX, int cellY, int flags);
|
||||
|
||||
// Not implemented in this class, because we need different Store implementations for game and editor
|
||||
virtual osg::ref_ptr<const LandObject> getLand (int cellX, int cellY)= 0;
|
||||
virtual const ESM::LandTexture* getLandTexture(int index, short plugin) = 0;
|
||||
/// Get bounds of the whole terrain in cell units
|
||||
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY) = 0;
|
||||
|
||||
@ -95,7 +106,7 @@ namespace ESMTerrain
|
||||
void fixColour (osg::Vec4f& colour, int cellX, int cellY, int col, int row);
|
||||
void averageNormal (osg::Vec3f& normal, int cellX, int cellY, int col, int row);
|
||||
|
||||
float getVertexHeight (const ESM::Land* land, int x, int y);
|
||||
float getVertexHeight (const ESM::Land::LandData* data, int x, int y);
|
||||
|
||||
// Since plugins can define new texture palettes, we need to know the plugin index too
|
||||
// in order to retrieve the correct texture name.
|
||||
|
@ -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", "", "UnrefQueue"};
|
||||
const char* statNames[] = {"Compiling", "WorkQueue", "WorkThread", "", "Texture", "StateSet", "Node", "Node Instance", "Shape", "Shape Instance", "Image", "Nif", "Keyframe", "Terrain Cell", "Terrain Texture", "Land", "", "UnrefQueue"};
|
||||
|
||||
int numLines = sizeof(statNames) / sizeof(statNames[0]);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user