mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-19 23:23:54 +00:00
Fixed a crash when there were cells with no data, refactored to remove non mutable data from CellStore
This commit is contained in:
parent
99b2b6b648
commit
b76b62e5e4
7 changed files with 144 additions and 129 deletions
|
@ -23,7 +23,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const
|
||||||
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine)
|
:mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine)
|
||||||
{
|
{
|
||||||
mRendering.createScene("PlayerCam", 55, 5);
|
mRendering.createScene("PlayerCam", 55, 5);
|
||||||
mTerrainManager = new TerrainManager(mRendering.getScene());
|
mTerrainManager = new TerrainManager(mRendering.getScene(),
|
||||||
|
environment);
|
||||||
|
|
||||||
//The fog type must be set before any terrain objects are created as if the
|
//The fog type must be set before any terrain objects are created as if the
|
||||||
//fog type is set to FOG_NONE then the initially created terrain won't have any fog
|
//fog type is set to FOG_NONE then the initially created terrain won't have any fog
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#include <OgreTerrain.h>
|
#include <OgreTerrain.h>
|
||||||
#include <OgreTerrainGroup.h>
|
#include <OgreTerrainGroup.h>
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/world.hpp"
|
||||||
|
|
||||||
#include "terrainmaterial.hpp"
|
#include "terrainmaterial.hpp"
|
||||||
#include "terrain.hpp"
|
#include "terrain.hpp"
|
||||||
|
|
||||||
#include "components/esm/loadland.hpp"
|
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
|
||||||
|
|
||||||
using namespace Ogre;
|
using namespace Ogre;
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@ namespace MWRender
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
TerrainManager::TerrainManager(SceneManager* mgr)
|
TerrainManager::TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& evn) :
|
||||||
|
mEnvironment(evn)
|
||||||
{
|
{
|
||||||
mTerrainGlobals = OGRE_NEW TerrainGlobalOptions();
|
mTerrainGlobals = OGRE_NEW TerrainGlobalOptions();
|
||||||
|
|
||||||
|
@ -102,6 +103,12 @@ namespace MWRender
|
||||||
const int cellX = store->cell->getGridX();
|
const int cellX = store->cell->getGridX();
|
||||||
const int cellY = store->cell->getGridY();
|
const int cellY = store->cell->getGridY();
|
||||||
|
|
||||||
|
ESM::Land* land = mEnvironment.mWorld->getStore().lands.search(cellX, cellY);
|
||||||
|
if ( land != NULL )
|
||||||
|
{
|
||||||
|
land->loadData();
|
||||||
|
}
|
||||||
|
|
||||||
//split the cell terrain into four segments
|
//split the cell terrain into four segments
|
||||||
const int numTextures = ESM::Land::LAND_TEXTURE_SIZE/2;
|
const int numTextures = ESM::Land::LAND_TEXTURE_SIZE/2;
|
||||||
|
|
||||||
|
@ -122,6 +129,8 @@ namespace MWRender
|
||||||
mLandSize*mLandSize,
|
mLandSize*mLandSize,
|
||||||
MEMCATEGORY_GEOMETRY);
|
MEMCATEGORY_GEOMETRY);
|
||||||
|
|
||||||
|
if ( land != NULL )
|
||||||
|
{
|
||||||
//copy the height data row by row
|
//copy the height data row by row
|
||||||
for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ )
|
for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ )
|
||||||
{
|
{
|
||||||
|
@ -132,12 +141,17 @@ namespace MWRender
|
||||||
const size_t xOffset = x * (mLandSize-1);
|
const size_t xOffset = x * (mLandSize-1);
|
||||||
|
|
||||||
memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize],
|
memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize],
|
||||||
&store->land[1][1]->landData->heights[yOffset + xOffset],
|
&land->landData->heights[yOffset + xOffset],
|
||||||
mLandSize*sizeof(float));
|
mLandSize*sizeof(float));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(terrainData.inputFloat, 0, mLandSize*mLandSize*sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
std::map<uint16_t, int> indexes;
|
std::map<uint16_t, int> indexes;
|
||||||
initTerrainTextures(&terrainData, store,
|
initTerrainTextures(&terrainData, cellX, cellY,
|
||||||
x * numTextures, y * numTextures,
|
x * numTextures, y * numTextures,
|
||||||
numTextures, indexes);
|
numTextures, indexes);
|
||||||
|
|
||||||
|
@ -148,16 +162,18 @@ namespace MWRender
|
||||||
mTerrainGroup->loadTerrain(terrainX, terrainY, true);
|
mTerrainGroup->loadTerrain(terrainX, terrainY, true);
|
||||||
|
|
||||||
Terrain* terrain = mTerrainGroup->getTerrain(terrainX, terrainY);
|
Terrain* terrain = mTerrainGroup->getTerrain(terrainX, terrainY);
|
||||||
initTerrainBlendMaps(terrain, store,
|
initTerrainBlendMaps(terrain,
|
||||||
|
cellX, cellY,
|
||||||
x * numTextures, y * numTextures,
|
x * numTextures, y * numTextures,
|
||||||
numTextures,
|
numTextures,
|
||||||
indexes);
|
indexes);
|
||||||
|
|
||||||
if ( store->land[1][1]->landData->usingColours )
|
if ( land->landData->usingColours )
|
||||||
{
|
{
|
||||||
// disable or enable global colour map (depends on available vertex colours)
|
// disable or enable global colour map (depends on available vertex colours)
|
||||||
mActiveProfile->setGlobalColourMapEnabled(true);
|
mActiveProfile->setGlobalColourMapEnabled(true);
|
||||||
TexturePtr vertex = getVertexColours(store,
|
TexturePtr vertex = getVertexColours(land,
|
||||||
|
cellX, cellY,
|
||||||
x*(mLandSize-1),
|
x*(mLandSize-1),
|
||||||
y*(mLandSize-1),
|
y*(mLandSize-1),
|
||||||
mLandSize);
|
mLandSize);
|
||||||
|
@ -197,11 +213,10 @@ namespace MWRender
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void TerrainManager::initTerrainTextures(Terrain::ImportData* terrainData,
|
void TerrainManager::initTerrainTextures(Terrain::ImportData* terrainData,
|
||||||
MWWorld::Ptr::CellStore* store,
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size,
|
int fromX, int fromY, int size,
|
||||||
std::map<uint16_t, int>& indexes)
|
std::map<uint16_t, int>& indexes)
|
||||||
{
|
{
|
||||||
assert(store != NULL && "store must be a valid pointer");
|
|
||||||
assert(terrainData != NULL && "Must have valid terrain data");
|
assert(terrainData != NULL && "Must have valid terrain data");
|
||||||
assert(fromX >= 0 && fromY >= 0 &&
|
assert(fromX >= 0 && fromY >= 0 &&
|
||||||
"Can't get a terrain texture on terrain outside the current cell");
|
"Can't get a terrain texture on terrain outside the current cell");
|
||||||
|
@ -219,7 +234,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
for ( int x = fromX - 1; x < fromX + size + 1; x++ )
|
for ( int x = fromX - 1; x < fromX + size + 1; x++ )
|
||||||
{
|
{
|
||||||
ltexIndexes.insert(getLtexIndexAt(store, x, y));
|
ltexIndexes.insert(getLtexIndexAt(cellX, cellY, x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +259,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
//NB: All vtex ids are +1 compared to the ltex ids
|
//NB: All vtex ids are +1 compared to the ltex ids
|
||||||
|
|
||||||
assert( (int)store->landTextures->ltex.size() >= (int)ltexIndex - 1 &&
|
assert( (int)mEnvironment.mWorld->getStore().landTexts.getSize() >= (int)ltexIndex - 1 &&
|
||||||
"LAND.VTEX must be within the bounds of the LTEX array");
|
"LAND.VTEX must be within the bounds of the LTEX array");
|
||||||
|
|
||||||
std::string texture;
|
std::string texture;
|
||||||
|
@ -254,7 +269,7 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
texture = store->landTextures->ltex[ltexIndex-1].texture;
|
texture = mEnvironment.mWorld->getStore().landTexts.search(ltexIndex-1)->texture;
|
||||||
//TODO this is needed due to MWs messed up texture handling
|
//TODO this is needed due to MWs messed up texture handling
|
||||||
texture = texture.substr(0, texture.rfind(".")) + ".dds";
|
texture = texture.substr(0, texture.rfind(".")) + ".dds";
|
||||||
}
|
}
|
||||||
|
@ -280,11 +295,10 @@ namespace MWRender
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void TerrainManager::initTerrainBlendMaps(Terrain* terrain,
|
void TerrainManager::initTerrainBlendMaps(Terrain* terrain,
|
||||||
MWWorld::Ptr::CellStore* store,
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size,
|
int fromX, int fromY, int size,
|
||||||
const std::map<uint16_t, int>& indexes)
|
const std::map<uint16_t, int>& indexes)
|
||||||
{
|
{
|
||||||
assert(store != NULL && "store must be a valid pointer");
|
|
||||||
assert(terrain != NULL && "Must have valid terrain");
|
assert(terrain != NULL && "Must have valid terrain");
|
||||||
assert(fromX >= 0 && fromY >= 0 &&
|
assert(fromX >= 0 && fromY >= 0 &&
|
||||||
"Can't get a terrain texture on terrain outside the current cell");
|
"Can't get a terrain texture on terrain outside the current cell");
|
||||||
|
@ -313,7 +327,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
for ( int texX = fromX - 1; texX < fromX + size + 1; texX++ )
|
for ( int texX = fromX - 1; texX < fromX + size + 1; texX++ )
|
||||||
{
|
{
|
||||||
const uint16_t ltexIndex = getLtexIndexAt(store, texX, texY);
|
const uint16_t ltexIndex = getLtexIndexAt(cellX, cellY, texX, texY);
|
||||||
|
|
||||||
//check if it is the base texture (which isn't in the map) and
|
//check if it is the base texture (which isn't in the map) and
|
||||||
//if it is don't bother altering the blend map for it
|
//if it is don't bother altering the blend map for it
|
||||||
|
@ -332,8 +346,10 @@ namespace MWRender
|
||||||
float* const pBlend = terrain->getLayerBlendMap(layerIndex)
|
float* const pBlend = terrain->getLayerBlendMap(layerIndex)
|
||||||
->getBlendPointer();
|
->getBlendPointer();
|
||||||
|
|
||||||
for ( int y = -1; y < splatSize + 1; y++ ){
|
for ( int y = -1; y < splatSize + 1; y++ )
|
||||||
for ( int x = -1; x < splatSize + 1; x++ ){
|
{
|
||||||
|
for ( int x = -1; x < splatSize + 1; x++ )
|
||||||
|
{
|
||||||
|
|
||||||
//Note: Y is reversed
|
//Note: Y is reversed
|
||||||
const int splatY = blendMapSize - 1 - relY * splatSize - y;
|
const int splatY = blendMapSize - 1 - relY * splatSize - y;
|
||||||
|
@ -373,7 +389,7 @@ namespace MWRender
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
int TerrainManager::getLtexIndexAt(MWWorld::Ptr::CellStore* store,
|
int TerrainManager::getLtexIndexAt(int cellX, int cellY,
|
||||||
int x, int y)
|
int x, int y)
|
||||||
{
|
{
|
||||||
//check texture index falls within the 9 cell bounds
|
//check texture index falls within the 9 cell bounds
|
||||||
|
@ -386,12 +402,6 @@ namespace MWRender
|
||||||
y < 2*ESM::Land::LAND_TEXTURE_SIZE &&
|
y < 2*ESM::Land::LAND_TEXTURE_SIZE &&
|
||||||
"Trying to get land textures that are out of bounds");
|
"Trying to get land textures that are out of bounds");
|
||||||
|
|
||||||
assert(store != NULL && "Store pointer must be valid");
|
|
||||||
|
|
||||||
//default center cell is indexed at (1,1)
|
|
||||||
int cellX = 1;
|
|
||||||
int cellY = 1;
|
|
||||||
|
|
||||||
if ( x < 0 )
|
if ( x < 0 )
|
||||||
{
|
{
|
||||||
cellX--;
|
cellX--;
|
||||||
|
@ -414,22 +424,32 @@ namespace MWRender
|
||||||
y -= ESM::Land::LAND_TEXTURE_SIZE;
|
y -= ESM::Land::LAND_TEXTURE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return store->land[cellX][cellY]
|
|
||||||
->landData
|
ESM::Land* land = mEnvironment.mWorld->getStore().lands.search(cellX, cellY);
|
||||||
|
if ( land != NULL )
|
||||||
|
{
|
||||||
|
land->loadData();
|
||||||
|
return land->landData
|
||||||
->textures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
|
->textures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
TexturePtr TerrainManager::getVertexColours(MWWorld::Ptr::CellStore* store,
|
TexturePtr TerrainManager::getVertexColours(ESM::Land* land,
|
||||||
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size)
|
int fromX, int fromY, int size)
|
||||||
{
|
{
|
||||||
TextureManager* const texMgr = TextureManager::getSingletonPtr();
|
TextureManager* const texMgr = TextureManager::getSingletonPtr();
|
||||||
|
|
||||||
const std::string colourTextureName = "VtexColours_" +
|
const std::string colourTextureName = "VtexColours_" +
|
||||||
boost::lexical_cast<std::string>(store->cell->getGridX()) +
|
boost::lexical_cast<std::string>(cellX) +
|
||||||
"_" +
|
"_" +
|
||||||
boost::lexical_cast<std::string>(store->cell->getGridY()) +
|
boost::lexical_cast<std::string>(cellY) +
|
||||||
"_" +
|
"_" +
|
||||||
boost::lexical_cast<std::string>(fromX) +
|
boost::lexical_cast<std::string>(fromX) +
|
||||||
"_" +
|
"_" +
|
||||||
|
@ -452,14 +472,16 @@ namespace MWRender
|
||||||
|
|
||||||
uint8* pDest = static_cast<uint8*>(pixelBox.data);
|
uint8* pDest = static_cast<uint8*>(pixelBox.data);
|
||||||
|
|
||||||
const char* const colours = store->land[1][1]->landData->colours;
|
if ( land != NULL )
|
||||||
|
{
|
||||||
|
const char* const colours = land->landData->colours;
|
||||||
for ( int y = 0; y < size; y++ )
|
for ( int y = 0; y < size; y++ )
|
||||||
{
|
{
|
||||||
for ( int x = 0; x < size; x++ )
|
for ( int x = 0; x < size; x++ )
|
||||||
{
|
{
|
||||||
const size_t colourOffset = (y+fromY)*3*65 + (x+fromX)*3;
|
const size_t colourOffset = (y+fromY)*3*65 + (x+fromX)*3;
|
||||||
|
|
||||||
assert( colourOffset >= 0 && colourOffset < 65*65*3 &&
|
assert( colourOffset < 65*65*3 &&
|
||||||
"Colour offset is out of the expected bounds of record" );
|
"Colour offset is out of the expected bounds of record" );
|
||||||
|
|
||||||
const unsigned char r = colours[colourOffset + 0];
|
const unsigned char r = colours[colourOffset + 0];
|
||||||
|
@ -473,6 +495,20 @@ namespace MWRender
|
||||||
pDest[imageOffset + 2] = r;
|
pDest[imageOffset + 2] = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for ( int y = 0; y < size; y++ )
|
||||||
|
{
|
||||||
|
for ( int x = 0; x < size; x++ )
|
||||||
|
{
|
||||||
|
for ( int k = 0; k < 3; k++ )
|
||||||
|
{
|
||||||
|
*pDest++ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pixelBuffer->unlock();
|
pixelBuffer->unlock();
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace MWRender{
|
||||||
*/
|
*/
|
||||||
class TerrainManager{
|
class TerrainManager{
|
||||||
public:
|
public:
|
||||||
TerrainManager(Ogre::SceneManager*);
|
TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& env);
|
||||||
virtual ~TerrainManager();
|
virtual ~TerrainManager();
|
||||||
|
|
||||||
void setDiffuse(const Ogre::ColourValue& diffuse);
|
void setDiffuse(const Ogre::ColourValue& diffuse);
|
||||||
|
@ -35,6 +35,8 @@ namespace MWRender{
|
||||||
Ogre::TerrainGlobalOptions* mTerrainGlobals;
|
Ogre::TerrainGlobalOptions* mTerrainGlobals;
|
||||||
Ogre::TerrainGroup* mTerrainGroup;
|
Ogre::TerrainGroup* mTerrainGroup;
|
||||||
|
|
||||||
|
const MWWorld::Environment& mEnvironment;
|
||||||
|
|
||||||
Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile;
|
Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +55,8 @@ namespace MWRender{
|
||||||
* layer
|
* layer
|
||||||
*
|
*
|
||||||
* @param terrainData the terrain data to setup the textures for
|
* @param terrainData the terrain data to setup the textures for
|
||||||
* @param store the cell store for the given terrain cell
|
* @param cellX the coord of the cell
|
||||||
|
* @param cellY the coord of the cell
|
||||||
* @param fromX the ltex index in the current cell to start making the texture from
|
* @param fromX the ltex index in the current cell to start making the texture from
|
||||||
* @param fromY the ltex index in the current cell to start making the texture from
|
* @param fromY the ltex index in the current cell to start making the texture from
|
||||||
* @param size the size (number of splats) to get
|
* @param size the size (number of splats) to get
|
||||||
|
@ -61,7 +64,7 @@ namespace MWRender{
|
||||||
* can be used by initTerrainBlendMaps
|
* can be used by initTerrainBlendMaps
|
||||||
*/
|
*/
|
||||||
void initTerrainTextures(Ogre::Terrain::ImportData* terrainData,
|
void initTerrainTextures(Ogre::Terrain::ImportData* terrainData,
|
||||||
MWWorld::Ptr::CellStore* store,
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size,
|
int fromX, int fromY, int size,
|
||||||
std::map<uint16_t, int>& indexes);
|
std::map<uint16_t, int>& indexes);
|
||||||
|
|
||||||
|
@ -69,14 +72,15 @@ namespace MWRender{
|
||||||
* Creates the blend (splatting maps) for the given terrain from the ltex data.
|
* Creates the blend (splatting maps) for the given terrain from the ltex data.
|
||||||
*
|
*
|
||||||
* @param terrain the terrain object for the current cell
|
* @param terrain the terrain object for the current cell
|
||||||
* @param store the cell store for the given terrain cell
|
* @param cellX the coord of the cell
|
||||||
|
* @param cellY the coord of the cell
|
||||||
* @param fromX the ltex index in the current cell to start making the texture from
|
* @param fromX the ltex index in the current cell to start making the texture from
|
||||||
* @param fromY the ltex index in the current cell to start making the texture from
|
* @param fromY the ltex index in the current cell to start making the texture from
|
||||||
* @param size the size (number of splats) to get
|
* @param size the size (number of splats) to get
|
||||||
* @param indexes the mapping of ltex to blend map produced by initTerrainTextures
|
* @param indexes the mapping of ltex to blend map produced by initTerrainTextures
|
||||||
*/
|
*/
|
||||||
void initTerrainBlendMaps(Ogre::Terrain* terrain,
|
void initTerrainBlendMaps(Ogre::Terrain* terrain,
|
||||||
MWWorld::Ptr::CellStore* store,
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size,
|
int fromX, int fromY, int size,
|
||||||
const std::map<uint16_t, int>& indexes);
|
const std::map<uint16_t, int>& indexes);
|
||||||
|
|
||||||
|
@ -85,22 +89,25 @@ namespace MWRender{
|
||||||
* starts at (0,0). This supports getting values from the surrounding
|
* starts at (0,0). This supports getting values from the surrounding
|
||||||
* cells so negative x, y is acceptable
|
* cells so negative x, y is acceptable
|
||||||
*
|
*
|
||||||
* @param store the cell store for the current cell
|
* @param cellX the coord of the cell
|
||||||
|
* @param cellY the coord of the cell
|
||||||
* @param x, y the splat position of the ltex index to get relative to the
|
* @param x, y the splat position of the ltex index to get relative to the
|
||||||
* first splat of the current cell
|
* first splat of the current cell
|
||||||
*/
|
*/
|
||||||
int getLtexIndexAt(MWWorld::Ptr::CellStore* store, int x, int y);
|
int getLtexIndexAt(int cellX, int cellY, int x, int y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Due to the fact that Ogre terrain doesn't support vertex colours
|
* Due to the fact that Ogre terrain doesn't support vertex colours
|
||||||
* we have to generate them manually
|
* we have to generate them manually
|
||||||
*
|
*
|
||||||
* @param store the cell store for the given terrain cell
|
* @param cellX the coord of the cell
|
||||||
|
* @param cellY the coord of the cell
|
||||||
* @param fromX the *vertex* index in the current cell to start making texture from
|
* @param fromX the *vertex* index in the current cell to start making texture from
|
||||||
* @param fromY the *vertex* index in the current cell to start making the texture from
|
* @param fromY the *vertex* index in the current cell to start making the texture from
|
||||||
* @param size the size (number of vertexes) to get
|
* @param size the size (number of vertexes) to get
|
||||||
*/
|
*/
|
||||||
Ogre::TexturePtr getVertexColours(MWWorld::Ptr::CellStore* store,
|
Ogre::TexturePtr getVertexColours(ESM::Land* land,
|
||||||
|
int cellX, int cellY,
|
||||||
int fromX, int fromY, int size);
|
int fromX, int fromY, int size);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ namespace ESM
|
||||||
{
|
{
|
||||||
void Land::load(ESMReader &esm)
|
void Land::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
mEsm = &esm;
|
||||||
|
|
||||||
// Get the grid location
|
// Get the grid location
|
||||||
esm.getSubNameIs("INTV");
|
esm.getSubNameIs("INTV");
|
||||||
esm.getSubHeaderIs(8);
|
esm.getSubHeaderIs(8);
|
||||||
|
@ -51,7 +53,7 @@ void Land::load(ESMReader &esm)
|
||||||
landData = NULL;
|
landData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Land::loadData(ESMReader &esm)
|
void Land::loadData()
|
||||||
{
|
{
|
||||||
if (dataLoaded)
|
if (dataLoaded)
|
||||||
{
|
{
|
||||||
|
@ -62,17 +64,17 @@ void Land::loadData(ESMReader &esm)
|
||||||
|
|
||||||
if (hasData)
|
if (hasData)
|
||||||
{
|
{
|
||||||
esm.restoreContext(context);
|
mEsm->restoreContext(context);
|
||||||
|
|
||||||
//esm.getHNExact(landData->normals, sizeof(VNML), "VNML");
|
//esm.getHNExact(landData->normals, sizeof(VNML), "VNML");
|
||||||
if (esm.isNextSub("VNML"))
|
if (mEsm->isNextSub("VNML"))
|
||||||
{
|
{
|
||||||
esm.skipHSubSize(12675);
|
mEsm->skipHSubSize(12675);
|
||||||
}
|
}
|
||||||
|
|
||||||
VHGT rawHeights;
|
VHGT rawHeights;
|
||||||
|
|
||||||
esm.getHNExact(&rawHeights, sizeof(VHGT), "VHGT");
|
mEsm->getHNExact(&rawHeights, sizeof(VHGT), "VHGT");
|
||||||
int currentHeightOffset = rawHeights.heightOffset;
|
int currentHeightOffset = rawHeights.heightOffset;
|
||||||
for (int y = 0; y < LAND_SIZE; y++)
|
for (int y = 0; y < LAND_SIZE; y++)
|
||||||
{
|
{
|
||||||
|
@ -87,20 +89,20 @@ void Land::loadData(ESMReader &esm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (esm.isNextSub("WNAM"))
|
if (mEsm->isNextSub("WNAM"))
|
||||||
{
|
{
|
||||||
esm.skipHSubSize(81);
|
mEsm->skipHSubSize(81);
|
||||||
}
|
}
|
||||||
if (esm.isNextSub("VCLR"))
|
if (mEsm->isNextSub("VCLR"))
|
||||||
{
|
{
|
||||||
landData->usingColours = true;
|
landData->usingColours = true;
|
||||||
esm.getHExact(&landData->colours, 3*LAND_NUM_VERTS);
|
mEsm->getHExact(&landData->colours, 3*LAND_NUM_VERTS);
|
||||||
}else{
|
}else{
|
||||||
landData->usingColours = false;
|
landData->usingColours = false;
|
||||||
}
|
}
|
||||||
//TODO fix magic numbers
|
//TODO fix magic numbers
|
||||||
uint16_t vtex[512];
|
uint16_t vtex[512];
|
||||||
esm.getHNExact(&vtex, 512, "VTEX");
|
mEsm->getHNExact(&vtex, 512, "VTEX");
|
||||||
|
|
||||||
int readPos = 0; //bit ugly, but it works
|
int readPos = 0; //bit ugly, but it works
|
||||||
for ( int y1 = 0; y1 < 4; y1++ )
|
for ( int y1 = 0; y1 < 4; y1++ )
|
||||||
|
|
|
@ -17,6 +17,7 @@ struct Land
|
||||||
|
|
||||||
// File context. This allows the ESM reader to be 'reset' to this
|
// File context. This allows the ESM reader to be 'reset' to this
|
||||||
// location later when we are ready to load the full data set.
|
// location later when we are ready to load the full data set.
|
||||||
|
ESMReader* mEsm;
|
||||||
ESM_Context context;
|
ESM_Context context;
|
||||||
|
|
||||||
bool hasData;
|
bool hasData;
|
||||||
|
@ -70,7 +71,7 @@ struct Land
|
||||||
/**
|
/**
|
||||||
* Actually loads data
|
* Actually loads data
|
||||||
*/
|
*/
|
||||||
void loadData(ESMReader &esm);
|
void loadData();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees memory allocated for land data
|
* Frees memory allocated for land data
|
||||||
|
|
|
@ -124,9 +124,6 @@ namespace ESMS
|
||||||
CellRefList<Static, D> statics;
|
CellRefList<Static, D> statics;
|
||||||
CellRefList<Weapon, D> weapons;
|
CellRefList<Weapon, D> weapons;
|
||||||
|
|
||||||
const Land* land[3][3];
|
|
||||||
const LTexList* landTextures;
|
|
||||||
|
|
||||||
void load (const ESMStore &store, ESMReader &esm)
|
void load (const ESMStore &store, ESMReader &esm)
|
||||||
{
|
{
|
||||||
if (mState!=State_Loaded)
|
if (mState!=State_Loaded)
|
||||||
|
@ -138,21 +135,6 @@ namespace ESMS
|
||||||
|
|
||||||
loadRefs (store, esm);
|
loadRefs (store, esm);
|
||||||
|
|
||||||
if ( ! (cell->data.flags & ESM::Cell::Interior) )
|
|
||||||
{
|
|
||||||
for ( size_t x = 0; x < 3; x++ )
|
|
||||||
{
|
|
||||||
for ( size_t y = 0; y < 3; y++ )
|
|
||||||
{
|
|
||||||
land[x][y] = loadTerrain(cell->data.gridX + x - 1,
|
|
||||||
cell->data.gridY + y - 1,
|
|
||||||
store,
|
|
||||||
esm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
landTextures = &store.landTexts;
|
|
||||||
}
|
|
||||||
|
|
||||||
mState = State_Loaded;
|
mState = State_Loaded;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,24 +180,6 @@ namespace ESMS
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Land* loadTerrain(int X, int Y, const ESMStore &store, ESMReader &esm)
|
|
||||||
{
|
|
||||||
// load terrain
|
|
||||||
Land *land = store.lands.search(X, Y);
|
|
||||||
if (land != NULL)
|
|
||||||
{
|
|
||||||
land->loadData(esm);
|
|
||||||
}
|
|
||||||
|
|
||||||
return land;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unloadTerrain(int X, int Y, const ESMStore &store) {
|
|
||||||
assert (false &&
|
|
||||||
"This function is not implemented due to the fact that we now store overlapping land blocks so" &&
|
|
||||||
"we cannot be sure that the land segment is not being used by another CellStore");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Functor, class List>
|
template<class Functor, class List>
|
||||||
bool forEachImp (Functor& functor, List& list)
|
bool forEachImp (Functor& functor, List& list)
|
||||||
{
|
{
|
||||||
|
|
|
@ -201,15 +201,21 @@ namespace ESMS
|
||||||
|
|
||||||
// TODO: For multiple ESM/ESP files we need one list per file.
|
// TODO: For multiple ESM/ESP files we need one list per file.
|
||||||
std::vector<LandTexture> ltex;
|
std::vector<LandTexture> ltex;
|
||||||
int count;
|
|
||||||
|
|
||||||
LTexList() : count(0)
|
LTexList()
|
||||||
{
|
{
|
||||||
// More than enough to hold Morrowind.esm.
|
// More than enough to hold Morrowind.esm.
|
||||||
ltex.reserve(128);
|
ltex.reserve(128);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getSize() { return count; }
|
const LandTexture* search(size_t index) const
|
||||||
|
{
|
||||||
|
assert(index < ltex.size());
|
||||||
|
return <ex.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getSize() { return ltex.size(); }
|
||||||
|
int getSize() const { return ltex.size(); }
|
||||||
|
|
||||||
virtual void listIdentifier (std::vector<std::string>& identifier) const {}
|
virtual void listIdentifier (std::vector<std::string>& identifier) const {}
|
||||||
|
|
||||||
|
@ -236,9 +242,9 @@ namespace ESMS
|
||||||
virtual ~LandList() {}
|
virtual ~LandList() {}
|
||||||
|
|
||||||
// Map containing all landscapes
|
// Map containing all landscapes
|
||||||
typedef std::map<int, Land*> LandsCol;
|
typedef std::pair<int, int> LandCoord;
|
||||||
typedef std::map<int, LandsCol> Lands;
|
typedef std::map<LandCoord, Land*> LandMap;
|
||||||
Lands lands;
|
LandMap lands;
|
||||||
|
|
||||||
int count;
|
int count;
|
||||||
LandList() : count(0) {}
|
LandList() : count(0) {}
|
||||||
|
@ -249,15 +255,13 @@ namespace ESMS
|
||||||
// Find land for the given coordinates. Return null if no data.
|
// Find land for the given coordinates. Return null if no data.
|
||||||
Land *search(int x, int y) const
|
Land *search(int x, int y) const
|
||||||
{
|
{
|
||||||
Lands::const_iterator it = lands.find(x);
|
LandMap::const_iterator itr = lands.find(std::make_pair<int, int>(x, y));
|
||||||
if(it==lands.end())
|
if ( itr == lands.end() )
|
||||||
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
LandsCol::const_iterator it2 = it->second.find(y);
|
return itr->second;
|
||||||
if(it2 == it->second.end())
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return it2->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void load(ESMReader &esm, const std::string &id)
|
void load(ESMReader &esm, const std::string &id)
|
||||||
|
@ -266,11 +270,11 @@ namespace ESMS
|
||||||
|
|
||||||
// Create the structure and load it. This actually skips the
|
// Create the structure and load it. This actually skips the
|
||||||
// landscape data and remembers the file position for later.
|
// landscape data and remembers the file position for later.
|
||||||
Land *land = new Land;
|
Land *land = new Land();
|
||||||
land->load(esm);
|
land->load(esm);
|
||||||
|
|
||||||
// Store the structure
|
// Store the structure
|
||||||
lands[land->X][land->Y] = land;
|
lands[std::make_pair<int, int>(land->X, land->Y)] = land;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue