mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-27 20:41:38 +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
|
||||
{
|
||||
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)
|
||||
{
|
||||
ESM::RefId worldspace;
|
||||
|
@ -65,7 +98,7 @@ namespace MWLua
|
|||
landApi["getTextureAt"] = [lua = lua](const osg::Vec3f& pos, sol::object cellOrName) {
|
||||
sol::variadic_results values;
|
||||
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));
|
||||
// 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)
|
||||
// and then get the corrected position that will map to the rendered texture
|
||||
const osg::Vec3f correctedPos
|
||||
= ESMTerrain::Storage::getTextureCorrectedWorldPos(pos, landData->sLandTextureSize, cellSize);
|
||||
const osg::Vec3f correctedPos = getTextureCorrectedWorldPos(pos, landData->sLandTextureSize, cellSize);
|
||||
|
||||
const ESM::Land* correctedLand = nullptr;
|
||||
const ESM::Land::LandData* correctedLandData = nullptr;
|
||||
|
@ -93,7 +125,7 @@ namespace MWLua
|
|||
|
||||
// We're passing in sLandTextureSize, NOT sLandSize like with getHeightAt
|
||||
const ESMTerrain::UniqueTextureId textureId
|
||||
= ESMTerrain::Storage::getTextureAt(correctedLandData->mTextures, correctedLand->getPlugin(),
|
||||
= getTextureAt(correctedLandData->mTextures, correctedLand->getPlugin(),
|
||||
correctedLandData->sLandTextureSize, correctedPos, cellSize);
|
||||
|
||||
// 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/Plane>
|
||||
#include <osg/Vec3f>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/esm/esmterrain.hpp>
|
||||
|
@ -23,19 +22,6 @@ namespace ESMTerrain
|
|||
{
|
||||
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)
|
||||
{
|
||||
assert(x < ESM::Land::LAND_TEXTURE_SIZE);
|
||||
|
@ -48,7 +34,11 @@ namespace ESMTerrain
|
|||
if (data == nullptr)
|
||||
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
|
||||
}
|
||||
|
||||
// Returns a position that can be used to look up a land texture, while taking their offset into account
|
||||
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)
|
||||
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;
|
||||
const int landSize = data->getLandSize();
|
||||
|
||||
// Mostly lifted from Ogre::Terrain::getHeightAtTerrainPosition
|
||||
|
||||
// Normalized position in the cell
|
||||
|
@ -544,10 +516,10 @@ namespace ESMTerrain
|
|||
*/
|
||||
|
||||
// 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 v1(endXTS, startYTS, Storage::getVertexHeight(data, landSize, endX, startY) / cellSize);
|
||||
osg::Vec3f v2(endXTS, endYTS, Storage::getVertexHeight(data, landSize, endX, endY) / cellSize);
|
||||
osg::Vec3f v3(startXTS, endYTS, Storage::getVertexHeight(data, landSize, startX, endY) / cellSize);
|
||||
osg::Vec3f v0(startXTS, startYTS, getVertexHeight(data, startX, startY) / cellSize);
|
||||
osg::Vec3f v1(endXTS, startYTS, getVertexHeight(data, endX, startY) / cellSize);
|
||||
osg::Vec3f v2(endXTS, endYTS, getVertexHeight(data, endX, endY) / cellSize);
|
||||
osg::Vec3f v3(startXTS, endYTS, getVertexHeight(data, startX, endY) / cellSize);
|
||||
// define this plane in terrain space
|
||||
osg::Plane plane;
|
||||
// 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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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.
|
||||
float getCellWorldSize(ESM::RefId worldspace) override;
|
||||
|
||||
|
@ -131,17 +122,12 @@ namespace ESMTerrain
|
|||
|
||||
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();
|
||||
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(y < landSize);
|
||||
return data[y * landSize + x];
|
||||
return data->getHeights()[y * landSize + x];
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in a new issue