mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-06 00:55:50 +00:00
Move blendmap sampling logic into separate function
This commit is contained in:
parent
6180ba8a3e
commit
ce6ffba986
@ -362,5 +362,130 @@ namespace ESMTerrain
|
||||
Sample{ .mCellX = 0, .mCellY = 3, .mLocalX = 0, .mLocalY = 2, .mVertexX = 0, .mVertexY = 1 },
|
||||
Sample{ .mCellX = 3, .mCellY = 3, .mLocalX = 2, .mLocalY = 2, .mVertexX = 1, .mVertexY = 1 }));
|
||||
}
|
||||
|
||||
auto tie(const CellSample& v)
|
||||
{
|
||||
return std::tie(v.mCellX, v.mCellY, v.mSrcRow, v.mSrcCol, v.mDstRow, v.mDstCol);
|
||||
}
|
||||
}
|
||||
|
||||
static bool operator==(const CellSample& l, const CellSample& r)
|
||||
{
|
||||
return tie(l) == tie(r);
|
||||
}
|
||||
|
||||
static std::ostream& operator<<(std::ostream& stream, const CellSample& v)
|
||||
{
|
||||
return stream << "CellSample{.mCellX = " << v.mCellX << ", .mCellY = " << v.mCellY
|
||||
<< ", .mSrcRow = " << v.mSrcRow << ", .mSrcCol = " << v.mSrcCol << ", .mDstRow = " << v.mDstRow
|
||||
<< ", .mDstCol = " << v.mDstCol << "}";
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct CollectCellSamples
|
||||
{
|
||||
std::vector<CellSample>& mSamples;
|
||||
|
||||
void operator()(const CellSample& value) { mSamples.push_back(value); }
|
||||
};
|
||||
|
||||
TEST(ESMTerrainSampleBlendmaps, doesNotSupportNotPositiveSize)
|
||||
{
|
||||
const float size = 0;
|
||||
EXPECT_THROW(sampleBlendmaps(size, 0, 0, 0, [](auto...) {}), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(ESMTerrainSampleBlendmaps, doesNotSupportNotPositiveTextureSize)
|
||||
{
|
||||
const float size = 1;
|
||||
const int textureSize = 0;
|
||||
EXPECT_THROW(sampleBlendmaps(size, 0, 0, textureSize, [](auto...) {}), std::invalid_argument);
|
||||
}
|
||||
|
||||
TEST(ESMTerrainSampleBlendmaps, shouldDecrementBeginRow)
|
||||
{
|
||||
const float size = 0.125f;
|
||||
const float minX = 0.125f;
|
||||
const float minY = 0.125f;
|
||||
const int textureSize = 8;
|
||||
std::vector<CellSample> samples;
|
||||
sampleBlendmaps(size, minX, minY, textureSize, CollectCellSamples{ samples });
|
||||
EXPECT_THAT(samples,
|
||||
ElementsAre( //
|
||||
CellSample{ .mCellX = 0, .mCellY = 0, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 0, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = 0, .mCellY = 0, .mSrcRow = 1, .mSrcCol = 1, .mDstRow = 1, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = 0, .mCellY = 0, .mSrcRow = 0, .mSrcCol = 2, .mDstRow = 0, .mDstCol = 1 },
|
||||
CellSample{ .mCellX = 0, .mCellY = 0, .mSrcRow = 1, .mSrcCol = 2, .mDstRow = 1, .mDstCol = 1 }));
|
||||
}
|
||||
|
||||
TEST(ESMTerrainSampleBlendmaps, shouldDecrementBeginRowOverCellBorder)
|
||||
{
|
||||
const float size = 0.125f;
|
||||
const float minX = 0;
|
||||
const float minY = 0;
|
||||
const int textureSize = 8;
|
||||
std::vector<CellSample> samples;
|
||||
sampleBlendmaps(size, minX, minY, textureSize, CollectCellSamples{ samples });
|
||||
EXPECT_THAT(samples,
|
||||
ElementsAre( //
|
||||
CellSample{ .mCellX = -1, .mCellY = 0, .mSrcRow = 7, .mSrcCol = 0, .mDstRow = 0, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = 0, .mCellY = 0, .mSrcRow = 0, .mSrcCol = 0, .mDstRow = 1, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = -1, .mCellY = 0, .mSrcRow = 7, .mSrcCol = 1, .mDstRow = 0, .mDstCol = 1 },
|
||||
CellSample{ .mCellX = 0, .mCellY = 0, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 1, .mDstCol = 1 }));
|
||||
}
|
||||
|
||||
TEST(ESMTerrainSampleBlendmaps, shouldSupportNegativeCoordinates)
|
||||
{
|
||||
const float size = 0.125f;
|
||||
const float minX = -0.5f;
|
||||
const float minY = -0.5f;
|
||||
const int textureSize = 8;
|
||||
std::vector<CellSample> samples;
|
||||
sampleBlendmaps(size, minX, minY, textureSize, CollectCellSamples{ samples });
|
||||
EXPECT_THAT(samples,
|
||||
ElementsAre( //
|
||||
CellSample{ .mCellX = -1, .mCellY = -1, .mSrcRow = 3, .mSrcCol = 4, .mDstRow = 0, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = -1, .mCellY = -1, .mSrcRow = 4, .mSrcCol = 4, .mDstRow = 1, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = -1, .mCellY = -1, .mSrcRow = 3, .mSrcCol = 5, .mDstRow = 0, .mDstCol = 1 },
|
||||
CellSample{ .mCellX = -1, .mCellY = -1, .mSrcRow = 4, .mSrcCol = 5, .mDstRow = 1, .mDstCol = 1 }));
|
||||
}
|
||||
|
||||
TEST(ESMTerrainSampleBlendmaps, shouldCoverMultipleCells)
|
||||
{
|
||||
const float size = 2;
|
||||
const float minX = -1.5f;
|
||||
const float minY = -1.5f;
|
||||
const int textureSize = 2;
|
||||
std::vector<CellSample> samples;
|
||||
sampleBlendmaps(size, minX, minY, textureSize, CollectCellSamples{ samples });
|
||||
EXPECT_THAT(samples,
|
||||
ElementsAre( //
|
||||
CellSample{ .mCellX = -2, .mCellY = -2, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 0, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = -2, .mCellY = -2, .mSrcRow = 1, .mSrcCol = 1, .mDstRow = 1, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = -1, .mCellY = -2, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 2, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = -1, .mCellY = -2, .mSrcRow = 1, .mSrcCol = 1, .mDstRow = 3, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = 0, .mCellY = -2, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 4, .mDstCol = 0 },
|
||||
CellSample{ .mCellX = -2, .mCellY = -1, .mSrcRow = 0, .mSrcCol = 0, .mDstRow = 0, .mDstCol = 1 },
|
||||
CellSample{ .mCellX = -2, .mCellY = -1, .mSrcRow = 1, .mSrcCol = 0, .mDstRow = 1, .mDstCol = 1 },
|
||||
CellSample{ .mCellX = -1, .mCellY = -1, .mSrcRow = 0, .mSrcCol = 0, .mDstRow = 2, .mDstCol = 1 },
|
||||
CellSample{ .mCellX = -1, .mCellY = -1, .mSrcRow = 1, .mSrcCol = 0, .mDstRow = 3, .mDstCol = 1 },
|
||||
CellSample{ .mCellX = 0, .mCellY = -1, .mSrcRow = 0, .mSrcCol = 0, .mDstRow = 4, .mDstCol = 1 },
|
||||
CellSample{ .mCellX = -2, .mCellY = -1, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 0, .mDstCol = 2 },
|
||||
CellSample{ .mCellX = -2, .mCellY = -1, .mSrcRow = 1, .mSrcCol = 1, .mDstRow = 1, .mDstCol = 2 },
|
||||
CellSample{ .mCellX = -1, .mCellY = -1, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 2, .mDstCol = 2 },
|
||||
CellSample{ .mCellX = -1, .mCellY = -1, .mSrcRow = 1, .mSrcCol = 1, .mDstRow = 3, .mDstCol = 2 },
|
||||
CellSample{ .mCellX = 0, .mCellY = -1, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 4, .mDstCol = 2 },
|
||||
CellSample{ .mCellX = -2, .mCellY = 0, .mSrcRow = 0, .mSrcCol = 0, .mDstRow = 0, .mDstCol = 3 },
|
||||
CellSample{ .mCellX = -2, .mCellY = 0, .mSrcRow = 1, .mSrcCol = 0, .mDstRow = 1, .mDstCol = 3 },
|
||||
CellSample{ .mCellX = -1, .mCellY = 0, .mSrcRow = 0, .mSrcCol = 0, .mDstRow = 2, .mDstCol = 3 },
|
||||
CellSample{ .mCellX = -1, .mCellY = 0, .mSrcRow = 1, .mSrcCol = 0, .mDstRow = 3, .mDstCol = 3 },
|
||||
CellSample{ .mCellX = 0, .mCellY = 0, .mSrcRow = 0, .mSrcCol = 0, .mDstRow = 4, .mDstCol = 3 },
|
||||
CellSample{ .mCellX = -2, .mCellY = 0, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 0, .mDstCol = 4 },
|
||||
CellSample{ .mCellX = -2, .mCellY = 0, .mSrcRow = 1, .mSrcCol = 1, .mDstRow = 1, .mDstCol = 4 },
|
||||
CellSample{ .mCellX = -1, .mCellY = 0, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 2, .mDstCol = 4 },
|
||||
CellSample{ .mCellX = -1, .mCellY = 0, .mSrcRow = 1, .mSrcCol = 1, .mDstRow = 3, .mDstCol = 4 },
|
||||
CellSample{ .mCellX = 0, .mCellY = 0, .mSrcRow = 0, .mSrcCol = 1, .mDstRow = 4, .mDstCol = 4 }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <components/misc/mathutil.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
@ -38,6 +39,16 @@ namespace ESMTerrain
|
||||
}
|
||||
}
|
||||
|
||||
struct CellSample
|
||||
{
|
||||
int mCellX;
|
||||
int mCellY;
|
||||
std::size_t mSrcRow;
|
||||
std::size_t mSrcCol;
|
||||
std::size_t mDstRow;
|
||||
std::size_t mDstCol;
|
||||
};
|
||||
|
||||
template <class F>
|
||||
void sampleCellGridSimple(std::size_t cellSize, std::size_t sampleSize, std::size_t beginX, std::size_t beginY,
|
||||
std::size_t endX, std::size_t endY, F&& f)
|
||||
@ -115,6 +126,71 @@ namespace ESMTerrain
|
||||
baseVertY = vertY + 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline int getBlendmapSize(float size, int textureSize)
|
||||
{
|
||||
return static_cast<int>(textureSize * size) + 1;
|
||||
}
|
||||
|
||||
inline void adjustTextureCoordinates(int textureSize, int& cellX, int& cellY, int& x, int& y)
|
||||
{
|
||||
--x;
|
||||
if (x < 0)
|
||||
{
|
||||
--cellX;
|
||||
x += textureSize;
|
||||
}
|
||||
|
||||
while (x >= textureSize)
|
||||
{
|
||||
++cellX;
|
||||
x -= textureSize;
|
||||
}
|
||||
|
||||
while (y >= textureSize)
|
||||
{
|
||||
++cellY;
|
||||
y -= textureSize;
|
||||
}
|
||||
}
|
||||
|
||||
template <class F>
|
||||
void sampleBlendmaps(float size, float minX, float minY, int textureSize, F&& f)
|
||||
{
|
||||
if (size <= 0)
|
||||
throw std::invalid_argument("Invalid size for blendmap sampling: " + std::to_string(size));
|
||||
|
||||
if (textureSize <= 0)
|
||||
throw std::invalid_argument("Invalid texture size for blendmap sampling: " + std::to_string(textureSize));
|
||||
|
||||
const int beginCellX = static_cast<int>(std::floor(minX));
|
||||
const int beginCellY = static_cast<int>(std::floor(minY));
|
||||
const int beginRow = static_cast<int>((minX - beginCellX) * (textureSize + 1));
|
||||
const int beginCol = static_cast<int>((minY - beginCellY) * (textureSize + 1));
|
||||
const int blendmapSize = getBlendmapSize(size, textureSize);
|
||||
|
||||
for (int y = 0; y < blendmapSize; y++)
|
||||
{
|
||||
for (int x = 0; x < blendmapSize; x++)
|
||||
{
|
||||
int cellX = beginCellX;
|
||||
int cellY = beginCellY;
|
||||
int srcX = x + beginRow;
|
||||
int srcY = y + beginCol;
|
||||
|
||||
adjustTextureCoordinates(textureSize, cellX, cellY, srcX, srcY);
|
||||
|
||||
f(CellSample{
|
||||
.mCellX = cellX,
|
||||
.mCellY = cellY,
|
||||
.mSrcRow = static_cast<std::size_t>(srcX),
|
||||
.mSrcCol = static_cast<std::size_t>(srcY),
|
||||
.mDstRow = static_cast<std::size_t>(x),
|
||||
.mDstCol = static_cast<std::size_t>(y),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -17,6 +17,27 @@
|
||||
|
||||
namespace ESMTerrain
|
||||
{
|
||||
namespace
|
||||
{
|
||||
UniqueTextureId getTextureIdAt(const LandObject* land, std::size_t x, std::size_t y)
|
||||
{
|
||||
assert(x < ESM::Land::LAND_TEXTURE_SIZE);
|
||||
assert(y < ESM::Land::LAND_TEXTURE_SIZE);
|
||||
|
||||
if (land == nullptr)
|
||||
return { 0, 0 };
|
||||
|
||||
const ESM::LandData* data = land->getData(ESM::Land::DATA_VTEX);
|
||||
if (data == nullptr)
|
||||
return { 0, 0 };
|
||||
|
||||
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() };
|
||||
}
|
||||
}
|
||||
|
||||
class LandCache
|
||||
{
|
||||
@ -306,47 +327,6 @@ namespace ESMTerrain
|
||||
std::fill(positions.begin(), positions.end(), osg::Vec3f());
|
||||
}
|
||||
|
||||
Storage::UniqueTextureId Storage::getVtexIndexAt(
|
||||
ESM::ExteriorCellLocation cellLocation, const LandObject* land, int x, int y, LandCache& cache)
|
||||
{
|
||||
// For the first/last row/column, we need to get the texture from the neighbour cell
|
||||
// to get consistent blending at the borders
|
||||
--x;
|
||||
ESM::ExteriorCellLocation cellLocationIn = cellLocation;
|
||||
if (x < 0)
|
||||
{
|
||||
--cellLocation.mX;
|
||||
x += ESM::Land::LAND_TEXTURE_SIZE;
|
||||
}
|
||||
while (x >= ESM::Land::LAND_TEXTURE_SIZE)
|
||||
{
|
||||
++cellLocation.mX;
|
||||
x -= ESM::Land::LAND_TEXTURE_SIZE;
|
||||
}
|
||||
while (
|
||||
y >= ESM::Land::LAND_TEXTURE_SIZE) // Y appears to be wrapped from the other side because why the hell not?
|
||||
{
|
||||
++cellLocation.mY;
|
||||
y -= ESM::Land::LAND_TEXTURE_SIZE;
|
||||
}
|
||||
|
||||
if (cellLocation != cellLocationIn)
|
||||
land = getLand(cellLocation, cache);
|
||||
|
||||
assert(x < ESM::Land::LAND_TEXTURE_SIZE);
|
||||
assert(y < ESM::Land::LAND_TEXTURE_SIZE);
|
||||
|
||||
const ESM::LandData* data = land ? land->getData(ESM::Land::DATA_VTEX) : nullptr;
|
||||
if (data)
|
||||
{
|
||||
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());
|
||||
}
|
||||
return std::make_pair(0, 0);
|
||||
}
|
||||
|
||||
std::string Storage::getTextureName(UniqueTextureId id)
|
||||
{
|
||||
static constexpr char defaultTexture[] = "textures\\_land_default.dds";
|
||||
@ -371,31 +351,40 @@ namespace ESMTerrain
|
||||
void Storage::getBlendmaps(float chunkSize, const osg::Vec2f& chunkCenter, ImageVector& blendmaps,
|
||||
std::vector<Terrain::LayerInfo>& layerList, ESM::RefId worldspace)
|
||||
{
|
||||
osg::Vec2f origin = chunkCenter - osg::Vec2f(chunkSize / 2.f, chunkSize / 2.f);
|
||||
int cellX = static_cast<int>(std::floor(origin.x()));
|
||||
int cellY = static_cast<int>(std::floor(origin.y()));
|
||||
|
||||
int realTextureSize = ESM::Land::LAND_TEXTURE_SIZE + 1; // add 1 to wrap around next cell
|
||||
|
||||
int rowStart = (origin.x() - cellX) * realTextureSize;
|
||||
int colStart = (origin.y() - cellY) * realTextureSize;
|
||||
|
||||
const int blendmapSize = (realTextureSize - 1) * chunkSize + 1;
|
||||
const osg::Vec2f origin = chunkCenter - osg::Vec2f(chunkSize, chunkSize) * 0.5f;
|
||||
const int startCellX = static_cast<int>(std::floor(origin.x()));
|
||||
const int startCellY = static_cast<int>(std::floor(origin.y()));
|
||||
const std::size_t blendmapSize = getBlendmapSize(chunkSize, ESM::Land::LAND_TEXTURE_SIZE);
|
||||
// We need to upscale the blendmap 2x with nearest neighbor sampling to look like Vanilla
|
||||
const int imageScaleFactor = 2;
|
||||
const int blendmapImageSize = blendmapSize * imageScaleFactor;
|
||||
constexpr std::size_t imageScaleFactor = 2;
|
||||
const std::size_t blendmapImageSize = blendmapSize * imageScaleFactor;
|
||||
|
||||
std::vector<UniqueTextureId> textureIds(blendmapSize * blendmapSize);
|
||||
LandCache cache;
|
||||
std::map<UniqueTextureId, unsigned int> textureIndicesMap;
|
||||
ESM::ExteriorCellLocation cellLocation(cellX, cellY, worldspace);
|
||||
std::pair lastCell{ startCellX, startCellY };
|
||||
const LandObject* land = getLand(ESM::ExteriorCellLocation(startCellX, startCellY, worldspace), cache);
|
||||
|
||||
const LandObject* land = getLand(cellLocation, cache);
|
||||
|
||||
for (int y = 0; y < blendmapSize; y++)
|
||||
{
|
||||
for (int x = 0; x < blendmapSize; x++)
|
||||
const auto handleSample = [&](const CellSample& sample) {
|
||||
const std::pair cell{ sample.mCellX, sample.mCellY };
|
||||
if (lastCell != cell)
|
||||
{
|
||||
UniqueTextureId id = getVtexIndexAt(cellLocation, land, x + rowStart, y + colStart, cache);
|
||||
land = getLand(ESM::ExteriorCellLocation(sample.mCellX, sample.mCellY, worldspace), cache);
|
||||
lastCell = cell;
|
||||
}
|
||||
|
||||
textureIds[sample.mDstCol * blendmapSize + sample.mDstRow]
|
||||
= getTextureIdAt(land, sample.mSrcRow, sample.mSrcCol);
|
||||
};
|
||||
|
||||
sampleBlendmaps(chunkSize, origin.x(), origin.y(), ESM::Land::LAND_TEXTURE_SIZE, handleSample);
|
||||
|
||||
std::map<UniqueTextureId, unsigned int> textureIndicesMap;
|
||||
|
||||
for (std::size_t y = 0; y < blendmapSize; ++y)
|
||||
{
|
||||
for (std::size_t x = 0; x < blendmapSize; ++x)
|
||||
{
|
||||
const UniqueTextureId id = textureIds[y * blendmapSize + x];
|
||||
std::map<UniqueTextureId, unsigned int>::iterator found = textureIndicesMap.find(id);
|
||||
if (found == textureIndicesMap.end())
|
||||
{
|
||||
@ -417,21 +406,21 @@ namespace ESMTerrain
|
||||
if (layerIndex >= layerList.size())
|
||||
{
|
||||
osg::ref_ptr<osg::Image> image(new osg::Image);
|
||||
image->allocateImage(blendmapImageSize, blendmapImageSize, 1, GL_ALPHA, GL_UNSIGNED_BYTE);
|
||||
unsigned char* pData = image->data();
|
||||
memset(pData, 0, image->getTotalDataSize());
|
||||
blendmaps.emplace_back(image);
|
||||
layerList.emplace_back(info);
|
||||
image->allocateImage(static_cast<int>(blendmapImageSize), static_cast<int>(blendmapImageSize),
|
||||
1, GL_ALPHA, GL_UNSIGNED_BYTE);
|
||||
std::memset(image->data(), 0, image->getTotalDataSize());
|
||||
blendmaps.push_back(std::move(image));
|
||||
layerList.push_back(std::move(info));
|
||||
}
|
||||
}
|
||||
unsigned int layerIndex = found->second;
|
||||
unsigned char* pData = blendmaps[layerIndex]->data();
|
||||
int realY = (blendmapSize - y - 1) * imageScaleFactor;
|
||||
int realX = x * imageScaleFactor;
|
||||
pData[((realY + 0) * blendmapImageSize + realX + 0)] = 255;
|
||||
pData[((realY + 1) * blendmapImageSize + realX + 0)] = 255;
|
||||
pData[((realY + 0) * blendmapImageSize + realX + 1)] = 255;
|
||||
pData[((realY + 1) * blendmapImageSize + realX + 1)] = 255;
|
||||
const unsigned int layerIndex = found->second;
|
||||
unsigned char* const data = blendmaps[layerIndex]->data();
|
||||
const std::size_t realY = (blendmapSize - y - 1) * imageScaleFactor;
|
||||
const std::size_t realX = x * imageScaleFactor;
|
||||
data[((realY + 0) * blendmapImageSize + realX + 0)] = 255;
|
||||
data[((realY + 1) * blendmapImageSize + realX + 0)] = 255;
|
||||
data[((realY + 0) * blendmapImageSize + realX + 1)] = 255;
|
||||
data[((realY + 1) * blendmapImageSize + realX + 1)] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,6 +62,11 @@ namespace ESMTerrain
|
||||
ESM::LandData mData;
|
||||
};
|
||||
|
||||
// Since plugins can define new texture palettes, we need to know the plugin index too
|
||||
// in order to retrieve the correct texture name.
|
||||
// pair <texture id, plugin id>
|
||||
using UniqueTextureId = std::pair<std::uint16_t, int>;
|
||||
|
||||
/// @brief Feeds data from ESM terrain records (ESM::Land, ESM::LandTexture)
|
||||
/// into the terrain component, converting it on the fly as needed.
|
||||
class Storage : public Terrain::Storage
|
||||
@ -146,13 +151,6 @@ namespace ESMTerrain
|
||||
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
|
||||
// in order to retrieve the correct texture name.
|
||||
// pair <texture id, plugin id>
|
||||
typedef std::pair<short, short> UniqueTextureId;
|
||||
|
||||
inline UniqueTextureId getVtexIndexAt(
|
||||
ESM::ExteriorCellLocation cellLocation, const LandObject* land, int x, int y, LandCache&);
|
||||
std::string getTextureName(UniqueTextureId id);
|
||||
|
||||
std::map<std::string, Terrain::LayerInfo> mLayerInfoMap;
|
||||
|
Loading…
Reference in New Issue
Block a user