From 2d5ddd104bdea09687b6e0ff91492de544fa05e4 Mon Sep 17 00:00:00 2001 From: greye Date: Fri, 21 Sep 2012 12:12:16 +0400 Subject: [PATCH] Land::loadData rework --- apps/openmw/mwrender/terrain.cpp | 9 ++- components/esm/loadland.cpp | 132 +++++++++++++++++-------------- components/esm/loadland.hpp | 15 +++- 3 files changed, 90 insertions(+), 66 deletions(-) diff --git a/apps/openmw/mwrender/terrain.cpp b/apps/openmw/mwrender/terrain.cpp index 35e2344e91..114a9bc375 100644 --- a/apps/openmw/mwrender/terrain.cpp +++ b/apps/openmw/mwrender/terrain.cpp @@ -99,9 +99,10 @@ namespace MWRender if (land == NULL) // no land data means we're not going to create any terrain. return; - if (!land->mDataLoaded) + int dataRequired = ESM::Land::DATA_VHGT | ESM::Land::DATA_VCLR; + if (!land->isDataLoaded(dataRequired)) { - land->loadData(); + land->loadData(dataRequired); } //split the cell terrain into four segments @@ -413,9 +414,9 @@ namespace MWRender ESM::Land* land = MWBase::Environment::get().getWorld()->getStore().lands.search(cellX, cellY); if ( land != NULL ) { - if (!land->mDataLoaded) + if (!land->isDataLoaded(ESM::Land::DATA_VTEX)) { - land->loadData(); + land->loadData(ESM::Land::DATA_VTEX); } return land->mLandData diff --git a/components/esm/loadland.cpp b/components/esm/loadland.cpp index 47f2382422..0107e80efa 100644 --- a/components/esm/loadland.cpp +++ b/components/esm/loadland.cpp @@ -12,7 +12,7 @@ void Land::LandData::save(ESMWriter &esm) esm.writeHNT("VNML", mNormals, sizeof(VNML)); } if (mDataTypes & Land::DATA_VHGT) { - VHGT offsets; + static VHGT offsets; offsets.mHeightOffset = mHeights[0] / HEIGHT_SCALE; offsets.mUnk1 = mUnk1; offsets.mUnk2 = mUnk2; @@ -124,9 +124,9 @@ void Land::load(ESMReader &esm) // We need all three of VNML, VHGT and VTEX in order to use the // landscape. (Though Morrowind seems to accept terrain without VTEX/VCLR entries) - mHasData = mDataTypes & (DATA_VNML|DATA_VHGT|DATA_WNAM|DATA_VTEX|DATA_VCLR); + mHasData = mDataTypes & (DATA_VNML|DATA_VHGT|DATA_WNAM); - mDataLoaded = false; + mDataLoaded = 0; mLandData = NULL; } @@ -141,10 +141,10 @@ void Land::save(ESMWriter &esm) // TODO: Land! bool wasLoaded = mDataLoaded; - if (mHasData) - loadData(); // I think it might be a good idea to have - // the data loaded before trying to save it - + if (mDataTypes) { + // Try to load all available data before saving + loadData(mDataTypes); + } if (mDataLoaded) mLandData->save(esm); @@ -152,73 +152,71 @@ void Land::save(ESMWriter &esm) unloadData(); // Don't need to keep the data loaded if it wasn't already } -void Land::loadData() +/// \todo remove memory allocation when only defaults needed +void Land::loadData(int flags) { - if (mDataLoaded) - { + // Try to load only available data + int actual = flags & mDataTypes; + // Return if all required data is loaded + if (flags == 0 || (actual != 0 && (mDataLoaded & actual) == actual)) { return; } + // Create storage if nothing is loaded + if (mLandData == NULL) { + mLandData = new LandData; + mLandData->mDataTypes = mDataTypes; + } + mEsm->restoreContext(mContext); - mLandData = new LandData; - - if (mHasData) - { - mEsm->restoreContext(mContext); - - memset(mLandData->mNormals, 0, LAND_NUM_VERTS * 3); + memset(mLandData->mNormals, 0, LAND_NUM_VERTS * 3); - if (mEsm->isNextSub("VNML")) { - mEsm->getHExact(mLandData->mNormals, sizeof(VNML)); - } + if (mEsm->isNextSub("VNML")) { + condLoad(actual, DATA_VNML, mLandData->mNormals, sizeof(VNML)); + } - if (mEsm->isNextSub("VHGT")) { - VHGT rawHeights; + if (mEsm->isNextSub("VHGT")) { + static VHGT vhgt; + if (condLoad(actual, DATA_VHGT, &vhgt, sizeof(vhgt))) { + float rowOffset = vhgt.mHeightOffset; + for (int y = 0; y < LAND_SIZE; y++) { + rowOffset += vhgt.mHeightData[y * LAND_SIZE]; - mEsm->getHExact(&rawHeights, sizeof(VHGT)); - float currentHeightOffset = rawHeights.mHeightOffset; - for (int y = 0; y < LAND_SIZE; y++) - { - currentHeightOffset += rawHeights.mHeightData[y * LAND_SIZE]; - mLandData->mHeights[y * LAND_SIZE] = currentHeightOffset * HEIGHT_SCALE; + mLandData->mHeights[y * LAND_SIZE] = rowOffset * HEIGHT_SCALE; - float tempOffset = currentHeightOffset; - for (int x = 1; x < LAND_SIZE; x++) - { - tempOffset += rawHeights.mHeightData[y * LAND_SIZE + x]; - mLandData->mHeights[x + y * LAND_SIZE] = tempOffset * HEIGHT_SCALE; + float colOffset = rowOffset; + for (int x = 1; x < LAND_SIZE; x++) { + colOffset += vhgt.mHeightData[y * LAND_SIZE + x]; + mLandData->mHeights[x + y * LAND_SIZE] = colOffset * HEIGHT_SCALE; } } - mLandData->mUnk1 = rawHeights.mUnk1; - mLandData->mUnk2 = rawHeights.mUnk2; + mLandData->mUnk1 = vhgt.mUnk1; + mLandData->mUnk2 = vhgt.mUnk2; } - - if (mEsm->isNextSub("WNAM")) { - mEsm->getHExact(mLandData->mWnam, 81); - } - if (mEsm->isNextSub("VCLR")) { - mLandData->mUsingColours = true; - mEsm->getHExact(&mLandData->mColours, 3*LAND_NUM_VERTS); - } else { - mLandData->mUsingColours = false; - } - if (mEsm->isNextSub("VTEX")) { - static uint16_t vtex[LAND_NUM_TEXTURES]; - mEsm->getHExact(&vtex, sizeof(vtex)); - LandData::transposeTextureData(vtex, mLandData->mTextures); - } - } - else - { - mLandData->mUsingColours = false; - memset(mLandData->mTextures, 0, sizeof(mLandData->mTextures)); - for (int i = 0; i < LAND_NUM_VERTS; i++) - { + } else if ((flags & DATA_VHGT) && (mDataLoaded & DATA_VHGT) == 0) { + for (int i = 0; i < LAND_NUM_VERTS; ++i) { mLandData->mHeights[i] = -256.0f * HEIGHT_SCALE; } + mDataLoaded |= DATA_VHGT; } - mLandData->mDataTypes = mDataTypes; - mDataLoaded = true; + if (mEsm->isNextSub("WNAM")) { + condLoad(actual, DATA_WNAM, mLandData->mWnam, 81); + } + if (mEsm->isNextSub("VCLR")) { + mLandData->mUsingColours = true; + condLoad(actual, DATA_VCLR, mLandData->mColours, 3 * LAND_NUM_VERTS); + } else { + mLandData->mUsingColours = false; + } + if (mEsm->isNextSub("VTEX")) { + static uint16_t vtex[LAND_NUM_TEXTURES]; + if (condLoad(actual, DATA_VTEX, vtex, sizeof(vtex))) { + LandData::transposeTextureData(vtex, mLandData->mTextures); + } + } else if ((flags & DATA_VTEX) && (mDataLoaded & DATA_VTEX) == 0) { + memset(mLandData->mTextures, 0, sizeof(mLandData->mTextures)); + mDataLoaded |= DATA_VTEX; + } } void Land::unloadData() @@ -227,8 +225,22 @@ void Land::unloadData() { delete mLandData; mLandData = NULL; - mDataLoaded = false; + mDataLoaded = 0; } } +bool Land::condLoad(int flags, int dataFlag, void *ptr, unsigned int size) +{ + if ((mDataLoaded & dataFlag) != 0) { + return false; + } + if (flags & dataFlag) { + mEsm->getHExact(ptr, size); + mDataLoaded |= dataFlag; + return true; + } + mEsm->skipHSubSize(size); + return false; +} + } diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 830f74c717..46534c826d 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -28,7 +28,7 @@ struct Land : public Record bool mHasData; int mDataTypes; - bool mDataLoaded; + int mDataLoaded; enum { @@ -97,16 +97,27 @@ struct Land : public Record /** * Actually loads data */ - void loadData(); + void loadData(int flags); /** * Frees memory allocated for land data */ void unloadData(); + /// Check if given data type is loaded + /// \todo reimplement this + bool isDataLoaded(int flags) { + return (mDataLoaded & flags) == flags; + } + private: Land(const Land& land); Land& operator=(const Land& land); + + /// Loads data and marks it as loaded + /// \return true if data is actually loaded from file, false otherwise + /// including the case when data is already loaded + bool condLoad(int flags, int dataFlag, void *ptr, unsigned int size); }; }