1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-03-03 15:09:39 +00:00

ESM::LandData no longer a virtual interface

instead it is constructed from ESM::Land or ESM4::Land
This commit is contained in:
florent.teppe 2023-05-26 02:14:56 +02:00
parent 4c4ed77bd7
commit ad8cfde4e0
10 changed files with 146 additions and 146 deletions

View file

@ -72,8 +72,8 @@ namespace CSVRender
if (index == -1) // no land! if (index == -1) // no land!
return height; return height;
const ESM::LandData* landData = mData.getLand().getRecord(index).get().getLandData(ESM::Land::DATA_VHGT); const ESM::Land::LandData* landData = mData.getLand().getRecord(index).get().getLandData(ESM::Land::DATA_VHGT);
height = landData->getHeights()[inCellY * ESM::Land::LAND_SIZE + inCellX]; height = landData->mHeights[inCellY * ESM::Land::LAND_SIZE + inCellX];
return mAlteredHeight[inCellY * ESM::Land::LAND_SIZE + inCellX] + height; return mAlteredHeight[inCellY * ESM::Land::LAND_SIZE + inCellX] + height;
} }
@ -88,65 +88,65 @@ namespace CSVRender
throw std::runtime_error("getBounds not implemented"); 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<const float> heightData) const
{ {
return heightData->mHeights[col * ESM::Land::LAND_SIZE + row] return heightData[col * ESM::Land::LAND_SIZE + row]
+ mAlteredHeight[static_cast<unsigned int>(col * ESM::Land::LAND_SIZE + row)]; + mAlteredHeight[static_cast<unsigned int>(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<const float> heightData) const
{ {
return heightData->mHeights[(col)*ESM::Land::LAND_SIZE + row - 1] return heightData[(col)*ESM::Land::LAND_SIZE + row - 1]
+ mAlteredHeight[static_cast<unsigned int>((col)*ESM::Land::LAND_SIZE + row - 1)]; + mAlteredHeight[static_cast<unsigned int>((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<const float> heightData) const
{ {
return heightData->mHeights[col * ESM::Land::LAND_SIZE + row + 1] return heightData[col * ESM::Land::LAND_SIZE + row + 1]
+ mAlteredHeight[static_cast<unsigned int>(col * ESM::Land::LAND_SIZE + row + 1)]; + mAlteredHeight[static_cast<unsigned int>(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<const float> heightData) const
{ {
return heightData->mHeights[(col - 1) * ESM::Land::LAND_SIZE + row] return heightData[(col - 1) * ESM::Land::LAND_SIZE + row]
+ mAlteredHeight[static_cast<unsigned int>((col - 1) * ESM::Land::LAND_SIZE + row)]; + mAlteredHeight[static_cast<unsigned int>((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<const float> heightData) const
{ {
return heightData->mHeights[(col + 1) * ESM::Land::LAND_SIZE + row] return heightData[(col + 1) * ESM::Land::LAND_SIZE + row]
+ mAlteredHeight[static_cast<unsigned int>((col + 1) * ESM::Land::LAND_SIZE + row)]; + mAlteredHeight[static_cast<unsigned int>((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<const float> heightData) const
{ {
return abs(getThisHeight(col, row, heightData) - getLeftHeight(col, row, heightData)); 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<const float> heightData) const
{ {
return abs(getThisHeight(col, row, heightData) - getRightHeight(col, row, heightData)); 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<const float> heightData) const
{ {
return abs(getThisHeight(col, row, heightData) - getUpHeight(col, row, heightData)); 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<const float> heightData) const
{ {
return abs(getThisHeight(col, row, heightData) - getDownHeight(col, row, heightData)); return abs(getThisHeight(col, row, heightData) - getDownHeight(col, row, heightData));
} }
bool TerrainStorage::leftOrUpIsOverTheLimit( bool TerrainStorage::leftOrUpIsOverTheLimit(
int col, int row, int heightWarningLimit, const ESM::Land::LandData* heightData) const int col, int row, int heightWarningLimit, std::span<const float> heightData) const
{ {
return getHeightDifferenceToLeft(col, row, heightData) >= heightWarningLimit return getHeightDifferenceToLeft(col, row, heightData) >= heightWarningLimit
|| getHeightDifferenceToUp(col, row, heightData) >= heightWarningLimit; || getHeightDifferenceToUp(col, row, heightData) >= heightWarningLimit;
} }
bool TerrainStorage::rightOrDownIsOverTheLimit( bool TerrainStorage::rightOrDownIsOverTheLimit(
int col, int row, int heightWarningLimit, const ESM::Land::LandData* heightData) const int col, int row, int heightWarningLimit, std::span<const float> heightData) const
{ {
return getHeightDifferenceToRight(col, row, heightData) >= heightWarningLimit return getHeightDifferenceToRight(col, row, heightData) >= heightWarningLimit
|| getHeightDifferenceToDown(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 void TerrainStorage::adjustColor(int col, int row, const ESM::LandData* heightData, osg::Vec4ub& color) const
{ {
// Highlight broken height changes // Highlight broken height changes
const ESM::Land::LandData* heightDataEsm3 = dynamic_cast<const ESM::Land::LandData*>(heightData);
int heightWarningLimit = 1024; 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) || ((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.r() = 255;
color.g() = 0; color.g() = 0;

View file

@ -42,19 +42,18 @@ namespace CSVRender
void getBounds(float& minX, float& maxX, float& minY, float& maxY, ESM::RefId worldspace) override; 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 getThisHeight(int col, int row, std::span<const float> heightData) const;
int getLeftHeight(int col, int row, const ESM::Land::LandData* heightData) const; int getLeftHeight(int col, int row, std::span<const float> heightData) const;
int getRightHeight(int col, int row, const ESM::Land::LandData* heightData) const; int getRightHeight(int col, int row, std::span<const float> heightData) const;
int getUpHeight(int col, int row, const ESM::Land::LandData* heightData) const; int getUpHeight(int col, int row, std::span<const float> heightData) const;
int getDownHeight(int col, int row, const ESM::Land::LandData* heightData) const; int getDownHeight(int col, int row, std::span<const float> heightData) const;
int getHeightDifferenceToLeft(int col, int row, const ESM::Land::LandData* heightData) const; int getHeightDifferenceToLeft(int col, int row, std::span<const float> heightData) const;
int getHeightDifferenceToRight(int col, int row, const ESM::Land::LandData* heightData) const; int getHeightDifferenceToRight(int col, int row, std::span<const float> heightData) const;
int getHeightDifferenceToUp(int col, int row, const ESM::Land::LandData* heightData) const; int getHeightDifferenceToUp(int col, int row, std::span<const float> heightData) const;
int getHeightDifferenceToDown(int col, int row, const ESM::Land::LandData* heightData) const; int getHeightDifferenceToDown(int col, int row, std::span<const float> heightData) const;
bool leftOrUpIsOverTheLimit( bool leftOrUpIsOverTheLimit(int col, int row, int heightWarningLimit, std::span<const float> heightData) const;
int col, int row, int heightWarningLimit, const ESM::Land::LandData* heightData) const;
bool rightOrDownIsOverTheLimit( bool rightOrDownIsOverTheLimit(
int col, int row, int heightWarningLimit, const ESM::Land::LandData* heightData) const; int col, int row, int heightWarningLimit, std::span<const float> heightData) const;
void adjustColor(int col, int row, const ESM::LandData* heightData, osg::Vec4ub& color) const override; void adjustColor(int col, int row, const ESM::LandData* heightData, osg::Vec4ub& color) const override;
float getAlteredHeight(int col, int row) const override; float getAlteredHeight(int col, int row) const override;

View file

@ -12,6 +12,7 @@
#include <components/detournavigator/heightfieldshape.hpp> #include <components/detournavigator/heightfieldshape.hpp>
#include <components/detournavigator/navigator.hpp> #include <components/detournavigator/navigator.hpp>
#include <components/detournavigator/updateguard.hpp> #include <components/detournavigator/updateguard.hpp>
#include <components/esm/esmterrain.hpp>
#include <components/esm/records.hpp> #include <components/esm/records.hpp>
#include <components/esm3/loadcell.hpp> #include <components/esm3/loadcell.hpp>
#include <components/loadinglistener/loadinglistener.hpp> #include <components/loadinglistener/loadinglistener.hpp>

View file

@ -0,0 +1,67 @@
#include <components/misc/constants.hpp>
#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<const float> heights(data.mHeights);
mHeights = std::vector(heights.begin(), heights.end());
std::span<const VNML> normals(data.mNormals);
mNormals = std::vector(normals.begin(), normals.end());
std::span<const unsigned char> colors(data.mColours);
mColors = std::vector(colors.begin(), colors.end());
std::span<const uint16_t> 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<float>::max();
mMaxHeight = std::numeric_limits<float>::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<const VNML> normals(land.mVertNorm);
mNormals = std::vector(normals.begin(), normals.end());
std::span<const unsigned char> colors(land.mVertColr);
mColors = std::vector(colors.begin(), colors.end());
}

View file

@ -2,6 +2,10 @@
#define COMPONENTS_ESM_ESMTERRAIN #define COMPONENTS_ESM_ESMTERRAIN
#include <span> #include <span>
#include <vector>
#include <components/esm3/loadland.hpp>
#include <components/esm4/loadland.hpp>
namespace ESM namespace ESM
{ {
@ -9,18 +13,33 @@ namespace ESM
{ {
public: 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; typedef signed char VNML;
virtual std::span<const float> getHeights() const = 0; std::span<const float> getHeights() const { return mHeights; }
virtual std::span<const VNML> getNormals() const = 0; std::span<const VNML> getNormals() const { return mNormals; }
virtual std::span<const unsigned char> getColors() const = 0; std::span<const unsigned char> getColors() const { return mColors; }
virtual std::span<const uint16_t> getTextures() const = 0; std::span<const uint16_t> getTextures() const { return mTextures; }
virtual float getSize() const = 0; float getSize() const { return mSize; }
virtual float getMinHeight() const = 0; float getMinHeight() const { return mMinHeight; }
virtual float getMaxHeight() const = 0; float getMaxHeight() const { return mMaxHeight; }
virtual int getLandSize() const = 0; 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<float> mHeights;
std::vector<VNML> mNormals;
std::vector<unsigned char> mColors;
std::vector<uint16_t> mTextures;
}; };
} }

View file

@ -7,7 +7,6 @@
#include "components/esm/defs.hpp" #include "components/esm/defs.hpp"
#include "components/esm/esmcommon.hpp" #include "components/esm/esmcommon.hpp"
#include "components/esm/esmterrain.hpp"
namespace ESM namespace ESM
{ {
@ -88,8 +87,10 @@ namespace ESM
}; };
#pragma pack(pop) #pragma pack(pop)
struct LandData : public ESM::LandData struct LandData
{ {
typedef signed char VNML;
LandData() LandData()
: mHeightOffset(0) : mHeightOffset(0)
, mMinHeight(0) , mMinHeight(0)
@ -123,15 +124,6 @@ namespace ESM
uint8_t mUnk2; uint8_t mUnk2;
int mDataLoaded; int mDataLoaded;
std::span<const float> getHeights() const override { return mHeights; }
std::span<const VNML> getNormals() const override { return mNormals; }
std::span<const unsigned char> getColors() const override { return mColours; }
std::span<const uint16_t> 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) // low-LOD heightmap (used for rendering the global map)

View file

@ -6,6 +6,7 @@
#include <osg/Plane> #include <osg/Plane>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include <components/esm/esmterrain.hpp>
#include <components/esm4/loadland.hpp> #include <components/esm4/loadland.hpp>
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
#include <components/misc/strings/algorithm.hpp> #include <components/misc/strings/algorithm.hpp>
@ -30,18 +31,15 @@ namespace ESMTerrain
LandObject::LandObject(const ESM4::Land* land, int loadFlags) LandObject::LandObject(const ESM4::Land* land, int loadFlags)
: mLand(nullptr) : mLand(nullptr)
, mLoadFlags(0) , mLoadFlags(0)
, mData(*land, loadFlags)
{ {
mData = std::make_unique<ESM4::Land>(*land);
} }
LandObject::LandObject(const ESM::Land* land, int loadFlags) LandObject::LandObject(const ESM::Land* land, int loadFlags)
: mLand(land) : mLand(land)
, mLoadFlags(loadFlags) , mLoadFlags(loadFlags)
, mData(nullptr) , mData(*land, loadFlags)
{ {
std::unique_ptr<ESM::Land::LandData> esm3LandData = std::make_unique<ESM::Land::LandData>();
mLand->loadData(mLoadFlags, esm3LandData.get());
mData = std::move(esm3LandData);
} }
LandObject::LandObject(const LandObject& copy, const osg::CopyOp& copyop) LandObject::LandObject(const LandObject& copy, const osg::CopyOp& copyop)

View file

@ -6,6 +6,7 @@
#include <components/terrain/storage.hpp> #include <components/terrain/storage.hpp>
#include <components/esm/esmterrain.hpp>
#include <components/esm/util.hpp> #include <components/esm/util.hpp>
#include <components/esm3/loadland.hpp> #include <components/esm3/loadland.hpp>
#include <components/esm3/loadltex.hpp> #include <components/esm3/loadltex.hpp>
@ -15,6 +16,11 @@ namespace ESM4
struct Land; struct Land;
} }
namespace ESM
{
class LandData;
}
namespace VFS namespace VFS
{ {
class Manager; class Manager;
@ -41,22 +47,20 @@ namespace ESMTerrain
inline const ESM::LandData* getData(int flags) const inline const ESM::LandData* getData(int flags) const
{ {
if (!mData) if ((mData.mLoadFlags & flags) != flags)
return nullptr; return nullptr;
ESM::Land::LandData* esm3Land = dynamic_cast<ESM::Land::LandData*>(mData.get());
if (esm3Land && ((esm3Land->mDataLoaded & flags) != flags)) return &mData;
return nullptr;
return mData.get();
} }
inline int getPlugin() const { return mLand->getPlugin(); } inline int getPlugin() const { return mLand->getPlugin(); }
inline int getLandSize() const { return mData->getLandSize(); } inline int getLandSize() const { return mData.getLandSize(); }
inline int getRealSize() const { return mData->getSize(); } inline int getRealSize() const { return mData.getSize(); }
private: private:
const ESM::Land* mLand; const ESM::Land* mLand;
int mLoadFlags; int mLoadFlags;
std::unique_ptr<ESM::LandData> mData; ESM::LandData mData;
}; };
/// @brief Feeds data from ESM terrain records (ESM::Land, ESM::LandTexture) /// @brief Feeds data from ESM terrain records (ESM::Land, ESM::LandTexture)

View file

@ -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 // at least one of the quadrants do not have a base texture, return without setting the flag
if (!missing) if (!missing)
mDataTypes |= LAND_VTEX; mDataTypes |= LAND_VTEX;
mMinHeight = std::numeric_limits<float>::max();
mMaxHeight = std::numeric_limits<float>::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<const uint16_t> ESM4::Land::getTextures() const
{
static uint16_t textureArray[16 * 16] = {};
return textureArray;
} }
// void ESM4::Land::save(ESM4::Writer& writer) const // void ESM4::Land::save(ESM4::Writer& writer) const

View file

@ -34,14 +34,13 @@
#include "formid.hpp" #include "formid.hpp"
#include <components/esm/defs.hpp> #include <components/esm/defs.hpp>
#include <components/esm/esmterrain.hpp>
#include <components/esm/refid.hpp> #include <components/esm/refid.hpp>
namespace ESM4 namespace ESM4
{ {
class Reader; class Reader;
struct Land : public ESM::LandData struct Land
{ {
enum enum
{ {
@ -131,41 +130,10 @@ namespace ESM4
ESM::RefId mCell; ESM::RefId mCell;
void load(Reader& reader); void load(Reader& reader);
Land() = default; Land() = default;
Land(const Land& Other);
// void save(Writer& writer) const; // void save(Writer& writer) const;
// void blank(); // void blank();
static constexpr ESM::RecNameInts sRecordId = ESM::REC_LAND4; static constexpr ESM::RecNameInts sRecordId = ESM::REC_LAND4;
std::span<const float> getHeights() const override
{
return mHeights;
}
std::span<const VNML> getNormals() const override
{
return mVertNorm;
}
std::span<const unsigned char> getColors() const override
{
return mVertColr;
}
std::span<const uint16_t> 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;
}
}; };
} }