From ad8cfde4e03505c72114ad71d1f51a19041289ff Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Fri, 26 May 2023 02:14:56 +0200 Subject: [PATCH] ESM::LandData no longer a virtual interface instead it is constructed from ESM::Land or ESM4::Land --- apps/opencs/view/render/terrainstorage.cpp | 41 +++++++------ apps/opencs/view/render/terrainstorage.hpp | 23 ++++---- apps/openmw/mwworld/scene.cpp | 1 + components/esm/esmterrain.cpp | 67 ++++++++++++++++++++++ components/esm/esmterrain.hpp | 37 +++++++++--- components/esm3/loadland.hpp | 14 +---- components/esm3terrain/storage.cpp | 8 +-- components/esm3terrain/storage.hpp | 20 ++++--- components/esm4/loadland.cpp | 47 --------------- components/esm4/loadland.hpp | 34 +---------- 10 files changed, 146 insertions(+), 146 deletions(-) create mode 100644 components/esm/esmterrain.cpp diff --git a/apps/opencs/view/render/terrainstorage.cpp b/apps/opencs/view/render/terrainstorage.cpp index a9c1c5e5cf..725b663649 100644 --- a/apps/opencs/view/render/terrainstorage.cpp +++ b/apps/opencs/view/render/terrainstorage.cpp @@ -72,8 +72,8 @@ namespace CSVRender if (index == -1) // no land! return height; - const ESM::LandData* landData = mData.getLand().getRecord(index).get().getLandData(ESM::Land::DATA_VHGT); - height = landData->getHeights()[inCellY * ESM::Land::LAND_SIZE + inCellX]; + const ESM::Land::LandData* landData = mData.getLand().getRecord(index).get().getLandData(ESM::Land::DATA_VHGT); + height = landData->mHeights[inCellY * ESM::Land::LAND_SIZE + inCellX]; return mAlteredHeight[inCellY * ESM::Land::LAND_SIZE + inCellX] + height; } @@ -88,65 +88,65 @@ namespace CSVRender throw std::runtime_error("getBounds not implemented"); } - int TerrainStorage::getThisHeight(int col, int row, const ESM::Land::LandData* heightData) const + int TerrainStorage::getThisHeight(int col, int row, std::span heightData) const { - return heightData->mHeights[col * ESM::Land::LAND_SIZE + row] + return heightData[col * ESM::Land::LAND_SIZE + row] + mAlteredHeight[static_cast(col * ESM::Land::LAND_SIZE + row)]; } - int TerrainStorage::getLeftHeight(int col, int row, const ESM::Land::LandData* heightData) const + int TerrainStorage::getLeftHeight(int col, int row, std::span heightData) const { - return heightData->mHeights[(col)*ESM::Land::LAND_SIZE + row - 1] + return heightData[(col)*ESM::Land::LAND_SIZE + row - 1] + mAlteredHeight[static_cast((col)*ESM::Land::LAND_SIZE + row - 1)]; } - int TerrainStorage::getRightHeight(int col, int row, const ESM::Land::LandData* heightData) const + int TerrainStorage::getRightHeight(int col, int row, std::span heightData) const { - return heightData->mHeights[col * ESM::Land::LAND_SIZE + row + 1] + return heightData[col * ESM::Land::LAND_SIZE + row + 1] + mAlteredHeight[static_cast(col * ESM::Land::LAND_SIZE + row + 1)]; } - int TerrainStorage::getUpHeight(int col, int row, const ESM::Land::LandData* heightData) const + int TerrainStorage::getUpHeight(int col, int row, std::span heightData) const { - return heightData->mHeights[(col - 1) * ESM::Land::LAND_SIZE + row] + return heightData[(col - 1) * ESM::Land::LAND_SIZE + row] + mAlteredHeight[static_cast((col - 1) * ESM::Land::LAND_SIZE + row)]; } - int TerrainStorage::getDownHeight(int col, int row, const ESM::Land::LandData* heightData) const + int TerrainStorage::getDownHeight(int col, int row, std::span heightData) const { - return heightData->mHeights[(col + 1) * ESM::Land::LAND_SIZE + row] + return heightData[(col + 1) * ESM::Land::LAND_SIZE + row] + mAlteredHeight[static_cast((col + 1) * ESM::Land::LAND_SIZE + row)]; } - int TerrainStorage::getHeightDifferenceToLeft(int col, int row, const ESM::Land::LandData* heightData) const + int TerrainStorage::getHeightDifferenceToLeft(int col, int row, std::span heightData) const { return abs(getThisHeight(col, row, heightData) - getLeftHeight(col, row, heightData)); } - int TerrainStorage::getHeightDifferenceToRight(int col, int row, const ESM::Land::LandData* heightData) const + int TerrainStorage::getHeightDifferenceToRight(int col, int row, std::span heightData) const { return abs(getThisHeight(col, row, heightData) - getRightHeight(col, row, heightData)); } - int TerrainStorage::getHeightDifferenceToUp(int col, int row, const ESM::Land::LandData* heightData) const + int TerrainStorage::getHeightDifferenceToUp(int col, int row, std::span heightData) const { return abs(getThisHeight(col, row, heightData) - getUpHeight(col, row, heightData)); } - int TerrainStorage::getHeightDifferenceToDown(int col, int row, const ESM::Land::LandData* heightData) const + int TerrainStorage::getHeightDifferenceToDown(int col, int row, std::span heightData) const { return abs(getThisHeight(col, row, heightData) - getDownHeight(col, row, heightData)); } bool TerrainStorage::leftOrUpIsOverTheLimit( - int col, int row, int heightWarningLimit, const ESM::Land::LandData* heightData) const + int col, int row, int heightWarningLimit, std::span heightData) const { return getHeightDifferenceToLeft(col, row, heightData) >= heightWarningLimit || getHeightDifferenceToUp(col, row, heightData) >= heightWarningLimit; } bool TerrainStorage::rightOrDownIsOverTheLimit( - int col, int row, int heightWarningLimit, const ESM::Land::LandData* heightData) const + int col, int row, int heightWarningLimit, std::span heightData) const { return getHeightDifferenceToRight(col, row, heightData) >= heightWarningLimit || getHeightDifferenceToDown(col, row, heightData) >= heightWarningLimit; @@ -155,11 +155,10 @@ namespace CSVRender void TerrainStorage::adjustColor(int col, int row, const ESM::LandData* heightData, osg::Vec4ub& color) const { // Highlight broken height changes - const ESM::Land::LandData* heightDataEsm3 = dynamic_cast(heightData); int heightWarningLimit = 1024; - if (((col > 0 && row > 0) && leftOrUpIsOverTheLimit(col, row, heightWarningLimit, heightDataEsm3)) + if (((col > 0 && row > 0) && leftOrUpIsOverTheLimit(col, row, heightWarningLimit, heightData->getHeights())) || ((col < ESM::Land::LAND_SIZE - 1 && row < ESM::Land::LAND_SIZE - 1) - && rightOrDownIsOverTheLimit(col, row, heightWarningLimit, heightDataEsm3))) + && rightOrDownIsOverTheLimit(col, row, heightWarningLimit, heightData->getHeights()))) { color.r() = 255; color.g() = 0; diff --git a/apps/opencs/view/render/terrainstorage.hpp b/apps/opencs/view/render/terrainstorage.hpp index bce5d94156..907e63a8eb 100644 --- a/apps/opencs/view/render/terrainstorage.hpp +++ b/apps/opencs/view/render/terrainstorage.hpp @@ -42,19 +42,18 @@ namespace CSVRender void getBounds(float& minX, float& maxX, float& minY, float& maxY, ESM::RefId worldspace) override; - int getThisHeight(int col, int row, const ESM::Land::LandData* heightData) const; - int getLeftHeight(int col, int row, const ESM::Land::LandData* heightData) const; - int getRightHeight(int col, int row, const ESM::Land::LandData* heightData) const; - int getUpHeight(int col, int row, const ESM::Land::LandData* heightData) const; - int getDownHeight(int col, int row, const ESM::Land::LandData* heightData) const; - int getHeightDifferenceToLeft(int col, int row, const ESM::Land::LandData* heightData) const; - int getHeightDifferenceToRight(int col, int row, const ESM::Land::LandData* heightData) const; - int getHeightDifferenceToUp(int col, int row, const ESM::Land::LandData* heightData) const; - int getHeightDifferenceToDown(int col, int row, const ESM::Land::LandData* heightData) const; - bool leftOrUpIsOverTheLimit( - int col, int row, int heightWarningLimit, const ESM::Land::LandData* heightData) const; + int getThisHeight(int col, int row, std::span heightData) const; + int getLeftHeight(int col, int row, std::span heightData) const; + int getRightHeight(int col, int row, std::span heightData) const; + int getUpHeight(int col, int row, std::span heightData) const; + int getDownHeight(int col, int row, std::span heightData) const; + int getHeightDifferenceToLeft(int col, int row, std::span heightData) const; + int getHeightDifferenceToRight(int col, int row, std::span heightData) const; + int getHeightDifferenceToUp(int col, int row, std::span heightData) const; + int getHeightDifferenceToDown(int col, int row, std::span heightData) const; + bool leftOrUpIsOverTheLimit(int col, int row, int heightWarningLimit, std::span heightData) const; bool rightOrDownIsOverTheLimit( - int col, int row, int heightWarningLimit, const ESM::Land::LandData* heightData) const; + int col, int row, int heightWarningLimit, std::span heightData) const; void adjustColor(int col, int row, const ESM::LandData* heightData, osg::Vec4ub& color) const override; float getAlteredHeight(int col, int row) const override; diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 3c172d3d4f..f67b570b02 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/components/esm/esmterrain.cpp b/components/esm/esmterrain.cpp new file mode 100644 index 0000000000..8ed0de74e9 --- /dev/null +++ b/components/esm/esmterrain.cpp @@ -0,0 +1,67 @@ +#include + +#include "esmterrain.hpp" + +ESM::LandData::LandData(const ESM::Land& land, int loadFlags) + : mLoadFlags(loadFlags) + , mSize(Constants::CellSizeInUnits) + , mLandSize(ESM::Land::LAND_SIZE) +{ + ESM::Land::LandData data; + land.loadData(loadFlags, &data); + mLoadFlags = data.mDataLoaded; + std::span heights(data.mHeights); + mHeights = std::vector(heights.begin(), heights.end()); + + std::span normals(data.mNormals); + mNormals = std::vector(normals.begin(), normals.end()); + + std::span colors(data.mColours); + mColors = std::vector(colors.begin(), colors.end()); + + std::span textures(data.mTextures); + mTextures = std::vector(textures.begin(), textures.end()); + + mMinHeight = data.mMinHeight; + mMaxHeight = data.mMaxHeight; +} + +ESM::LandData::LandData(const ESM4::Land& land, int loadFlags) + : mLoadFlags(loadFlags) + , mSize(Constants::ESM4CellSizeInUnits) + , mLandSize(ESM4::Land::VERTS_PER_SIDE) +{ + + mMinHeight = std::numeric_limits::max(); + mMaxHeight = std::numeric_limits::lowest(); + mHeights.resize(ESM4::Land::LAND_NUM_VERTS); + mTextures.resize(ESM::Land::LAND_NUM_TEXTURES); + std::fill(mTextures.begin(), mTextures.end(), 0); + + float row_offset = land.mHeightMap.heightOffset; + for (int y = 0; y < mLandSize; y++) + { + row_offset += land.mHeightMap.gradientData[y * mLandSize]; + + const float heightY = row_offset * ESM4::Land::HEIGHT_SCALE; + mHeights[y * mLandSize] = heightY; + mMinHeight = std::min(mMinHeight, heightY); + mMaxHeight = std::max(mMaxHeight, heightY); + + float colOffset = row_offset; + for (int x = 1; x < mLandSize; x++) + { + colOffset += land.mHeightMap.gradientData[y * mLandSize + x]; + const float heightX = colOffset * ESM4::Land::HEIGHT_SCALE; + mMinHeight = std::min(mMinHeight, heightX); + mMaxHeight = std::max(mMaxHeight, heightX); + mHeights[x + y * mLandSize] = heightX; + } + } + + std::span normals(land.mVertNorm); + mNormals = std::vector(normals.begin(), normals.end()); + + std::span colors(land.mVertColr); + mColors = std::vector(colors.begin(), colors.end()); +} diff --git a/components/esm/esmterrain.hpp b/components/esm/esmterrain.hpp index 593d8f6e28..b8303008c2 100644 --- a/components/esm/esmterrain.hpp +++ b/components/esm/esmterrain.hpp @@ -2,6 +2,10 @@ #define COMPONENTS_ESM_ESMTERRAIN #include +#include + +#include +#include namespace ESM { @@ -9,18 +13,33 @@ namespace ESM { public: - virtual ~LandData() = default; + ~LandData() = default; + LandData() = default; + LandData(const ESM::Land& Land, int loadFLags); + LandData(const ESM4::Land& Land, int loadFLags); typedef signed char VNML; - virtual std::span getHeights() const = 0; - virtual std::span getNormals() const = 0; - virtual std::span getColors() const = 0; - virtual std::span getTextures() const = 0; - virtual float getSize() const = 0; - virtual float getMinHeight() const = 0; - virtual float getMaxHeight() const = 0; - virtual int getLandSize() const = 0; + std::span getHeights() const { return mHeights; } + std::span getNormals() const { return mNormals; } + std::span getColors() const { return mColors; } + std::span getTextures() const { return mTextures; } + float getSize() const { return mSize; } + float getMinHeight() const { return mMinHeight; } + float getMaxHeight() const { return mMaxHeight; } + int getLandSize() const { return mLandSize; } + + int mLoadFlags; + + private: + float mMinHeight = 0.f; + float mMaxHeight = 0.f; + float mSize = 0.f; + int mLandSize = 0; + std::vector mHeights; + std::vector mNormals; + std::vector mColors; + std::vector mTextures; }; } diff --git a/components/esm3/loadland.hpp b/components/esm3/loadland.hpp index 9cebc935d6..83ac849c7e 100644 --- a/components/esm3/loadland.hpp +++ b/components/esm3/loadland.hpp @@ -7,7 +7,6 @@ #include "components/esm/defs.hpp" #include "components/esm/esmcommon.hpp" -#include "components/esm/esmterrain.hpp" namespace ESM { @@ -88,8 +87,10 @@ namespace ESM }; #pragma pack(pop) - struct LandData : public ESM::LandData + struct LandData { + typedef signed char VNML; + LandData() : mHeightOffset(0) , mMinHeight(0) @@ -123,15 +124,6 @@ namespace ESM uint8_t mUnk2; int mDataLoaded; - - std::span getHeights() const override { return mHeights; } - std::span getNormals() const override { return mNormals; } - std::span getColors() const override { return mColours; } - std::span getTextures() const override { return mTextures; } - float getSize() const override { return REAL_SIZE; } - float getMinHeight() const override { return mMinHeight; } - float getMaxHeight() const override { return mMaxHeight; } - int getLandSize() const override { return LAND_SIZE; } }; // low-LOD heightmap (used for rendering the global map) diff --git a/components/esm3terrain/storage.cpp b/components/esm3terrain/storage.cpp index 474d171426..feaacfc21b 100644 --- a/components/esm3terrain/storage.cpp +++ b/components/esm3terrain/storage.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -30,18 +31,15 @@ namespace ESMTerrain LandObject::LandObject(const ESM4::Land* land, int loadFlags) : mLand(nullptr) , mLoadFlags(0) + , mData(*land, loadFlags) { - mData = std::make_unique(*land); } LandObject::LandObject(const ESM::Land* land, int loadFlags) : mLand(land) , mLoadFlags(loadFlags) - , mData(nullptr) + , mData(*land, loadFlags) { - std::unique_ptr esm3LandData = std::make_unique(); - mLand->loadData(mLoadFlags, esm3LandData.get()); - mData = std::move(esm3LandData); } LandObject::LandObject(const LandObject& copy, const osg::CopyOp& copyop) diff --git a/components/esm3terrain/storage.hpp b/components/esm3terrain/storage.hpp index 8876ae9755..736bf065aa 100644 --- a/components/esm3terrain/storage.hpp +++ b/components/esm3terrain/storage.hpp @@ -6,6 +6,7 @@ #include +#include #include #include #include @@ -15,6 +16,11 @@ namespace ESM4 struct Land; } +namespace ESM +{ + class LandData; +} + namespace VFS { class Manager; @@ -41,22 +47,20 @@ namespace ESMTerrain inline const ESM::LandData* getData(int flags) const { - if (!mData) + if ((mData.mLoadFlags & flags) != flags) return nullptr; - ESM::Land::LandData* esm3Land = dynamic_cast(mData.get()); - if (esm3Land && ((esm3Land->mDataLoaded & flags) != flags)) - return nullptr; - return mData.get(); + + return &mData; } inline int getPlugin() const { return mLand->getPlugin(); } - inline int getLandSize() const { return mData->getLandSize(); } - inline int getRealSize() const { return mData->getSize(); } + inline int getLandSize() const { return mData.getLandSize(); } + inline int getRealSize() const { return mData.getSize(); } private: const ESM::Land* mLand; int mLoadFlags; - std::unique_ptr mData; + ESM::LandData mData; }; /// @brief Feeds data from ESM terrain records (ESM::Land, ESM::LandTexture) diff --git a/components/esm4/loadland.cpp b/components/esm4/loadland.cpp index d7acc47ec0..086a15a660 100644 --- a/components/esm4/loadland.cpp +++ b/components/esm4/loadland.cpp @@ -233,53 +233,6 @@ void ESM4::Land::load(ESM4::Reader& reader) // at least one of the quadrants do not have a base texture, return without setting the flag if (!missing) mDataTypes |= LAND_VTEX; - - mMinHeight = std::numeric_limits::max(); - mMaxHeight = std::numeric_limits::lowest(); - - float row_offset = mHeightMap.heightOffset; - for (int y = 0; y < VERTS_PER_SIDE; y++) - { - row_offset += mHeightMap.gradientData[y * VERTS_PER_SIDE]; - - const float heightY = row_offset * HEIGHT_SCALE; - mHeights[y * VERTS_PER_SIDE] = heightY; - mMinHeight = std::min(mMinHeight, heightY); - mMaxHeight = std::max(mMaxHeight, heightY); - - float colOffset = row_offset; - for (int x = 1; x < VERTS_PER_SIDE; x++) - { - colOffset += mHeightMap.gradientData[y * VERTS_PER_SIDE + x]; - const float heightX = colOffset * HEIGHT_SCALE; - mMinHeight = std::min(mMinHeight, heightX); - mMaxHeight = std::max(mMaxHeight, heightX); - mHeights[x + y * VERTS_PER_SIDE] = heightX; - } - } -} - -ESM4::Land::Land(const Land& Other) -{ - mId = Other.mId; - mCell = Other.mCell; - for (int i = 0; i < VERTS_PER_SIDE * VERTS_PER_SIDE; i++) - { - mHeights[i] = Other.mHeights[i]; - } - for (int i = 0; i < VERTS_PER_SIDE * VERTS_PER_SIDE * 3; i++) - { - mVertNorm[i] = Other.mVertNorm[i]; - mVertColr[i] = Other.mVertColr[i]; - } - mMinHeight = Other.mMinHeight; - mMaxHeight = Other.mMaxHeight; -} - -std::span ESM4::Land::getTextures() const -{ - static uint16_t textureArray[16 * 16] = {}; - return textureArray; } // void ESM4::Land::save(ESM4::Writer& writer) const diff --git a/components/esm4/loadland.hpp b/components/esm4/loadland.hpp index 7b26f95bc5..de844394ad 100644 --- a/components/esm4/loadland.hpp +++ b/components/esm4/loadland.hpp @@ -34,14 +34,13 @@ #include "formid.hpp" #include -#include #include namespace ESM4 { class Reader; - struct Land : public ESM::LandData + struct Land { enum { @@ -131,41 +130,10 @@ namespace ESM4 ESM::RefId mCell; void load(Reader& reader); Land() = default; - Land(const Land& Other); // void save(Writer& writer) const; // void blank(); static constexpr ESM::RecNameInts sRecordId = ESM::REC_LAND4; - - std::span getHeights() const override - { - return mHeights; - } - std::span getNormals() const override - { - return mVertNorm; - } - std::span getColors() const override - { - return mVertColr; - } - std::span getTextures() const override; - float getSize() const override - { - return REAL_SIZE; - } - float getMinHeight() const override - { - return mMinHeight; - } - float getMaxHeight() const override - { - return mMaxHeight; - } - int getLandSize() const override - { - return VERTS_PER_SIDE; - } }; }