mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-28 04:41:34 +00:00
don't touch ESMTerrain::Storage
This commit is contained in:
parent
3d07b63ad8
commit
fc772744d2
3 changed files with 58 additions and 84 deletions
|
@ -13,6 +13,39 @@
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
osg::Vec3f getTextureCorrectedWorldPos(
|
||||||
|
const osg::Vec3f& uncorrectedWorldPos, const int textureSize, const float cellSize)
|
||||||
|
{
|
||||||
|
// the offset is [-0.25, +0.25] of a single texture's size
|
||||||
|
// TODO: verify whether or not this works in TES4 and beyond
|
||||||
|
float offset = (cellSize / textureSize) * 0.25;
|
||||||
|
return uncorrectedWorldPos + osg::Vec3f{ -offset, +offset, 0.0f };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Takes in a corrected world pos to match the visuals.
|
||||||
|
ESMTerrain::UniqueTextureId getTextureAt(const std::span<const std::uint16_t> landData, const int plugin,
|
||||||
|
const int textureSize, const osg::Vec3f& correctedWorldPos, const float cellSize)
|
||||||
|
{
|
||||||
|
int cellX = static_cast<int>(std::floor(correctedWorldPos.x() / cellSize));
|
||||||
|
int cellY = static_cast<int>(std::floor(correctedWorldPos.y() / cellSize));
|
||||||
|
|
||||||
|
// Normalized position in the cell
|
||||||
|
float nX = (correctedWorldPos.x() - (cellX * cellSize)) / cellSize;
|
||||||
|
float nY = (correctedWorldPos.y() - (cellY * cellSize)) / cellSize;
|
||||||
|
|
||||||
|
int startX = static_cast<int>(nX * textureSize);
|
||||||
|
int startY = static_cast<int>(nY * textureSize);
|
||||||
|
|
||||||
|
assert(startX < ESM::Land::LAND_TEXTURE_SIZE);
|
||||||
|
assert(startY < ESM::Land::LAND_TEXTURE_SIZE);
|
||||||
|
|
||||||
|
const std::uint16_t tex = landData[startY * ESM::Land::LAND_TEXTURE_SIZE + startX];
|
||||||
|
if (tex == 0)
|
||||||
|
return { 0, 0 }; // vtex 0 is always the base texture, regardless of plugin
|
||||||
|
|
||||||
|
return { tex, plugin };
|
||||||
|
}
|
||||||
|
|
||||||
const ESM::RefId worldspaceAt(const osg::Vec3f& pos, sol::object cellOrName)
|
const ESM::RefId worldspaceAt(const osg::Vec3f& pos, sol::object cellOrName)
|
||||||
{
|
{
|
||||||
ESM::RefId worldspace;
|
ESM::RefId worldspace;
|
||||||
|
@ -65,7 +98,7 @@ namespace MWLua
|
||||||
landApi["getTextureAt"] = [lua = lua](const osg::Vec3f& pos, sol::object cellOrName) {
|
landApi["getTextureAt"] = [lua = lua](const osg::Vec3f& pos, sol::object cellOrName) {
|
||||||
sol::variadic_results values;
|
sol::variadic_results values;
|
||||||
auto store = MWBase::Environment::get().getESMStore();
|
auto store = MWBase::Environment::get().getESMStore();
|
||||||
const auto &landStore = store->get<ESM::Land>();
|
const auto& landStore = store->get<ESM::Land>();
|
||||||
|
|
||||||
const float cellSize = ESM::getCellSize(worldspaceAt(pos, cellOrName));
|
const float cellSize = ESM::getCellSize(worldspaceAt(pos, cellOrName));
|
||||||
// We need to read land twice. Once to get the amount of texture samples per cell edge, and the second time
|
// We need to read land twice. Once to get the amount of texture samples per cell edge, and the second time
|
||||||
|
@ -82,8 +115,7 @@ namespace MWLua
|
||||||
|
|
||||||
// Use landData to get amount of sampler per cell edge (sLandTextureSize)
|
// Use landData to get amount of sampler per cell edge (sLandTextureSize)
|
||||||
// and then get the corrected position that will map to the rendered texture
|
// and then get the corrected position that will map to the rendered texture
|
||||||
const osg::Vec3f correctedPos
|
const osg::Vec3f correctedPos = getTextureCorrectedWorldPos(pos, landData->sLandTextureSize, cellSize);
|
||||||
= ESMTerrain::Storage::getTextureCorrectedWorldPos(pos, landData->sLandTextureSize, cellSize);
|
|
||||||
|
|
||||||
const ESM::Land* correctedLand = nullptr;
|
const ESM::Land* correctedLand = nullptr;
|
||||||
const ESM::Land::LandData* correctedLandData = nullptr;
|
const ESM::Land::LandData* correctedLandData = nullptr;
|
||||||
|
@ -93,7 +125,7 @@ namespace MWLua
|
||||||
|
|
||||||
// We're passing in sLandTextureSize, NOT sLandSize like with getHeightAt
|
// We're passing in sLandTextureSize, NOT sLandSize like with getHeightAt
|
||||||
const ESMTerrain::UniqueTextureId textureId
|
const ESMTerrain::UniqueTextureId textureId
|
||||||
= ESMTerrain::Storage::getTextureAt(correctedLandData->mTextures, correctedLand->getPlugin(),
|
= getTextureAt(correctedLandData->mTextures, correctedLand->getPlugin(),
|
||||||
correctedLandData->sLandTextureSize, correctedPos, cellSize);
|
correctedLandData->sLandTextureSize, correctedPos, cellSize);
|
||||||
|
|
||||||
// Need to check for 0, 0 so that we can safely subtract 1 later, as per documentation on UniqueTextureId
|
// Need to check for 0, 0 so that we can safely subtract 1 later, as per documentation on UniqueTextureId
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include <osg/Image>
|
#include <osg/Image>
|
||||||
#include <osg/Plane>
|
#include <osg/Plane>
|
||||||
#include <osg/Vec3f>
|
|
||||||
|
|
||||||
#include <components/debug/debuglog.hpp>
|
#include <components/debug/debuglog.hpp>
|
||||||
#include <components/esm/esmterrain.hpp>
|
#include <components/esm/esmterrain.hpp>
|
||||||
|
@ -23,19 +22,6 @@ namespace ESMTerrain
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
UniqueTextureId getTextureIdAt(
|
|
||||||
const std::span<const std::uint16_t> data, const int plugin, const std::size_t x, const std::size_t y)
|
|
||||||
{
|
|
||||||
assert(x < ESM::Land::LAND_TEXTURE_SIZE);
|
|
||||||
assert(y < ESM::Land::LAND_TEXTURE_SIZE);
|
|
||||||
|
|
||||||
const std::uint16_t tex = data[y * ESM::Land::LAND_TEXTURE_SIZE + x];
|
|
||||||
if (tex == 0)
|
|
||||||
return { 0, 0 }; // vtex 0 is always the base texture, regardless of plugin
|
|
||||||
|
|
||||||
return { tex, plugin };
|
|
||||||
}
|
|
||||||
|
|
||||||
UniqueTextureId getTextureIdAt(const LandObject* land, std::size_t x, std::size_t y)
|
UniqueTextureId getTextureIdAt(const LandObject* land, std::size_t x, std::size_t y)
|
||||||
{
|
{
|
||||||
assert(x < ESM::Land::LAND_TEXTURE_SIZE);
|
assert(x < ESM::Land::LAND_TEXTURE_SIZE);
|
||||||
|
@ -48,7 +34,11 @@ namespace ESMTerrain
|
||||||
if (data == nullptr)
|
if (data == nullptr)
|
||||||
return { 0, 0 };
|
return { 0, 0 };
|
||||||
|
|
||||||
return getTextureIdAt(data->getTextures(), land->getPlugin(), x, y);
|
const std::uint16_t tex = data->getTextures()[y * ESM::Land::LAND_TEXTURE_SIZE + x];
|
||||||
|
if (tex == 0)
|
||||||
|
return { 0, 0 }; // vtex 0 is always the base texture, regardless of plugin
|
||||||
|
|
||||||
|
return { tex, land->getPlugin() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,39 +465,21 @@ namespace ESMTerrain
|
||||||
blendmaps.clear(); // If a single texture fills the whole terrain, there is no need to blend
|
blendmaps.clear(); // If a single texture fills the whole terrain, there is no need to blend
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a position that can be used to look up a land texture, while taking their offset into account
|
float Storage::getHeightAt(const osg::Vec3f& worldPos, ESM::RefId worldspace)
|
||||||
osg::Vec3f Storage::getTextureCorrectedWorldPos(
|
|
||||||
const osg::Vec3f& uncorrectedWorldPos, const int textureSize, const float cellSize)
|
|
||||||
{
|
|
||||||
// the offset is [-0.25, +0.25] of a single texture's size
|
|
||||||
// TODO: verify whether or not this works in TES4 and beyond
|
|
||||||
float offset = (cellSize / textureSize) * 0.25;
|
|
||||||
return uncorrectedWorldPos + osg::Vec3f{ -offset, +offset, 0.0f };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Takes in a corrected world pos to match the visuals.
|
|
||||||
UniqueTextureId Storage::getTextureAt(const std::span<const std::uint16_t> landData, const int plugin,
|
|
||||||
const int textureSize, const osg::Vec3f& correctedWorldPos, const float cellSize)
|
|
||||||
{
|
|
||||||
int cellX = static_cast<int>(std::floor(correctedWorldPos.x() / cellSize));
|
|
||||||
int cellY = static_cast<int>(std::floor(correctedWorldPos.y() / cellSize));
|
|
||||||
|
|
||||||
// Normalized position in the cell
|
|
||||||
float nX = (correctedWorldPos.x() - (cellX * cellSize)) / cellSize;
|
|
||||||
float nY = (correctedWorldPos.y() - (cellY * cellSize)) / cellSize;
|
|
||||||
|
|
||||||
int startX = static_cast<int>(nX * textureSize);
|
|
||||||
int startY = static_cast<int>(nY * textureSize);
|
|
||||||
|
|
||||||
return getTextureIdAt(landData, plugin, startX, startY);
|
|
||||||
}
|
|
||||||
|
|
||||||
float Storage::getHeightAt(
|
|
||||||
const std::span<const float> data, const int landSize, const osg::Vec3f& worldPos, const float cellSize)
|
|
||||||
{
|
{
|
||||||
|
const float cellSize = ESM::getCellSize(worldspace);
|
||||||
int cellX = static_cast<int>(std::floor(worldPos.x() / cellSize));
|
int cellX = static_cast<int>(std::floor(worldPos.x() / cellSize));
|
||||||
int cellY = static_cast<int>(std::floor(worldPos.y() / cellSize));
|
int cellY = static_cast<int>(std::floor(worldPos.y() / cellSize));
|
||||||
|
|
||||||
|
osg::ref_ptr<const LandObject> land = getLand(ESM::ExteriorCellLocation(cellX, cellY, worldspace));
|
||||||
|
if (!land)
|
||||||
|
return ESM::isEsm4Ext(worldspace) ? std::numeric_limits<float>::lowest() : defaultHeight;
|
||||||
|
|
||||||
|
const ESM::LandData* data = land->getData(ESM::Land::DATA_VHGT);
|
||||||
|
if (!data)
|
||||||
|
return defaultHeight;
|
||||||
|
const int landSize = data->getLandSize();
|
||||||
|
|
||||||
// Mostly lifted from Ogre::Terrain::getHeightAtTerrainPosition
|
// Mostly lifted from Ogre::Terrain::getHeightAtTerrainPosition
|
||||||
|
|
||||||
// Normalized position in the cell
|
// Normalized position in the cell
|
||||||
|
@ -544,10 +516,10 @@ namespace ESMTerrain
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Build all 4 positions in normalized cell space, using point-sampled height
|
// Build all 4 positions in normalized cell space, using point-sampled height
|
||||||
osg::Vec3f v0(startXTS, startYTS, Storage::getVertexHeight(data, landSize, startX, startY) / cellSize);
|
osg::Vec3f v0(startXTS, startYTS, getVertexHeight(data, startX, startY) / cellSize);
|
||||||
osg::Vec3f v1(endXTS, startYTS, Storage::getVertexHeight(data, landSize, endX, startY) / cellSize);
|
osg::Vec3f v1(endXTS, startYTS, getVertexHeight(data, endX, startY) / cellSize);
|
||||||
osg::Vec3f v2(endXTS, endYTS, Storage::getVertexHeight(data, landSize, endX, endY) / cellSize);
|
osg::Vec3f v2(endXTS, endYTS, getVertexHeight(data, endX, endY) / cellSize);
|
||||||
osg::Vec3f v3(startXTS, endYTS, Storage::getVertexHeight(data, landSize, startX, endY) / cellSize);
|
osg::Vec3f v3(startXTS, endYTS, getVertexHeight(data, startX, endY) / cellSize);
|
||||||
// define this plane in terrain space
|
// define this plane in terrain space
|
||||||
osg::Plane plane;
|
osg::Plane plane;
|
||||||
// FIXME: deal with differing triangle alignment
|
// FIXME: deal with differing triangle alignment
|
||||||
|
@ -576,22 +548,6 @@ namespace ESMTerrain
|
||||||
return (-plane.getNormal().x() * nX - plane.getNormal().y() * nY - plane[3]) / plane.getNormal().z() * cellSize;
|
return (-plane.getNormal().x() * nX - plane.getNormal().y() * nY - plane[3]) / plane.getNormal().z() * cellSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Storage::getHeightAt(const osg::Vec3f& worldPos, ESM::RefId worldspace)
|
|
||||||
{
|
|
||||||
const float cellSize = ESM::getCellSize(worldspace);
|
|
||||||
int cellX = static_cast<int>(std::floor(worldPos.x() / cellSize));
|
|
||||||
int cellY = static_cast<int>(std::floor(worldPos.y() / cellSize));
|
|
||||||
|
|
||||||
osg::ref_ptr<const LandObject> land = getLand(ESM::ExteriorCellLocation(cellX, cellY, worldspace));
|
|
||||||
if (!land)
|
|
||||||
return ESM::isEsm4Ext(worldspace) ? std::numeric_limits<float>::lowest() : defaultHeight;
|
|
||||||
|
|
||||||
const ESM::LandData* data = land->getData(ESM::Land::DATA_VHGT);
|
|
||||||
if (!data)
|
|
||||||
return defaultHeight;
|
|
||||||
return Storage::getHeightAt(data->getHeights(), data->getLandSize(), worldPos, cellSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
const LandObject* Storage::getLand(ESM::ExteriorCellLocation cellLocation, LandCache& cache)
|
const LandObject* Storage::getLand(ESM::ExteriorCellLocation cellLocation, LandCache& cache)
|
||||||
{
|
{
|
||||||
if (const auto land = cache.find(cellLocation.mX, cellLocation.mY))
|
if (const auto land = cache.find(cellLocation.mX, cellLocation.mY))
|
||||||
|
|
|
@ -114,15 +114,6 @@ namespace ESMTerrain
|
||||||
|
|
||||||
float getHeightAt(const osg::Vec3f& worldPos, ESM::RefId worldspace) override;
|
float getHeightAt(const osg::Vec3f& worldPos, ESM::RefId worldspace) override;
|
||||||
|
|
||||||
static float getHeightAt(
|
|
||||||
const std::span<const float> data, const int landSize, const osg::Vec3f& worldPos, const float cellSize);
|
|
||||||
|
|
||||||
static osg::Vec3f getTextureCorrectedWorldPos(
|
|
||||||
const osg::Vec3f& uncorrectedWorldPos, const int textureSize, const float cellSize);
|
|
||||||
|
|
||||||
static UniqueTextureId getTextureAt(const std::span<const std::uint16_t> landData, const int plugin,
|
|
||||||
const int textureSize, const osg::Vec3f& worldPos, const float cellSize);
|
|
||||||
|
|
||||||
/// Get the transformation factor for mapping cell units to world units.
|
/// Get the transformation factor for mapping cell units to world units.
|
||||||
float getCellWorldSize(ESM::RefId worldspace) override;
|
float getCellWorldSize(ESM::RefId worldspace) override;
|
||||||
|
|
||||||
|
@ -131,17 +122,12 @@ namespace ESMTerrain
|
||||||
|
|
||||||
int getBlendmapScale(float chunkSize) override;
|
int getBlendmapScale(float chunkSize) override;
|
||||||
|
|
||||||
static float getVertexHeight(const ESM::LandData* data, int x, int y)
|
float getVertexHeight(const ESM::LandData* data, int x, int y)
|
||||||
{
|
{
|
||||||
const int landSize = data->getLandSize();
|
const int landSize = data->getLandSize();
|
||||||
return getVertexHeight(data->getHeights(), landSize, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static float getVertexHeight(const std::span<const float> data, const int landSize, int x, int y)
|
|
||||||
{
|
|
||||||
assert(x < landSize);
|
assert(x < landSize);
|
||||||
assert(y < landSize);
|
assert(y < landSize);
|
||||||
return data[y * landSize + x];
|
return data->getHeights()[y * landSize + x];
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in a new issue