Removed the option of not splitting terrain as it was slower and adding to code complexity. The only real reason for keeping it, which was that it made debugging some texture issues easier is now gone.

This commit is contained in:
Jacob Essex 2012-03-02 21:03:53 +00:00
parent 3ecc427b96
commit 0f705eaca5
2 changed files with 69 additions and 139 deletions

View file

@ -31,9 +31,9 @@ namespace MWRender
static_cast<TerrainMaterialGeneratorB::SM2Profile*>(activeProfile);
mTerrainGlobals->setMaxPixelError(8);
mTerrainGlobals->setLayerBlendMapSize(SPLIT_TERRAIN ? 32 : 1024);
mTerrainGlobals->setLightMapSize(SPLIT_TERRAIN ? 256 : 1024);
mTerrainGlobals->setCompositeMapSize(SPLIT_TERRAIN ? 256 : 1024);
mTerrainGlobals->setLayerBlendMapSize(32);
mTerrainGlobals->setLightMapSize(256);
mTerrainGlobals->setCompositeMapSize(256);
mTerrainGlobals->setDefaultGlobalColourMapSize(256);
//10 (default) didn't seem to be quite enough
@ -52,29 +52,21 @@ namespace MWRender
matProfile->setReceiveDynamicShadowsEnabled(false);
matProfile->setGlobalColourMapEnabled(true);
mLandSize = ESM::Land::LAND_SIZE;
mRealSize = ESM::Land::REAL_SIZE;
if ( SPLIT_TERRAIN )
{
mLandSize = (mLandSize - 1)/2 + 1;
mRealSize /= 2;
}
mTerrainGroup = OGRE_NEW Ogre::TerrainGroup(mgr,
Ogre::Terrain::ALIGN_X_Z,
mLandSize,
mRealSize);
mWorldSize);
mTerrainGroup->setOrigin(Ogre::Vector3(mRealSize/2,
mTerrainGroup->setOrigin(Ogre::Vector3(mWorldSize/2,
0,
-mRealSize/2));
-mWorldSize/2));
Ogre::Terrain::ImportData& importSettings =
mTerrainGroup->getDefaultImportSettings();
importSettings.inputBias = 0;
importSettings.terrainSize = mLandSize;
importSettings.worldSize = mRealSize;
importSettings.worldSize = mWorldSize;
importSettings.minBatchSize = 9;
importSettings.maxBatchSize = mLandSize;
@ -111,109 +103,72 @@ namespace MWRender
const int cellY = store->cell->getGridY();
if ( SPLIT_TERRAIN )
//split the cell terrain into four segments
const int numTextures = ESM::Land::LAND_TEXTURE_SIZE/2;
for ( int x = 0; x < 2; x++ )
{
//split the cell terrain into four segments
const int numTextures = ESM::Land::LAND_TEXTURE_SIZE/2;
for ( int x = 0; x < 2; x++ )
for ( int y = 0; y < 2; y++ )
{
for ( int y = 0; y < 2; y++ )
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
const int terrainX = cellX * 2 + x;
const int terrainY = cellY * 2 + y;
//it makes far more sense to reallocate the memory here,
//and let Ogre deal with it due to the issues with deleting
//it at the wrong time if using threads (Which Ogre::Terrain does)
terrainData.inputFloat = OGRE_ALLOC_T(float,
mLandSize*mLandSize,
Ogre::MEMCATEGORY_GEOMETRY);
//copy the height data row by row
for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ )
{
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
//the offset of the current segment
const size_t yOffset = y * (mLandSize-1) * ESM::Land::LAND_SIZE +
//offset of the row
terrainCopyY * ESM::Land::LAND_SIZE;
const size_t xOffset = x * (mLandSize-1);
const int terrainX = cellX * 2 + x;
const int terrainY = cellY * 2 + y;
memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize],
&store->land[1][1]->landData->heights[yOffset + xOffset],
mLandSize*sizeof(float));
}
//it makes far more sense to reallocate the memory here,
//and let Ogre deal with it due to the issues with deleting
//it at the wrong time if using threads (Which Ogre::Terrain does)
terrainData.inputFloat = OGRE_ALLOC_T(float,
mLandSize*mLandSize,
Ogre::MEMCATEGORY_GEOMETRY);
std::map<uint16_t, int> indexes;
initTerrainTextures(&terrainData, store,
x * numTextures, y * numTextures,
numTextures, indexes);
//copy the height data row by row
for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ )
if (mTerrainGroup->getTerrain(cellX, cellY) == NULL)
{
mTerrainGroup->defineTerrain(terrainX, terrainY, &terrainData);
mTerrainGroup->loadTerrain(terrainX, terrainY, true);
Ogre::Terrain* terrain = mTerrainGroup->getTerrain(terrainX, terrainY);
initTerrainBlendMaps(terrain, store,
x * numTextures, y * numTextures,
numTextures,
indexes);
if ( store->land[1][1]->landData->usingColours )
{
//the offset of the current segment
const size_t yOffset = y * (mLandSize-1) * ESM::Land::LAND_SIZE +
//offset of the row
terrainCopyY * ESM::Land::LAND_SIZE;
const size_t xOffset = x * (mLandSize-1);
Ogre::TexturePtr vertex = getVertexColours(store,
x*(mLandSize-1),
y*(mLandSize-1),
mLandSize);
memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize],
&store->land[1][1]->landData->heights[yOffset + xOffset],
mLandSize*sizeof(float));
}
std::map<uint16_t, int> indexes;
initTerrainTextures(&terrainData, store,
x * numTextures, y * numTextures,
numTextures, indexes);
if (mTerrainGroup->getTerrain(cellX, cellY) == NULL)
{
mTerrainGroup->defineTerrain(terrainX, terrainY, &terrainData);
mTerrainGroup->loadTerrain(terrainX, terrainY, true);
Ogre::Terrain* terrain = mTerrainGroup->getTerrain(terrainX, terrainY);
initTerrainBlendMaps(terrain, store,
x * numTextures, y * numTextures,
numTextures,
indexes);
if ( store->land[1][1]->landData->usingColours )
{
Ogre::TexturePtr vertex = getVertexColours(store, x*32, y*32, mLandSize);
MaterialPtr mat = terrain->_getMaterial();
mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() );
mat = terrain->_getCompositeMapMaterial();
mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() );
}
MaterialPtr mat = terrain->_getMaterial();
mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() );
mat = terrain->_getCompositeMapMaterial();
mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() );
}
}
}
}
else
{
Ogre::Terrain::ImportData terrainData =
mTerrainGroup->getDefaultImportSettings();
//one cell is one terrain segment
terrainData.inputFloat = OGRE_ALLOC_T(float,
mLandSize*mLandSize,
Ogre::MEMCATEGORY_GEOMETRY);
memcpy(&terrainData.inputFloat[0],
&store->land[1][1]->landData->heights[0],
mLandSize*mLandSize*sizeof(float));
std::map<uint16_t, int> indexes;
initTerrainTextures(&terrainData, store, 0, 0,
ESM::Land::LAND_TEXTURE_SIZE, indexes);
mTerrainGroup->defineTerrain(cellX, cellY, &terrainData);
mTerrainGroup->loadTerrain(cellX, cellY, true);
Ogre::Terrain* terrain = mTerrainGroup->getTerrain(cellX, cellY);
initTerrainBlendMaps(terrain, store, 0, 0,
ESM::Land::LAND_TEXTURE_SIZE,
indexes);
if ( store->land[1][1]->landData->usingColours )
{
Ogre::TexturePtr vertex = getVertexColours(store, 0, 0, mLandSize);
MaterialPtr mat = terrain->_getMaterial();
mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() );
mat = terrain->_getCompositeMapMaterial();
mat->getTechnique(0)->getPass(0)->getTextureUnitState(1)->setTextureName( vertex->getName() );
}
}
mTerrainGroup->freeTemporaryResources();
}
@ -222,22 +177,14 @@ namespace MWRender
void TerrainManager::cellRemoved(MWWorld::Ptr::CellStore *store)
{
if ( SPLIT_TERRAIN )
for ( int x = 0; x < 2; x++ )
{
for ( int x = 0; x < 2; x++ )
for ( int y = 0; y < 2; y++ )
{
for ( int y = 0; y < 2; y++ )
{
mTerrainGroup->unloadTerrain(store->cell->getGridX() * 2 + x,
store->cell->getGridY() * 2 + y);
}
mTerrainGroup->unloadTerrain(store->cell->getGridX() * 2 + x,
store->cell->getGridY() * 2 + y);
}
}
else
{
mTerrainGroup->unloadTerrain(store->cell->getGridX(),
store->cell->getGridY());
}
}
//----------------------------------------------------------------------------------------------

View file

@ -17,14 +17,8 @@ namespace MWRender{
/**
* Implements the Morrowind terrain using the Ogre Terrain Component
*
* This currently has two options as to how the terrain is rendered, one
* is that one cell is rendered as one Ogre::Terrain and the other that
* it is rendered as 4 Ogre::Terrain segments
*
* Splitting it up into segments has the following advantages
* * Seems to be faster
* * Terrain can now be culled more aggressivly using view frustram culling
* * We don't hit splat limits as much
* Each terrain cell is split into four blocks as this leads to an increase
* in performance and means we don't hit splat limits quite as much
*/
class TerrainManager{
public:
@ -40,26 +34,15 @@ namespace MWRender{
Ogre::TerrainGlobalOptions* mTerrainGlobals;
Ogre::TerrainGroup* mTerrainGroup;
/**
* Should each cell be split into a further four Ogre::Terrain objects
*
* This has the advantage that it is possible to cull more terrain and
* we are more likly to be able to be able to fit all the required splats
* in (Ogre's default material generator only works with about 6 textures)
*/
static const bool SPLIT_TERRAIN = true;
/**
* The length in verticies of a single terrain block.
* This takes into account the SPLIT_TERRAIN option
*/
int mLandSize;
static const int mLandSize = (ESM::Land::LAND_SIZE - 1)/2 + 1;
/**
* The length in game units of a single terrain block.
* This takes into account the SPLIT_TERRAIN option
*/
int mRealSize;
static const int mWorldSize = ESM::Land::REAL_SIZE/2;
/**
* Setups up the list of textures for part of a cell, using indexes as