diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 386b36842..ddf7fe3b0 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -23,7 +23,8 @@ RenderingManager::RenderingManager (OEngine::Render::OgreRenderer& _rend, const :mRendering(_rend), mObjects(mRendering), mActors(mRendering, environment), mAmbientMode(0), mDebugging(engine) { 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 //fog type is set to FOG_NONE then the initially created terrain won't have any fog diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 64acd9fe3..ac60e6323 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -1,12 +1,12 @@ #include #include +#include + +#include "../mwworld/world.hpp" #include "terrainmaterial.hpp" #include "terrain.hpp" -#include "components/esm/loadland.hpp" - -#include using namespace Ogre; @@ -15,33 +15,33 @@ namespace MWRender //---------------------------------------------------------------------------------------------- - TerrainManager::TerrainManager(SceneManager* mgr) + TerrainManager::TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& evn) : + mEnvironment(evn), mTerrainGroup(TerrainGroup(mgr, Terrain::ALIGN_X_Z, mLandSize, mWorldSize)) { - mTerrainGlobals = OGRE_NEW TerrainGlobalOptions(); TerrainMaterialGeneratorPtr matGen; TerrainMaterialGeneratorB* matGenP = new TerrainMaterialGeneratorB(); matGen.bind(matGenP); - mTerrainGlobals->setDefaultMaterialGenerator(matGen); + mTerrainGlobals.setDefaultMaterialGenerator(matGen); TerrainMaterialGenerator::Profile* const activeProfile = - mTerrainGlobals->getDefaultMaterialGenerator() + mTerrainGlobals.getDefaultMaterialGenerator() ->getActiveProfile(); mActiveProfile = static_cast(activeProfile); //The pixel error should be as high as possible without it being noticed //as it governs how fast mesh quality decreases. - mTerrainGlobals->setMaxPixelError(8); + mTerrainGlobals.setMaxPixelError(8); - mTerrainGlobals->setLayerBlendMapSize(32); - mTerrainGlobals->setDefaultGlobalColourMapSize(65); + mTerrainGlobals.setLayerBlendMapSize(32); + mTerrainGlobals.setDefaultGlobalColourMapSize(65); //10 (default) didn't seem to be quite enough - mTerrainGlobals->setSkirtSize(128); + mTerrainGlobals.setSkirtSize(128); //due to the sudden flick between composite and non composite textures, //this seemed the distance where it wasn't too noticeable - mTerrainGlobals->setCompositeMapDistance(mWorldSize*2); + mTerrainGlobals.setCompositeMapDistance(mWorldSize*2); mActiveProfile->setLightmapEnabled(false); mActiveProfile->setLayerSpecularMappingEnabled(false); @@ -53,16 +53,11 @@ namespace MWRender //disabled mActiveProfile->setCompositeMapEnabled(false); - mTerrainGroup = OGRE_NEW TerrainGroup(mgr, - Terrain::ALIGN_X_Z, - mLandSize, - mWorldSize); - - mTerrainGroup->setOrigin(Vector3(mWorldSize/2, + mTerrainGroup.setOrigin(Vector3(mWorldSize/2, 0, -mWorldSize/2)); - Terrain::ImportData& importSettings = mTerrainGroup->getDefaultImportSettings(); + Terrain::ImportData& importSettings = mTerrainGroup.getDefaultImportSettings(); importSettings.inputBias = 0; importSettings.terrainSize = mLandSize; @@ -77,22 +72,20 @@ namespace MWRender TerrainManager::~TerrainManager() { - OGRE_DELETE mTerrainGroup; - OGRE_DELETE mTerrainGlobals; } //---------------------------------------------------------------------------------------------- void TerrainManager::setDiffuse(const ColourValue& diffuse) { - mTerrainGlobals->setCompositeMapDiffuse(diffuse); + mTerrainGlobals.setCompositeMapDiffuse(diffuse); } //---------------------------------------------------------------------------------------------- void TerrainManager::setAmbient(const ColourValue& ambient) { - mTerrainGlobals->setCompositeMapAmbient(ambient); + mTerrainGlobals.setCompositeMapAmbient(ambient); } //---------------------------------------------------------------------------------------------- @@ -102,6 +95,12 @@ namespace MWRender const int cellX = store->cell->getGridX(); 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 const int numTextures = ESM::Land::LAND_TEXTURE_SIZE/2; @@ -110,7 +109,7 @@ namespace MWRender for ( int y = 0; y < 2; y++ ) { Terrain::ImportData terrainData = - mTerrainGroup->getDefaultImportSettings(); + mTerrainGroup.getDefaultImportSettings(); const int terrainX = cellX * 2 + x; const int terrainY = cellY * 2 + y; @@ -122,42 +121,51 @@ namespace MWRender mLandSize*mLandSize, MEMCATEGORY_GEOMETRY); - //copy the height data row by row - for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ ) + if ( land != NULL ) { - //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); + //copy the height data row by row + for ( int terrainCopyY = 0; terrainCopyY < mLandSize; terrainCopyY++ ) + { + //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); - memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize], - &store->land[1][1]->landData->heights[yOffset + xOffset], - mLandSize*sizeof(float)); + memcpy(&terrainData.inputFloat[terrainCopyY*mLandSize], + &land->landData->heights[yOffset + xOffset], + mLandSize*sizeof(float)); + } + } + else + { + memset(terrainData.inputFloat, 0, mLandSize*mLandSize*sizeof(float)); } std::map indexes; - initTerrainTextures(&terrainData, store, + initTerrainTextures(&terrainData, cellX, cellY, x * numTextures, y * numTextures, numTextures, indexes); - if (mTerrainGroup->getTerrain(terrainX, terrainY) == NULL) + if (mTerrainGroup.getTerrain(terrainX, terrainY) == NULL) { - mTerrainGroup->defineTerrain(terrainX, terrainY, &terrainData); + mTerrainGroup.defineTerrain(terrainX, terrainY, &terrainData); - mTerrainGroup->loadTerrain(terrainX, terrainY, true); + mTerrainGroup.loadTerrain(terrainX, terrainY, true); - Terrain* terrain = mTerrainGroup->getTerrain(terrainX, terrainY); - initTerrainBlendMaps(terrain, store, + Terrain* terrain = mTerrainGroup.getTerrain(terrainX, terrainY); + initTerrainBlendMaps(terrain, + cellX, cellY, x * numTextures, y * numTextures, numTextures, indexes); - if ( store->land[1][1]->landData->usingColours ) + if ( land->landData->usingColours ) { // disable or enable global colour map (depends on available vertex colours) mActiveProfile->setGlobalColourMapEnabled(true); - TexturePtr vertex = getVertexColours(store, + TexturePtr vertex = getVertexColours(land, + cellX, cellY, x*(mLandSize-1), y*(mLandSize-1), mLandSize); @@ -177,7 +185,7 @@ namespace MWRender } } - mTerrainGroup->freeTemporaryResources(); + mTerrainGroup.freeTemporaryResources(); } //---------------------------------------------------------------------------------------------- @@ -188,8 +196,8 @@ namespace MWRender { 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); } } } @@ -197,11 +205,10 @@ namespace MWRender //---------------------------------------------------------------------------------------------- void TerrainManager::initTerrainTextures(Terrain::ImportData* terrainData, - MWWorld::Ptr::CellStore* store, + int cellX, int cellY, int fromX, int fromY, int size, std::map& indexes) { - assert(store != NULL && "store must be a valid pointer"); assert(terrainData != NULL && "Must have valid terrain data"); assert(fromX >= 0 && fromY >= 0 && "Can't get a terrain texture on terrain outside the current cell"); @@ -219,7 +226,7 @@ namespace MWRender { 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 +251,7 @@ namespace MWRender { //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"); std::string texture; @@ -254,7 +261,7 @@ namespace MWRender } 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 texture = texture.substr(0, texture.rfind(".")) + ".dds"; } @@ -280,11 +287,10 @@ namespace MWRender //---------------------------------------------------------------------------------------------- void TerrainManager::initTerrainBlendMaps(Terrain* terrain, - MWWorld::Ptr::CellStore* store, + int cellX, int cellY, int fromX, int fromY, int size, const std::map& indexes) { - assert(store != NULL && "store must be a valid pointer"); assert(terrain != NULL && "Must have valid terrain"); assert(fromX >= 0 && fromY >= 0 && "Can't get a terrain texture on terrain outside the current cell"); @@ -313,7 +319,7 @@ namespace MWRender { 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 //if it is don't bother altering the blend map for it @@ -332,8 +338,10 @@ namespace MWRender float* const pBlend = terrain->getLayerBlendMap(layerIndex) ->getBlendPointer(); - for ( int y = -1; y < splatSize + 1; y++ ){ - for ( int x = -1; x < splatSize + 1; x++ ){ + for ( int y = -1; y < splatSize + 1; y++ ) + { + for ( int x = -1; x < splatSize + 1; x++ ) + { //Note: Y is reversed const int splatY = blendMapSize - 1 - relY * splatSize - y; @@ -373,7 +381,7 @@ namespace MWRender //---------------------------------------------------------------------------------------------- - int TerrainManager::getLtexIndexAt(MWWorld::Ptr::CellStore* store, + int TerrainManager::getLtexIndexAt(int cellX, int cellY, int x, int y) { //check texture index falls within the 9 cell bounds @@ -386,12 +394,6 @@ namespace MWRender y < 2*ESM::Land::LAND_TEXTURE_SIZE && "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 ) { cellX--; @@ -414,22 +416,32 @@ namespace MWRender y -= ESM::Land::LAND_TEXTURE_SIZE; } - return store->land[cellX][cellY] - ->landData - ->textures[y * ESM::Land::LAND_TEXTURE_SIZE + x]; + + 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]; + } + else + { + return 0; + } } //---------------------------------------------------------------------------------------------- - TexturePtr TerrainManager::getVertexColours(MWWorld::Ptr::CellStore* store, - int fromX, int fromY, int size) + TexturePtr TerrainManager::getVertexColours(ESM::Land* land, + int cellX, int cellY, + int fromX, int fromY, int size) { TextureManager* const texMgr = TextureManager::getSingletonPtr(); const std::string colourTextureName = "VtexColours_" + - boost::lexical_cast(store->cell->getGridX()) + + boost::lexical_cast(cellX) + "_" + - boost::lexical_cast(store->cell->getGridY()) + + boost::lexical_cast(cellY) + "_" + boost::lexical_cast(fromX) + "_" + @@ -451,26 +463,42 @@ namespace MWRender const PixelBox& pixelBox = pixelBuffer->getCurrentLock(); uint8* pDest = static_cast(pixelBox.data); - - const char* const colours = store->land[1][1]->landData->colours; - for ( int y = 0; y < size; y++ ) + + if ( land != NULL ) { - for ( int x = 0; x < size; x++ ) + const char* const colours = land->landData->colours; + for ( int y = 0; y < size; y++ ) { - const size_t colourOffset = (y+fromY)*3*65 + (x+fromX)*3; + for ( int x = 0; x < size; x++ ) + { + const size_t colourOffset = (y+fromY)*3*65 + (x+fromX)*3; - assert( colourOffset >= 0 && colourOffset < 65*65*3 && - "Colour offset is out of the expected bounds of record" ); + assert( colourOffset < 65*65*3 && + "Colour offset is out of the expected bounds of record" ); - const unsigned char r = colours[colourOffset + 0]; - const unsigned char g = colours[colourOffset + 1]; - const unsigned char b = colours[colourOffset + 2]; + const unsigned char r = colours[colourOffset + 0]; + const unsigned char g = colours[colourOffset + 1]; + const unsigned char b = colours[colourOffset + 2]; - //as is the case elsewhere we need to flip the y - const size_t imageOffset = (size - 1 - y)*size*4 + x*4; - pDest[imageOffset + 0] = b; - pDest[imageOffset + 1] = g; - pDest[imageOffset + 2] = r; + //as is the case elsewhere we need to flip the y + const size_t imageOffset = (size - 1 - y)*size*4 + x*4; + pDest[imageOffset + 0] = b; + pDest[imageOffset + 1] = g; + 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; + } + } } } diff --git a/apps/openmw/mwrender/terrain.hpp b/apps/openmw/mwrender/terrain.hpp index 397c0c473..29a4ba36b 100644 --- a/apps/openmw/mwrender/terrain.hpp +++ b/apps/openmw/mwrender/terrain.hpp @@ -2,6 +2,7 @@ #define _GAME_RENDER_TERRAIN_H #include +#include #include "terrainmaterial.hpp" #include "../mwworld/ptr.hpp" @@ -23,7 +24,7 @@ namespace MWRender{ */ class TerrainManager{ public: - TerrainManager(Ogre::SceneManager*); + TerrainManager(Ogre::SceneManager* mgr, const MWWorld::Environment& env); virtual ~TerrainManager(); void setDiffuse(const Ogre::ColourValue& diffuse); @@ -32,8 +33,10 @@ namespace MWRender{ void cellAdded(MWWorld::Ptr::CellStore* store); void cellRemoved(MWWorld::Ptr::CellStore* store); private: - Ogre::TerrainGlobalOptions* mTerrainGlobals; - Ogre::TerrainGroup* mTerrainGroup; + Ogre::TerrainGlobalOptions mTerrainGlobals; + Ogre::TerrainGroup mTerrainGroup; + + const MWWorld::Environment& mEnvironment; Ogre::TerrainMaterialGeneratorB::SM2Profile* mActiveProfile; @@ -53,7 +56,8 @@ namespace MWRender{ * layer * * @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 fromY the ltex index in the current cell to start making the texture from * @param size the size (number of splats) to get @@ -61,7 +65,7 @@ namespace MWRender{ * can be used by initTerrainBlendMaps */ void initTerrainTextures(Ogre::Terrain::ImportData* terrainData, - MWWorld::Ptr::CellStore* store, + int cellX, int cellY, int fromX, int fromY, int size, std::map& indexes); @@ -69,14 +73,15 @@ namespace MWRender{ * Creates the blend (splatting maps) for the given terrain from the ltex data. * * @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 fromY the ltex index in the current cell to start making the texture from * @param size the size (number of splats) to get * @param indexes the mapping of ltex to blend map produced by initTerrainTextures */ void initTerrainBlendMaps(Ogre::Terrain* terrain, - MWWorld::Ptr::CellStore* store, + int cellX, int cellY, int fromX, int fromY, int size, const std::map& indexes); @@ -85,22 +90,25 @@ namespace MWRender{ * starts at (0,0). This supports getting values from the surrounding * 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 * 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 * 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 fromY the *vertex* index in the current cell to start making the texture from * @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); }; diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index 4fe6279d3..cd2cf1d91 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -4,6 +4,8 @@ namespace ESM { void Land::load(ESMReader &esm) { + mEsm = &esm; + // Get the grid location esm.getSubNameIs("INTV"); esm.getSubHeaderIs(8); @@ -51,7 +53,7 @@ void Land::load(ESMReader &esm) landData = NULL; } -void Land::loadData(ESMReader &esm) +void Land::loadData() { if (dataLoaded) { @@ -62,17 +64,17 @@ void Land::loadData(ESMReader &esm) if (hasData) { - esm.restoreContext(context); + mEsm->restoreContext(context); //esm.getHNExact(landData->normals, sizeof(VNML), "VNML"); - if (esm.isNextSub("VNML")) + if (mEsm->isNextSub("VNML")) { - esm.skipHSubSize(12675); + mEsm->skipHSubSize(12675); } VHGT rawHeights; - esm.getHNExact(&rawHeights, sizeof(VHGT), "VHGT"); + mEsm->getHNExact(&rawHeights, sizeof(VHGT), "VHGT"); int currentHeightOffset = rawHeights.heightOffset; 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; - esm.getHExact(&landData->colours, 3*LAND_NUM_VERTS); + mEsm->getHExact(&landData->colours, 3*LAND_NUM_VERTS); }else{ landData->usingColours = false; } //TODO fix magic numbers uint16_t vtex[512]; - esm.getHNExact(&vtex, 512, "VTEX"); + mEsm->getHNExact(&vtex, 512, "VTEX"); int readPos = 0; //bit ugly, but it works for ( int y1 = 0; y1 < 4; y1++ ) diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index eeb198e90..5ccd966d9 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -17,6 +17,7 @@ struct Land // File context. This allows the ESM reader to be 'reset' to this // location later when we are ready to load the full data set. + ESMReader* mEsm; ESM_Context context; bool hasData; @@ -70,7 +71,7 @@ struct Land /** * Actually loads data */ - void loadData(ESMReader &esm); + void loadData(); /** * Frees memory allocated for land data diff --git a/components/esm_store/cell_store.hpp b/components/esm_store/cell_store.hpp index b733a7ee8..c0a84c577 100644 --- a/components/esm_store/cell_store.hpp +++ b/components/esm_store/cell_store.hpp @@ -124,9 +124,6 @@ namespace ESMS CellRefList statics; CellRefList weapons; - const Land* land[3][3]; - const LTexList* landTextures; - void load (const ESMStore &store, ESMReader &esm) { if (mState!=State_Loaded) @@ -138,21 +135,6 @@ namespace ESMS 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; } } @@ -198,24 +180,6 @@ namespace ESMS 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 bool forEachImp (Functor& functor, List& list) { diff --git a/components/esm_store/reclists.hpp b/components/esm_store/reclists.hpp index cfbd23d75..16d37bec7 100644 --- a/components/esm_store/reclists.hpp +++ b/components/esm_store/reclists.hpp @@ -201,15 +201,21 @@ namespace ESMS // TODO: For multiple ESM/ESP files we need one list per file. std::vector ltex; - int count; - LTexList() : count(0) + LTexList() { // More than enough to hold Morrowind.esm. 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& identifier) const {} @@ -233,12 +239,18 @@ namespace ESMS */ struct LandList : RecList { - virtual ~LandList() {} + virtual ~LandList() + { + for ( LandMap::iterator itr = lands.begin(); itr != lands.end(); ++itr ) + { + delete itr->second; + } + } // Map containing all landscapes - typedef std::map LandsCol; - typedef std::map Lands; - Lands lands; + typedef std::pair LandCoord; + typedef std::map LandMap; + LandMap lands; int count; LandList() : count(0) {} @@ -249,15 +261,13 @@ namespace ESMS // Find land for the given coordinates. Return null if no data. Land *search(int x, int y) const { - Lands::const_iterator it = lands.find(x); - if(it==lands.end()) + LandMap::const_iterator itr = lands.find(std::make_pair(x, y)); + if ( itr == lands.end() ) + { return NULL; + } - LandsCol::const_iterator it2 = it->second.find(y); - if(it2 == it->second.end()) - return NULL; - - return it2->second; + return itr->second; } void load(ESMReader &esm, const std::string &id) @@ -266,11 +276,11 @@ namespace ESMS // Create the structure and load it. This actually skips the // landscape data and remembers the file position for later. - Land *land = new Land; + Land *land = new Land(); land->load(esm); // Store the structure - lands[land->X][land->Y] = land; + lands[std::make_pair(land->X, land->Y)] = land; } };