diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 39aeb64371..113a4a8317 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -31,9 +31,9 @@ namespace MWRender static_cast(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 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 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 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()); - } } //---------------------------------------------------------------------------------------------- diff --git a/apps/openmw/mwrender/terrain.hpp b/apps/openmw/mwrender/terrain.hpp index c298b7fc18..eba437a2d5 100644 --- a/apps/openmw/mwrender/terrain.hpp +++ b/apps/openmw/mwrender/terrain.hpp @@ -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