mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-28 15:39:48 +00:00
Abstracted Land data that can be used by esm3 and esm4.
This commit is contained in:
parent
e09cf6ac61
commit
e0fa15b727
8 changed files with 121 additions and 76 deletions
|
@ -72,8 +72,8 @@ namespace CSVRender
|
|||
if (index == -1) // no land!
|
||||
return height;
|
||||
|
||||
const ESM::Land::LandData* landData = mData.getLand().getRecord(index).get().getLandData(ESM::Land::DATA_VHGT);
|
||||
height = landData->mHeights[inCellY * ESM::Land::LAND_SIZE + inCellX];
|
||||
const ESM::LandData* landData = mData.getLand().getRecord(index).get().getLandData(ESM::Land::DATA_VHGT);
|
||||
height = landData->getHeights()[inCellY * ESM::Land::LAND_SIZE + inCellX];
|
||||
return mAlteredHeight[inCellY * ESM::Land::LAND_SIZE + inCellX] + height;
|
||||
}
|
||||
|
||||
|
@ -152,13 +152,14 @@ namespace CSVRender
|
|||
|| getHeightDifferenceToDown(col, row, heightData) >= heightWarningLimit;
|
||||
}
|
||||
|
||||
void TerrainStorage::adjustColor(int col, int row, const ESM::Land::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
|
||||
const ESM::Land::LandData* heightDataEsm3 = dynamic_cast<const ESM::Land::LandData*>(heightData);
|
||||
int heightWarningLimit = 1024;
|
||||
if (((col > 0 && row > 0) && leftOrUpIsOverTheLimit(col, row, heightWarningLimit, heightData))
|
||||
if (((col > 0 && row > 0) && leftOrUpIsOverTheLimit(col, row, heightWarningLimit, heightDataEsm3))
|
||||
|| ((col < ESM::Land::LAND_SIZE - 1 && row < ESM::Land::LAND_SIZE - 1)
|
||||
&& rightOrDownIsOverTheLimit(col, row, heightWarningLimit, heightData)))
|
||||
&& rightOrDownIsOverTheLimit(col, row, heightWarningLimit, heightDataEsm3)))
|
||||
{
|
||||
color.r() = 255;
|
||||
color.g() = 0;
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace CSVRender
|
|||
bool rightOrDownIsOverTheLimit(
|
||||
int col, int row, int heightWarningLimit, const ESM::Land::LandData* heightData) const;
|
||||
|
||||
void adjustColor(int col, int row, const ESM::Land::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;
|
||||
};
|
||||
|
||||
|
|
|
@ -397,13 +397,13 @@ namespace MWWorld
|
|||
if (cellVariant.isExterior())
|
||||
{
|
||||
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellIndex);
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
|
||||
const int verts = ESM::Land::LAND_SIZE;
|
||||
const int worldsize = ESM::Land::REAL_SIZE;
|
||||
const ESM::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
|
||||
const int verts = data->getLandSize();
|
||||
const int worldsize = data->getSize();
|
||||
if (data)
|
||||
{
|
||||
mPhysics->addHeightField(
|
||||
data->mHeights, cellX, cellY, worldsize, verts, data->mMinHeight, data->mMaxHeight, land.get());
|
||||
mPhysics->addHeightField(data->getHeights().data(), cellX, cellY, worldsize, verts,
|
||||
data->getMinHeight(), data->getMaxHeight(), land.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -425,14 +425,14 @@ namespace MWWorld
|
|||
else
|
||||
{
|
||||
DetourNavigator::HeightfieldSurface heights;
|
||||
heights.mHeights = data->mHeights;
|
||||
heights.mSize = static_cast<std::size_t>(ESM::Land::LAND_SIZE);
|
||||
heights.mMinHeight = data->mMinHeight;
|
||||
heights.mMaxHeight = data->mMaxHeight;
|
||||
heights.mHeights = data->getHeights().data();
|
||||
heights.mSize = static_cast<std::size_t>(data->getLandSize());
|
||||
heights.mMinHeight = data->getMinHeight();
|
||||
heights.mMaxHeight = data->getMaxHeight();
|
||||
return heights;
|
||||
}
|
||||
}();
|
||||
mNavigator.addHeightfield(cellPosition, ESM::Land::REAL_SIZE, shape, navigatorUpdateGuard);
|
||||
mNavigator.addHeightfield(cellPosition, data->getSize(), shape, navigatorUpdateGuard);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ add_component_dir (to_utf8
|
|||
to_utf8
|
||||
)
|
||||
|
||||
add_component_dir(esm attr common defs esmcommon records util luascripts format refid esmbridge
|
||||
add_component_dir(esm attr common defs esmcommon records util luascripts format refid esmbridge esmterrain
|
||||
formid
|
||||
formidrefid
|
||||
stringrefid
|
||||
|
|
25
components/esm/esmterrain.hpp
Normal file
25
components/esm/esmterrain.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef COMPONENTS_ESM_ESMTERRAIN
|
||||
#define COMPONENTS_ESM_ESMTERRAIN
|
||||
|
||||
#include <span>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class LandData
|
||||
{
|
||||
|
||||
public:
|
||||
typedef signed char VNML;
|
||||
|
||||
virtual std::span<const float> getHeights() const = 0;
|
||||
virtual std::span<const VNML> getNormals() const = 0;
|
||||
virtual std::span<const unsigned char> getColors() const = 0;
|
||||
virtual std::span<const uint16_t> getTextures() const = 0;
|
||||
virtual float getSize() const = 0;
|
||||
virtual float getMinHeight() const = 0;
|
||||
virtual float getMaxHeight() const = 0;
|
||||
virtual int getLandSize() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // ! COMPNENTS_ESM_ESMTERRAIN
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "components/esm/defs.hpp"
|
||||
#include "components/esm/esmcommon.hpp"
|
||||
#include "components/esm/esmterrain.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -87,9 +88,7 @@ namespace ESM
|
|||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef signed char VNML;
|
||||
|
||||
struct LandData
|
||||
struct LandData : public ESM::LandData
|
||||
{
|
||||
LandData()
|
||||
: mHeightOffset(0)
|
||||
|
@ -124,6 +123,15 @@ namespace ESM
|
|||
uint8_t mUnk2;
|
||||
|
||||
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 { return mMaxHeight; }
|
||||
int getLandSize() const { return LAND_SIZE; }
|
||||
};
|
||||
|
||||
// low-LOD heightmap (used for rendering the global map)
|
||||
|
|
|
@ -63,15 +63,15 @@ namespace ESMTerrain
|
|||
|
||||
int cellX = static_cast<int>(std::floor(origin.x()));
|
||||
int cellY = static_cast<int>(std::floor(origin.y()));
|
||||
|
||||
int startRow = (origin.x() - cellX) * ESM::Land::LAND_SIZE;
|
||||
int startColumn = (origin.y() - cellY) * ESM::Land::LAND_SIZE;
|
||||
|
||||
int endRow = startRow + size * (ESM::Land::LAND_SIZE - 1) + 1;
|
||||
int endColumn = startColumn + size * (ESM::Land::LAND_SIZE - 1) + 1;
|
||||
|
||||
osg::ref_ptr<const LandObject> land = getLand(ESM::ExteriorCellLocation(cellX, cellY, worldspace));
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
|
||||
const ESM::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
|
||||
|
||||
int startRow = (origin.x() - cellX) * data->getLandSize();
|
||||
int startColumn = (origin.y() - cellY) * data->getLandSize();
|
||||
|
||||
int endRow = startRow + size * (data->getLandSize() - 1) + 1;
|
||||
int endColumn = startColumn + size * (data->getLandSize() - 1) + 1;
|
||||
|
||||
if (data)
|
||||
{
|
||||
min = std::numeric_limits<float>::max();
|
||||
|
@ -80,7 +80,7 @@ namespace ESMTerrain
|
|||
{
|
||||
for (int col = startColumn; col < endColumn; ++col)
|
||||
{
|
||||
float h = data->mHeights[col * ESM::Land::LAND_SIZE + row];
|
||||
float h = data->getHeights()[col * data->getLandSize() + row];
|
||||
if (h > max)
|
||||
max = h;
|
||||
if (h < min)
|
||||
|
@ -98,34 +98,37 @@ namespace ESMTerrain
|
|||
void Storage::fixNormal(
|
||||
osg::Vec3f& normal, ESM::ExteriorCellLocation cellLocation, int col, int row, LandCache& cache)
|
||||
{
|
||||
while (col >= ESM::Land::LAND_SIZE - 1)
|
||||
|
||||
const LandObject* land = getLand(cellLocation, cache);
|
||||
const ESM::LandData* data = land ? land->getData(ESM::Land::DATA_VNML) : nullptr;
|
||||
const int landSize = data ? data->getLandSize() : ESM::Land::LAND_SIZE;
|
||||
|
||||
while (col >= landSize - 1)
|
||||
{
|
||||
++cellLocation.mY;
|
||||
col -= ESM::Land::LAND_SIZE - 1;
|
||||
col -= landSize - 1;
|
||||
}
|
||||
while (row >= ESM::Land::LAND_SIZE - 1)
|
||||
while (row >= landSize - 1)
|
||||
{
|
||||
++cellLocation.mX;
|
||||
row -= ESM::Land::LAND_SIZE - 1;
|
||||
row -= landSize - 1;
|
||||
}
|
||||
while (col < 0)
|
||||
{
|
||||
--cellLocation.mY;
|
||||
col += ESM::Land::LAND_SIZE - 1;
|
||||
col += landSize - 1;
|
||||
}
|
||||
while (row < 0)
|
||||
{
|
||||
--cellLocation.mX;
|
||||
row += ESM::Land::LAND_SIZE - 1;
|
||||
row += landSize - 1;
|
||||
}
|
||||
|
||||
const LandObject* land = getLand(cellLocation, cache);
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VNML) : nullptr;
|
||||
if (data)
|
||||
{
|
||||
normal.x() = data->mNormals[col * ESM::Land::LAND_SIZE * 3 + row * 3];
|
||||
normal.y() = data->mNormals[col * ESM::Land::LAND_SIZE * 3 + row * 3 + 1];
|
||||
normal.z() = data->mNormals[col * ESM::Land::LAND_SIZE * 3 + row * 3 + 2];
|
||||
normal.x() = data->getNormals()[col * landSize * 3 + row * 3];
|
||||
normal.y() = data->getNormals()[col * landSize * 3 + row * 3 + 1];
|
||||
normal.z() = data->getNormals()[col * landSize * 3 + row * 3 + 2];
|
||||
normal.normalize();
|
||||
}
|
||||
else
|
||||
|
@ -147,24 +150,26 @@ namespace ESMTerrain
|
|||
void Storage::fixColour(
|
||||
osg::Vec4ub& color, ESM::ExteriorCellLocation cellLocation, int col, int row, LandCache& cache)
|
||||
{
|
||||
if (col == ESM::Land::LAND_SIZE - 1)
|
||||
const LandObject* land = getLand(cellLocation, cache);
|
||||
const ESM::LandData* data = land ? land->getData(ESM::Land::DATA_VCLR) : nullptr;
|
||||
const int landSize = data ? data->getLandSize() : ESM::Land::LAND_SIZE;
|
||||
|
||||
if (col == landSize - 1)
|
||||
{
|
||||
++cellLocation.mY;
|
||||
col = 0;
|
||||
}
|
||||
if (row == ESM::Land::LAND_SIZE - 1)
|
||||
if (row == landSize - 1)
|
||||
{
|
||||
++cellLocation.mX;
|
||||
row = 0;
|
||||
}
|
||||
|
||||
const LandObject* land = getLand(cellLocation, cache);
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VCLR) : nullptr;
|
||||
if (data)
|
||||
{
|
||||
color.r() = data->mColours[col * ESM::Land::LAND_SIZE * 3 + row * 3];
|
||||
color.g() = data->mColours[col * ESM::Land::LAND_SIZE * 3 + row * 3 + 1];
|
||||
color.b() = data->mColours[col * ESM::Land::LAND_SIZE * 3 + row * 3 + 2];
|
||||
color.r() = data->getColors()[col * landSize * 3 + row * 3];
|
||||
color.g() = data->getColors()[col * landSize * 3 + row * 3 + 1];
|
||||
color.b() = data->getColors()[col * landSize * 3 + row * 3 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -210,9 +215,11 @@ namespace ESMTerrain
|
|||
{
|
||||
ESM::ExteriorCellLocation cellLocation(cellX, cellY, worldspace);
|
||||
const LandObject* land = getLand(cellLocation, cache);
|
||||
const ESM::Land::LandData* heightData = nullptr;
|
||||
const ESM::Land::LandData* normalData = nullptr;
|
||||
const ESM::Land::LandData* colourData = nullptr;
|
||||
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;
|
||||
if (land)
|
||||
{
|
||||
heightData = land->getData(ESM::Land::DATA_VHGT);
|
||||
|
@ -231,12 +238,12 @@ namespace ESMTerrain
|
|||
rowStart += increment;
|
||||
|
||||
// Only relevant for chunks smaller than (contained in) one cell
|
||||
rowStart += (origin.x() - startCellX) * ESM::Land::LAND_SIZE;
|
||||
colStart += (origin.y() - startCellY) * ESM::Land::LAND_SIZE;
|
||||
int rowEnd = std::min(static_cast<int>(rowStart + std::min(1.f, size) * (ESM::Land::LAND_SIZE - 1) + 1),
|
||||
static_cast<int>(ESM::Land::LAND_SIZE));
|
||||
int colEnd = std::min(static_cast<int>(colStart + std::min(1.f, size) * (ESM::Land::LAND_SIZE - 1) + 1),
|
||||
static_cast<int>(ESM::Land::LAND_SIZE));
|
||||
rowStart += (origin.x() - startCellX) * LandSize;
|
||||
colStart += (origin.y() - startCellY) * LandSize;
|
||||
int rowEnd = std::min(
|
||||
static_cast<int>(rowStart + std::min(1.f, size) * (LandSize - 1) + 1), static_cast<int>(LandSize));
|
||||
int colEnd = std::min(
|
||||
static_cast<int>(colStart + std::min(1.f, size) * (LandSize - 1) + 1), static_cast<int>(LandSize));
|
||||
|
||||
vertY = vertY_;
|
||||
for (int col = colStart; col < colEnd; col += increment)
|
||||
|
@ -244,27 +251,27 @@ namespace ESMTerrain
|
|||
vertX = vertX_;
|
||||
for (int row = rowStart; row < rowEnd; row += increment)
|
||||
{
|
||||
int srcArrayIndex = col * ESM::Land::LAND_SIZE * 3 + row * 3;
|
||||
int srcArrayIndex = col * LandSize * 3 + row * 3;
|
||||
|
||||
assert(row >= 0 && row < ESM::Land::LAND_SIZE);
|
||||
assert(col >= 0 && col < ESM::Land::LAND_SIZE);
|
||||
assert(row >= 0 && row < LandSize);
|
||||
assert(col >= 0 && col < LandSize);
|
||||
|
||||
assert(vertX < numVerts);
|
||||
assert(vertY < numVerts);
|
||||
|
||||
float height = defaultHeight;
|
||||
if (heightData)
|
||||
height = heightData->mHeights[col * ESM::Land::LAND_SIZE + row];
|
||||
height = heightData->getHeights()[col * LandSize + row];
|
||||
if (alteration)
|
||||
height += getAlteredHeight(col, row);
|
||||
(*positions)[static_cast<unsigned int>(vertX * numVerts + vertY)]
|
||||
= osg::Vec3f((vertX / float(numVerts - 1) - 0.5f) * size * Constants::CellSizeInUnits,
|
||||
(vertY / float(numVerts - 1) - 0.5f) * size * Constants::CellSizeInUnits, height);
|
||||
= osg::Vec3f((vertX / float(numVerts - 1) - 0.5f) * size * LandSizeInUnits,
|
||||
(vertY / float(numVerts - 1) - 0.5f) * size * LandSizeInUnits, height);
|
||||
|
||||
if (normalData)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
normal[i] = normalData->mNormals[srcArrayIndex + i];
|
||||
normal[i] = normalData->getNormals()[srcArrayIndex + i];
|
||||
|
||||
normal.normalize();
|
||||
}
|
||||
|
@ -272,12 +279,11 @@ namespace ESMTerrain
|
|||
normal = osg::Vec3f(0, 0, 1);
|
||||
|
||||
// Normals apparently don't connect seamlessly between cells
|
||||
if (col == ESM::Land::LAND_SIZE - 1 || row == ESM::Land::LAND_SIZE - 1)
|
||||
if (col == LandSize - 1 || row == LandSize - 1)
|
||||
fixNormal(normal, cellLocation, col, row, cache);
|
||||
|
||||
// some corner normals appear to be complete garbage (z < 0)
|
||||
if ((row == 0 || row == ESM::Land::LAND_SIZE - 1)
|
||||
&& (col == 0 || col == ESM::Land::LAND_SIZE - 1))
|
||||
if ((row == 0 || row == LandSize - 1) && (col == 0 || col == LandSize - 1))
|
||||
averageNormal(normal, cellLocation, col, row, cache);
|
||||
|
||||
assert(normal.z() > 0);
|
||||
|
@ -287,7 +293,7 @@ namespace ESMTerrain
|
|||
if (colourData)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
color[i] = colourData->mColours[srcArrayIndex + i];
|
||||
color[i] = colourData->getColors()[srcArrayIndex + i];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -299,7 +305,7 @@ namespace ESMTerrain
|
|||
adjustColor(col, row, heightData, color); // Does nothing by default, override in OpenMW-CS
|
||||
|
||||
// Unlike normals, colors mostly connect seamlessly between cells, but not always...
|
||||
if (col == ESM::Land::LAND_SIZE - 1 || row == ESM::Land::LAND_SIZE - 1)
|
||||
if (col == LandSize - 1 || row == LandSize - 1)
|
||||
fixColour(color, cellLocation, col, row, cache);
|
||||
|
||||
color.a() = 255;
|
||||
|
@ -347,10 +353,10 @@ namespace ESMTerrain
|
|||
|
||||
const LandObject* land = getLand(cellLocation, cache);
|
||||
|
||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VTEX) : nullptr;
|
||||
const ESM::LandData* data = land ? land->getData(ESM::Land::DATA_VTEX) : nullptr;
|
||||
if (data)
|
||||
{
|
||||
int tex = data->mTextures[y * ESM::Land::LAND_TEXTURE_SIZE + x];
|
||||
int tex = data->getTextures()[y * ESM::Land::LAND_TEXTURE_SIZE + x];
|
||||
if (tex == 0)
|
||||
return std::make_pair(0, 0); // vtex 0 is always the base texture, regardless of plugin
|
||||
return std::make_pair(tex, land->getPlugin());
|
||||
|
@ -458,7 +464,7 @@ namespace ESMTerrain
|
|||
if (!land)
|
||||
return defaultHeight;
|
||||
|
||||
const ESM::Land::LandData* data = land->getData(ESM::Land::DATA_VHGT);
|
||||
const ESM::LandData* data = land->getData(ESM::Land::DATA_VHGT);
|
||||
if (!data)
|
||||
return defaultHeight;
|
||||
|
||||
|
@ -542,7 +548,7 @@ namespace ESMTerrain
|
|||
}
|
||||
}
|
||||
|
||||
void Storage::adjustColor(int col, int row, const ESM::Land::LandData* heightData, osg::Vec4ub& color) const {}
|
||||
void Storage::adjustColor(int col, int row, const ESM::LandData* heightData, osg::Vec4ub& color) const {}
|
||||
|
||||
float Storage::getAlteredHeight(int col, int row) const
|
||||
{
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
#include <components/esm3/loadland.hpp>
|
||||
#include <components/esm3/loadltex.hpp>
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
struct Land;
|
||||
}
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
class Manager;
|
||||
|
@ -32,7 +37,7 @@ namespace ESMTerrain
|
|||
|
||||
META_Object(ESMTerrain, LandObject)
|
||||
|
||||
inline const ESM::Land::LandData* getData(int flags) const
|
||||
inline const ESM::LandData* getData(int flags) const
|
||||
{
|
||||
if ((mData.mDataLoaded & flags) != flags)
|
||||
return nullptr;
|
||||
|
@ -108,11 +113,11 @@ namespace ESMTerrain
|
|||
|
||||
int getBlendmapScale(float chunkSize) override;
|
||||
|
||||
float getVertexHeight(const ESM::Land::LandData* data, int x, int y)
|
||||
float getVertexHeight(const ESM::LandData* data, int x, int y)
|
||||
{
|
||||
assert(x < ESM::Land::LAND_SIZE);
|
||||
assert(y < ESM::Land::LAND_SIZE);
|
||||
return data->mHeights[y * ESM::Land::LAND_SIZE + x];
|
||||
return data->getHeights()[y * ESM::Land::LAND_SIZE + x];
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -128,7 +133,7 @@ namespace ESMTerrain
|
|||
inline const LandObject* getLand(ESM::ExteriorCellLocation cellLocation, LandCache& cache);
|
||||
|
||||
virtual bool useAlteration() const { return false; }
|
||||
virtual void adjustColor(int col, int row, const ESM::Land::LandData* heightData, osg::Vec4ub& color) const;
|
||||
virtual void adjustColor(int col, int row, const ESM::LandData* heightData, osg::Vec4ub& color) const;
|
||||
virtual float getAlteredHeight(int col, int row) const;
|
||||
|
||||
// Since plugins can define new texture palettes, we need to know the plugin index too
|
||||
|
|
Loading…
Reference in a new issue