From fffcf52316472ae4a52fdab309a26c9ee3731706 Mon Sep 17 00:00:00 2001 From: "florent.teppe" Date: Mon, 15 May 2023 00:34:17 +0200 Subject: [PATCH] land manager cache's key is an ExteriorCellLocation ESM4::Land is now a ESM::LandData --- apps/openmw/mwrender/landmanager.cpp | 10 ++++------ apps/openmw/mwrender/landmanager.hpp | 2 +- components/esm/esmterrain.hpp | 2 ++ components/esm/util.hpp | 6 ++++++ components/esm3terrain/storage.cpp | 17 ++++++++++++++--- components/esm3terrain/storage.hpp | 11 ++++++++--- components/esm4/loadland.cpp | 20 +++++++++++++++++++- components/esm4/loadland.hpp | 17 +++++++++++++++-- 8 files changed, 69 insertions(+), 16 deletions(-) diff --git a/apps/openmw/mwrender/landmanager.cpp b/apps/openmw/mwrender/landmanager.cpp index e7a647f348..5cd72f716c 100644 --- a/apps/openmw/mwrender/landmanager.cpp +++ b/apps/openmw/mwrender/landmanager.cpp @@ -12,7 +12,7 @@ namespace MWRender { LandManager::LandManager(int loadFlags) - : GenericResourceManager>(nullptr) + : GenericResourceManager(nullptr) , mLoadFlags(loadFlags) { mCache = new CacheType; @@ -22,9 +22,7 @@ namespace MWRender { if (ESM::isEsm4Ext(cellIndex.mWorldspace)) return osg::ref_ptr(nullptr); - int x = cellIndex.mX; - int y = cellIndex.mY; - osg::ref_ptr obj = mCache->getRefFromObjectCache(std::make_pair(x, y)); + osg::ref_ptr obj = mCache->getRefFromObjectCache(cellIndex); if (obj) return static_cast(obj.get()); else @@ -32,11 +30,11 @@ namespace MWRender const auto world = MWBase::Environment::get().getWorld(); if (!world) return nullptr; - const ESM::Land* land = world->getStore().get().search(x, y); + const ESM::Land* land = world->getStore().get().search(cellIndex.mX, cellIndex.mY); if (!land) return nullptr; osg::ref_ptr landObj(new ESMTerrain::LandObject(land, mLoadFlags)); - mCache->addEntryToObjectCache(std::make_pair(x, y), landObj.get()); + mCache->addEntryToObjectCache(cellIndex, landObj.get()); return landObj; } } diff --git a/apps/openmw/mwrender/landmanager.hpp b/apps/openmw/mwrender/landmanager.hpp index 1a95038eea..d9c36ea5d9 100644 --- a/apps/openmw/mwrender/landmanager.hpp +++ b/apps/openmw/mwrender/landmanager.hpp @@ -15,7 +15,7 @@ namespace ESM namespace MWRender { - class LandManager : public Resource::GenericResourceManager> + class LandManager : public Resource::GenericResourceManager { public: LandManager(int loadFlags); diff --git a/components/esm/esmterrain.hpp b/components/esm/esmterrain.hpp index 90c4fae122..593d8f6e28 100644 --- a/components/esm/esmterrain.hpp +++ b/components/esm/esmterrain.hpp @@ -9,6 +9,8 @@ namespace ESM { public: + virtual ~LandData() = default; + typedef signed char VNML; virtual std::span getHeights() const = 0; diff --git a/components/esm/util.hpp b/components/esm/util.hpp index ac687fea4b..1bc1119e84 100644 --- a/components/esm/util.hpp +++ b/components/esm/util.hpp @@ -53,6 +53,12 @@ namespace ESM { int mX, mY; ESM::RefId mWorldspace; + ExteriorCellLocation() + : mX(0) + , mY(0) + , mWorldspace(ESM::Cell::sDefaultWorldspaceId) + { + } ExteriorCellLocation(int x, int y, ESM::RefId worldspace) : mX(x) diff --git a/components/esm3terrain/storage.cpp b/components/esm3terrain/storage.cpp index 6fb0a29b15..5a1324dfe4 100644 --- a/components/esm3terrain/storage.cpp +++ b/components/esm3terrain/storage.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -26,11 +27,21 @@ namespace ESMTerrain { } + LandObject::LandObject(const ESM4::Land* land, int loadFlags) + : mLand(nullptr) + , mLoadFlags(0) + { + mData = std::make_unique(*land); + } + LandObject::LandObject(const ESM::Land* land, int loadFlags) : mLand(land) , mLoadFlags(loadFlags) + , mData() { - mLand->loadData(mLoadFlags, &mData); + auto esm3LandData = new ESM::Land::LandData; + mData.reset(esm3LandData); + mLand->loadData(mLoadFlags, esm3LandData); } LandObject::LandObject(const LandObject& copy, const osg::CopyOp& copyop) @@ -218,8 +229,8 @@ namespace ESMTerrain const ESM::LandData* heightData = nullptr; const ESM::LandData* normalData = nullptr; const ESM::LandData* colourData = nullptr; - const int LandSize = ESM::Land::LAND_SIZE; - const int LandSizeInUnits = Constants::CellSizeInUnits; + const int LandSize = land ? land->getLandSize() : ESM::Land::LAND_SIZE; + const int LandSizeInUnits = land ? land->getRealSize() : Constants::CellSizeInUnits; if (land) { heightData = land->getData(ESM::Land::DATA_VHGT); diff --git a/components/esm3terrain/storage.hpp b/components/esm3terrain/storage.hpp index 7f7f25c5d6..a81465a56d 100644 --- a/components/esm3terrain/storage.hpp +++ b/components/esm3terrain/storage.hpp @@ -32,6 +32,8 @@ namespace ESMTerrain public: LandObject(); LandObject(const ESM::Land* land, int loadFlags); + LandObject(const ESM4::Land* land, int loadFlags); + LandObject(const LandObject& copy, const osg::CopyOp& copyop); virtual ~LandObject(); @@ -39,17 +41,20 @@ namespace ESMTerrain inline const ESM::LandData* getData(int flags) const { - if ((mData.mDataLoaded & flags) != flags) + ESM::Land::LandData* esm3Land = dynamic_cast(mData.get()); + if (esm3Land && ((esm3Land->mDataLoaded & flags) != flags)) return nullptr; - return &mData; + return mData.get(); } inline int getPlugin() const { return mLand->getPlugin(); } + inline int getLandSize() const { return mData->getLandSize(); } + inline int getRealSize() const { return mData->getSize(); } private: const ESM::Land* mLand; int mLoadFlags; - ESM::Land::LandData mData; + std::unique_ptr 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 7bc0f8bbde..b2a9ece20c 100644 --- a/components/esm4/loadland.cpp +++ b/components/esm4/loadland.cpp @@ -35,7 +35,7 @@ #include // FIXME: debug only #include "reader.hpp" -//#include "writer.hpp" +// #include "writer.hpp" // overlap north // @@ -232,6 +232,24 @@ 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 = -200000.f; + mMaxHeight = 200000.f; + + float row_offset = mHeightMap.heightOffset; + for (int y = 0; y < VERTS_PER_SIDE; y++) + { + row_offset += mHeightMap.gradientData[y * VERTS_PER_SIDE]; + + mHeights[y * VERTS_PER_SIDE] = row_offset * HEIGHT_SCALE; + + float colOffset = row_offset; + for (int x = 1; x < VERTS_PER_SIDE; x++) + { + colOffset += mHeightMap.gradientData[y * VERTS_PER_SIDE + x]; + mHeights[x + y * VERTS_PER_SIDE] = colOffset * HEIGHT_SCALE; + } + } } // void ESM4::Land::save(ESM4::Writer& writer) const diff --git a/components/esm4/loadland.hpp b/components/esm4/loadland.hpp index 9c5e21b9bc..e34d5a0f5b 100644 --- a/components/esm4/loadland.hpp +++ b/components/esm4/loadland.hpp @@ -33,11 +33,13 @@ #include "formid.hpp" +#include + namespace ESM4 { class Reader; - struct Land + struct Land : public ESM::LandData { enum { @@ -117,8 +119,10 @@ namespace ESM4 // FIXME: lazy loading not yet implemented int mDataTypes; // which data types are loaded + float mHeights[VERTS_PER_SIDE * VERTS_PER_SIDE]; // Float value of compressed Heightmap + float mMinHeight, mMaxHeight; signed char mVertNorm[VERTS_PER_SIDE * VERTS_PER_SIDE * 3]; // from VNML subrecord - signed char mVertColr[VERTS_PER_SIDE * VERTS_PER_SIDE * 3]; // from VCLR subrecord + unsigned char mVertColr[VERTS_PER_SIDE * VERTS_PER_SIDE * 3]; // from VCLR subrecord VHGT mHeightMap; Texture mTextures[4]; // 0 = bottom left, 1 = bottom right, 2 = top left, 3 = top right std::vector mIds; // land texture (LTEX) formids @@ -127,6 +131,15 @@ namespace ESM4 // void save(Writer& writer) const; // void blank(); + + 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 { return {}; } + float getSize() const override { return REAL_SIZE; } + float getMinHeight() const override { return mMinHeight; } + float getMaxHeight() const { return mMaxHeight; } + int getLandSize() const { return VERTS_PER_SIDE; } }; }