mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-23 12:11:36 +00:00
Revert back to less aggressive component-level changes.
This commit is contained in:
parent
69083369f8
commit
0ce971c1bb
4 changed files with 160 additions and 279 deletions
|
@ -72,173 +72,42 @@ namespace CSVRender
|
||||||
return &mAlteredHeight[inCellY*ESM::Land::LAND_SIZE + inCellX];
|
return &mAlteredHeight[inCellY*ESM::Land::LAND_SIZE + inCellX];
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainStorage::fillVertexBuffers (int lodLevel, float size, const osg::Vec2f& center,
|
|
||||||
osg::ref_ptr<osg::Vec3Array> positions,
|
|
||||||
osg::ref_ptr<osg::Vec3Array> normals,
|
|
||||||
osg::ref_ptr<osg::Vec4ubArray> colours)
|
|
||||||
{
|
|
||||||
// LOD level n means every 2^n-th vertex is kept
|
|
||||||
size_t increment = static_cast<size_t>(1) << lodLevel;
|
|
||||||
|
|
||||||
osg::Vec2f origin = center - osg::Vec2f(size/2.f, size/2.f);
|
|
||||||
|
|
||||||
int startCellX = static_cast<int>(std::floor(origin.x()));
|
|
||||||
int startCellY = static_cast<int>(std::floor(origin.y()));
|
|
||||||
|
|
||||||
size_t numVerts = static_cast<size_t>(size*(ESM::Land::LAND_SIZE - 1) / increment + 1);
|
|
||||||
|
|
||||||
positions->resize(numVerts*numVerts);
|
|
||||||
normals->resize(numVerts*numVerts);
|
|
||||||
colours->resize(numVerts*numVerts);
|
|
||||||
|
|
||||||
osg::Vec3f normal;
|
|
||||||
osg::Vec4ub color;
|
|
||||||
|
|
||||||
float vertY = 0;
|
|
||||||
float vertX = 0;
|
|
||||||
|
|
||||||
ESMTerrain::LandCache cache;
|
|
||||||
|
|
||||||
float vertY_ = 0; // of current cell corner
|
|
||||||
for (int cellY = startCellY; cellY < startCellY + std::ceil(size); ++cellY)
|
|
||||||
{
|
|
||||||
float vertX_ = 0; // of current cell corner
|
|
||||||
for (int cellX = startCellX; cellX < startCellX + std::ceil(size); ++cellX)
|
|
||||||
{
|
|
||||||
const ESMTerrain::LandObject* land = ESMTerrain::Storage::getLand(cellX, cellY, cache);
|
|
||||||
const ESM::Land::LandData *heightData = 0;
|
|
||||||
const ESM::Land::LandData *normalData = 0;
|
|
||||||
const ESM::Land::LandData *colourData = 0;
|
|
||||||
if (land)
|
|
||||||
{
|
|
||||||
heightData = land->getData(ESM::Land::DATA_VHGT);
|
|
||||||
normalData = land->getData(ESM::Land::DATA_VNML);
|
|
||||||
colourData = land->getData(ESM::Land::DATA_VCLR);
|
|
||||||
}
|
|
||||||
|
|
||||||
int rowStart = 0;
|
|
||||||
int colStart = 0;
|
|
||||||
// Skip the first row / column unless we're at a chunk edge,
|
|
||||||
// since this row / column is already contained in a previous cell
|
|
||||||
// This is only relevant if we're creating a chunk spanning multiple cells
|
|
||||||
if (vertY_ != 0)
|
|
||||||
colStart += increment;
|
|
||||||
if (vertX_ != 0)
|
|
||||||
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));
|
|
||||||
|
|
||||||
vertY = vertY_;
|
|
||||||
for (int col=colStart; col<colEnd; col += increment)
|
|
||||||
{
|
|
||||||
vertX = vertX_;
|
|
||||||
for (int row=rowStart; row<rowEnd; row += increment)
|
|
||||||
{
|
|
||||||
int srcArrayIndex = col*ESM::Land::LAND_SIZE*3+row*3;
|
|
||||||
|
|
||||||
assert(row >= 0 && row < ESM::Land::LAND_SIZE);
|
|
||||||
assert(col >= 0 && col < ESM::Land::LAND_SIZE);
|
|
||||||
|
|
||||||
assert (vertX < numVerts);
|
|
||||||
assert (vertY < numVerts);
|
|
||||||
|
|
||||||
float height = defaultHeight;
|
|
||||||
if (heightData)
|
|
||||||
height = heightData->mHeights[col*ESM::Land::LAND_SIZE + 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 + mAlteredHeight[static_cast<unsigned int>(col*ESM::Land::LAND_SIZE + row)]);
|
|
||||||
|
|
||||||
if (normalData)
|
|
||||||
{
|
|
||||||
for (int i=0; i<3; ++i)
|
|
||||||
normal[i] = normalData->mNormals[srcArrayIndex+i];
|
|
||||||
|
|
||||||
normal.normalize();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
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)
|
|
||||||
fixNormal(normal, cellX, cellY, 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))
|
|
||||||
averageNormal(normal, cellX, cellY, col, row, cache);
|
|
||||||
|
|
||||||
assert(normal.z() > 0);
|
|
||||||
|
|
||||||
(*normals)[static_cast<unsigned int>(vertX*numVerts + vertY)] = normal;
|
|
||||||
|
|
||||||
if (colourData)
|
|
||||||
{
|
|
||||||
for (int i=0; i<3; ++i)
|
|
||||||
color[i] = colourData->mColours[srcArrayIndex+i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
color.r() = 255;
|
|
||||||
color.g() = 255;
|
|
||||||
color.b() = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Highlight broken height changes
|
|
||||||
if ( ((col > 0 && row > 0) &&
|
|
||||||
((abs(heightData->mHeights[col*ESM::Land::LAND_SIZE + row] +
|
|
||||||
mAlteredHeight[static_cast<unsigned int>(col*ESM::Land::LAND_SIZE + row)] -
|
|
||||||
(heightData->mHeights[(col)*ESM::Land::LAND_SIZE + row - 1] +
|
|
||||||
mAlteredHeight[static_cast<unsigned int>((col)*ESM::Land::LAND_SIZE + row - 1)])) >= 1024 ) ||
|
|
||||||
abs(heightData->mHeights[col*ESM::Land::LAND_SIZE + row] +
|
|
||||||
mAlteredHeight[static_cast<unsigned int>(col*ESM::Land::LAND_SIZE + row)] -
|
|
||||||
(heightData->mHeights[(col - 1)*ESM::Land::LAND_SIZE + row] +
|
|
||||||
mAlteredHeight[static_cast<unsigned int>((col - 1)*ESM::Land::LAND_SIZE + row)])) >= 1024 )) ||
|
|
||||||
((col < ESM::Land::LAND_SIZE - 1 && row < ESM::Land::LAND_SIZE - 1) &&
|
|
||||||
((abs(heightData->mHeights[col*ESM::Land::LAND_SIZE + row] +
|
|
||||||
mAlteredHeight[static_cast<unsigned int>(col*ESM::Land::LAND_SIZE + row)] -
|
|
||||||
(heightData->mHeights[(col)*ESM::Land::LAND_SIZE + row + 1] +
|
|
||||||
mAlteredHeight[static_cast<unsigned int>((col)*ESM::Land::LAND_SIZE + row + 1)])) >= 1024 ) ||
|
|
||||||
abs(heightData->mHeights[col*ESM::Land::LAND_SIZE + row] +
|
|
||||||
mAlteredHeight[static_cast<unsigned int>(col*ESM::Land::LAND_SIZE + row)] -
|
|
||||||
(heightData->mHeights[(col + 1)*ESM::Land::LAND_SIZE + row] +
|
|
||||||
mAlteredHeight[static_cast<unsigned int>((col + 1)*ESM::Land::LAND_SIZE + row)])) >= 1024 )))
|
|
||||||
{
|
|
||||||
color.r() = 255;
|
|
||||||
color.g() = 0;
|
|
||||||
color.b() = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unlike normals, colors mostly connect seamlessly between cells, but not always...
|
|
||||||
if (col == ESM::Land::LAND_SIZE-1 || row == ESM::Land::LAND_SIZE-1)
|
|
||||||
fixColour(color, cellX, cellY, col, row, cache);
|
|
||||||
|
|
||||||
color.a() = 255;
|
|
||||||
|
|
||||||
(*colours)[static_cast<unsigned int>(vertX*numVerts + vertY)] = color;
|
|
||||||
|
|
||||||
++vertX;
|
|
||||||
}
|
|
||||||
++vertY;
|
|
||||||
}
|
|
||||||
vertX_ = vertX;
|
|
||||||
}
|
|
||||||
vertY_ = vertY;
|
|
||||||
|
|
||||||
assert(vertX_ == numVerts); // Ensure we covered whole area
|
|
||||||
}
|
|
||||||
assert(vertY_ == numVerts); // Ensure we covered whole area*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void TerrainStorage::getBounds(float &minX, float &maxX, float &minY, float &maxY)
|
void TerrainStorage::getBounds(float &minX, float &maxX, float &minY, float &maxY)
|
||||||
{
|
{
|
||||||
// not needed at the moment - this returns the bounds of the whole world, but we only edit individual cells
|
// not needed at the moment - this returns the bounds of the whole world, but we only edit individual cells
|
||||||
throw std::runtime_error("getBounds not implemented");
|
throw std::runtime_error("getBounds not implemented");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TerrainStorage::adjustColor(int col, int row, const ESM::Land::LandData *heightData, osg::Vec4ub& color) const
|
||||||
|
{
|
||||||
|
// Highlight broken height changes
|
||||||
|
if ( ((col > 0 && row > 0) &&
|
||||||
|
((abs(heightData->mHeights[col*ESM::Land::LAND_SIZE + row] +
|
||||||
|
mAlteredHeight[static_cast<unsigned int>(col*ESM::Land::LAND_SIZE + row)] -
|
||||||
|
(heightData->mHeights[(col)*ESM::Land::LAND_SIZE + row - 1] +
|
||||||
|
mAlteredHeight[static_cast<unsigned int>((col)*ESM::Land::LAND_SIZE + row - 1)])) >= 1024 ) ||
|
||||||
|
abs(heightData->mHeights[col*ESM::Land::LAND_SIZE + row] +
|
||||||
|
mAlteredHeight[static_cast<unsigned int>(col*ESM::Land::LAND_SIZE + row)] -
|
||||||
|
(heightData->mHeights[(col - 1)*ESM::Land::LAND_SIZE + row] +
|
||||||
|
mAlteredHeight[static_cast<unsigned int>((col - 1)*ESM::Land::LAND_SIZE + row)])) >= 1024 )) ||
|
||||||
|
((col < ESM::Land::LAND_SIZE - 1 && row < ESM::Land::LAND_SIZE - 1) &&
|
||||||
|
((abs(heightData->mHeights[col*ESM::Land::LAND_SIZE + row] +
|
||||||
|
mAlteredHeight[static_cast<unsigned int>(col*ESM::Land::LAND_SIZE + row)] -
|
||||||
|
(heightData->mHeights[(col)*ESM::Land::LAND_SIZE + row + 1] +
|
||||||
|
mAlteredHeight[static_cast<unsigned int>((col)*ESM::Land::LAND_SIZE + row + 1)])) >= 1024 ) ||
|
||||||
|
abs(heightData->mHeights[col*ESM::Land::LAND_SIZE + row] +
|
||||||
|
mAlteredHeight[static_cast<unsigned int>(col*ESM::Land::LAND_SIZE + row)] -
|
||||||
|
(heightData->mHeights[(col + 1)*ESM::Land::LAND_SIZE + row] +
|
||||||
|
mAlteredHeight[static_cast<unsigned int>((col + 1)*ESM::Land::LAND_SIZE + row)])) >= 1024 )))
|
||||||
|
{
|
||||||
|
color.r() = 255;
|
||||||
|
color.g() = 0;
|
||||||
|
color.b() = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float TerrainStorage::getAlteredHeight(int col, int row) const
|
||||||
|
{
|
||||||
|
return mAlteredHeight[static_cast<unsigned int>(col*ESM::Land::LAND_SIZE + row)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
|
|
||||||
namespace CSVRender
|
namespace CSVRender
|
||||||
{
|
{
|
||||||
class LandCache;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A bridge between the terrain component and OpenCS's terrain data storage.
|
* @brief A bridge between the terrain component and OpenCS's terrain data storage.
|
||||||
*/
|
*/
|
||||||
|
@ -30,13 +28,10 @@ namespace CSVRender
|
||||||
virtual osg::ref_ptr<const ESMTerrain::LandObject> getLand (int cellX, int cellY) override;
|
virtual osg::ref_ptr<const ESMTerrain::LandObject> getLand (int cellX, int cellY) override;
|
||||||
virtual const ESM::LandTexture* getLandTexture(int index, short plugin) override;
|
virtual const ESM::LandTexture* getLandTexture(int index, short plugin) override;
|
||||||
|
|
||||||
/// Draws temporarily altered land (transient change support)
|
|
||||||
void fillVertexBuffers (int lodLevel, float size, const osg::Vec2f& center,
|
|
||||||
osg::ref_ptr<osg::Vec3Array> positions,
|
|
||||||
osg::ref_ptr<osg::Vec3Array> normals,
|
|
||||||
osg::ref_ptr<osg::Vec4ubArray> colours) override;
|
|
||||||
|
|
||||||
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY) override;
|
virtual void getBounds(float& minX, float& maxX, float& minY, float& maxY) override;
|
||||||
|
|
||||||
|
void adjustColor(int col, int row, const ESM::Land::LandData *heightData, osg::Vec4ub& color) const override;
|
||||||
|
float getAlteredHeight(int col, int row) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,13 @@
|
||||||
namespace ESMTerrain
|
namespace ESMTerrain
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class LandCache
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::map<std::pair<int, int>, osg::ref_ptr<const LandObject> > Map;
|
||||||
|
Map mMap;
|
||||||
|
};
|
||||||
|
|
||||||
LandObject::LandObject()
|
LandObject::LandObject()
|
||||||
: mLand(nullptr)
|
: mLand(nullptr)
|
||||||
, mLoadFlags(0)
|
, mLoadFlags(0)
|
||||||
|
@ -91,6 +98,82 @@ namespace ESMTerrain
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Storage::fixNormal (osg::Vec3f& normal, int cellX, int cellY, int col, int row, LandCache& cache)
|
||||||
|
{
|
||||||
|
while (col >= ESM::Land::LAND_SIZE-1)
|
||||||
|
{
|
||||||
|
++cellY;
|
||||||
|
col -= ESM::Land::LAND_SIZE-1;
|
||||||
|
}
|
||||||
|
while (row >= ESM::Land::LAND_SIZE-1)
|
||||||
|
{
|
||||||
|
++cellX;
|
||||||
|
row -= ESM::Land::LAND_SIZE-1;
|
||||||
|
}
|
||||||
|
while (col < 0)
|
||||||
|
{
|
||||||
|
--cellY;
|
||||||
|
col += ESM::Land::LAND_SIZE-1;
|
||||||
|
}
|
||||||
|
while (row < 0)
|
||||||
|
{
|
||||||
|
--cellX;
|
||||||
|
row += ESM::Land::LAND_SIZE-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LandObject* land = getLand(cellX, cellY, cache);
|
||||||
|
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VNML) : 0;
|
||||||
|
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.normalize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
normal = osg::Vec3f(0,0,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::averageNormal(osg::Vec3f &normal, int cellX, int cellY, int col, int row, LandCache& cache)
|
||||||
|
{
|
||||||
|
osg::Vec3f n1,n2,n3,n4;
|
||||||
|
fixNormal(n1, cellX, cellY, col+1, row, cache);
|
||||||
|
fixNormal(n2, cellX, cellY, col-1, row, cache);
|
||||||
|
fixNormal(n3, cellX, cellY, col, row+1, cache);
|
||||||
|
fixNormal(n4, cellX, cellY, col, row-1, cache);
|
||||||
|
normal = (n1+n2+n3+n4);
|
||||||
|
normal.normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::fixColour (osg::Vec4ub& color, int cellX, int cellY, int col, int row, LandCache& cache)
|
||||||
|
{
|
||||||
|
if (col == ESM::Land::LAND_SIZE-1)
|
||||||
|
{
|
||||||
|
++cellY;
|
||||||
|
col = 0;
|
||||||
|
}
|
||||||
|
if (row == ESM::Land::LAND_SIZE-1)
|
||||||
|
{
|
||||||
|
++cellX;
|
||||||
|
row = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const LandObject* land = getLand(cellX, cellY, cache);
|
||||||
|
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VCLR) : 0;
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color.r() = 255;
|
||||||
|
color.g() = 255;
|
||||||
|
color.b() = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Storage::fillVertexBuffers (int lodLevel, float size, const osg::Vec2f& center,
|
void Storage::fillVertexBuffers (int lodLevel, float size, const osg::Vec2f& center,
|
||||||
osg::ref_ptr<osg::Vec3Array> positions,
|
osg::ref_ptr<osg::Vec3Array> positions,
|
||||||
osg::ref_ptr<osg::Vec3Array> normals,
|
osg::ref_ptr<osg::Vec3Array> normals,
|
||||||
|
@ -172,7 +255,7 @@ namespace ESMTerrain
|
||||||
(*positions)[static_cast<unsigned int>(vertX*numVerts + vertY)]
|
(*positions)[static_cast<unsigned int>(vertX*numVerts + vertY)]
|
||||||
= osg::Vec3f((vertX / float(numVerts - 1) - 0.5f) * size * Constants::CellSizeInUnits,
|
= osg::Vec3f((vertX / float(numVerts - 1) - 0.5f) * size * Constants::CellSizeInUnits,
|
||||||
(vertY / float(numVerts - 1) - 0.5f) * size * Constants::CellSizeInUnits,
|
(vertY / float(numVerts - 1) - 0.5f) * size * Constants::CellSizeInUnits,
|
||||||
height);
|
height + getAlteredHeight(col, row));
|
||||||
|
|
||||||
if (normalData)
|
if (normalData)
|
||||||
{
|
{
|
||||||
|
@ -208,6 +291,8 @@ namespace ESMTerrain
|
||||||
color.b() = 255;
|
color.b() = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adjustColor(col, row, heightData, color); //Does nothing by default, override in OpenMW-CS
|
||||||
|
|
||||||
// Unlike normals, colors mostly connect seamlessly between cells, but not always...
|
// 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 == ESM::Land::LAND_SIZE-1 || row == ESM::Land::LAND_SIZE-1)
|
||||||
fixColour(color, cellX, cellY, col, row, cache);
|
fixColour(color, cellX, cellY, col, row, cache);
|
||||||
|
@ -438,6 +523,27 @@ namespace ESMTerrain
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LandObject* Storage::getLand(int cellX, int cellY, LandCache& cache)
|
||||||
|
{
|
||||||
|
LandCache::Map::iterator found = cache.mMap.find(std::make_pair(cellX, cellY));
|
||||||
|
if (found != cache.mMap.end())
|
||||||
|
return found->second;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
found = cache.mMap.insert(std::make_pair(std::make_pair(cellX, cellY), getLand(cellX, cellY))).first;
|
||||||
|
return found->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::adjustColor(int col, int row, const ESM::Land::LandData *heightData, osg::Vec4ub& color) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
float Storage::getAlteredHeight(int col, int row) const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Terrain::LayerInfo Storage::getLayerInfo(const std::string& texture)
|
Terrain::LayerInfo Storage::getLayerInfo(const std::string& texture)
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mLayerInfoMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mLayerInfoMutex);
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
|
|
||||||
#include <OpenThreads/Mutex>
|
#include <OpenThreads/Mutex>
|
||||||
|
|
||||||
#include <osg/Image>
|
|
||||||
#include <osg/Plane>
|
|
||||||
|
|
||||||
#include <components/terrain/storage.hpp>
|
#include <components/terrain/storage.hpp>
|
||||||
|
|
||||||
#include <components/esm/loadland.hpp>
|
#include <components/esm/loadland.hpp>
|
||||||
|
@ -21,6 +18,8 @@ namespace VFS
|
||||||
namespace ESMTerrain
|
namespace ESMTerrain
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class LandCache;
|
||||||
|
|
||||||
/// @brief Wrapper around Land Data with reference counting. The wrapper needs to be held as long as the data is still in use
|
/// @brief Wrapper around Land Data with reference counting. The wrapper needs to be held as long as the data is still in use
|
||||||
class LandObject : public osg::Object
|
class LandObject : public osg::Object
|
||||||
{
|
{
|
||||||
|
@ -51,13 +50,6 @@ namespace ESMTerrain
|
||||||
ESM::Land::LandData mData;
|
ESM::Land::LandData mData;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LandCache
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef std::map<std::pair<int, int>, osg::ref_ptr<const LandObject> > Map;
|
|
||||||
Map mMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @brief Feeds data from ESM terrain records (ESM::Land, ESM::LandTexture)
|
/// @brief Feeds data from ESM terrain records (ESM::Land, ESM::LandTexture)
|
||||||
/// into the terrain component, converting it on the fly as needed.
|
/// into the terrain component, converting it on the fly as needed.
|
||||||
class Storage : public Terrain::Storage
|
class Storage : public Terrain::Storage
|
||||||
|
@ -117,9 +109,25 @@ namespace ESMTerrain
|
||||||
|
|
||||||
virtual int getBlendmapScale(float chunkSize);
|
virtual int getBlendmapScale(float chunkSize);
|
||||||
|
|
||||||
|
float getVertexHeight (const ESM::Land::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];
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const VFS::Manager* mVFS;
|
const VFS::Manager* mVFS;
|
||||||
|
|
||||||
|
inline void fixNormal (osg::Vec3f& normal, int cellX, int cellY, int col, int row, LandCache& cache);
|
||||||
|
inline void fixColour (osg::Vec4ub& colour, int cellX, int cellY, int col, int row, LandCache& cache);
|
||||||
|
inline void averageNormal (osg::Vec3f& normal, int cellX, int cellY, int col, int row, LandCache& cache);
|
||||||
|
|
||||||
|
inline const LandObject* getLand(int cellX, int cellY, LandCache& cache);
|
||||||
|
|
||||||
|
virtual void adjustColor(int col, int row, const ESM::Land::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
|
// Since plugins can define new texture palettes, we need to know the plugin index too
|
||||||
// in order to retrieve the correct texture name.
|
// in order to retrieve the correct texture name.
|
||||||
// pair <texture id, plugin id>
|
// pair <texture id, plugin id>
|
||||||
|
@ -139,103 +147,6 @@ namespace ESMTerrain
|
||||||
bool mAutoUseSpecularMaps;
|
bool mAutoUseSpecularMaps;
|
||||||
|
|
||||||
Terrain::LayerInfo getLayerInfo(const std::string& texture);
|
Terrain::LayerInfo getLayerInfo(const std::string& texture);
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
inline void fixNormal (osg::Vec3f& normal, int cellX, int cellY, int col, int row, LandCache& cache)
|
|
||||||
{
|
|
||||||
while (col >= ESM::Land::LAND_SIZE-1)
|
|
||||||
{
|
|
||||||
++cellY;
|
|
||||||
col -= ESM::Land::LAND_SIZE-1;
|
|
||||||
}
|
|
||||||
while (row >= ESM::Land::LAND_SIZE-1)
|
|
||||||
{
|
|
||||||
++cellX;
|
|
||||||
row -= ESM::Land::LAND_SIZE-1;
|
|
||||||
}
|
|
||||||
while (col < 0)
|
|
||||||
{
|
|
||||||
--cellY;
|
|
||||||
col += ESM::Land::LAND_SIZE-1;
|
|
||||||
}
|
|
||||||
while (row < 0)
|
|
||||||
{
|
|
||||||
--cellX;
|
|
||||||
row += ESM::Land::LAND_SIZE-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LandObject* land = getLand(cellX, cellY, cache);
|
|
||||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VNML) : 0;
|
|
||||||
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.normalize();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
normal = osg::Vec3f(0,0,1);
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void fixColour (osg::Vec4ub& color, int cellX, int cellY, int col, int row, LandCache& cache)
|
|
||||||
{
|
|
||||||
if (col == ESM::Land::LAND_SIZE-1)
|
|
||||||
{
|
|
||||||
++cellY;
|
|
||||||
col = 0;
|
|
||||||
}
|
|
||||||
if (row == ESM::Land::LAND_SIZE-1)
|
|
||||||
{
|
|
||||||
++cellX;
|
|
||||||
row = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const LandObject* land = getLand(cellX, cellY, cache);
|
|
||||||
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VCLR) : 0;
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
color.r() = 255;
|
|
||||||
color.g() = 255;
|
|
||||||
color.b() = 255;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline void averageNormal (osg::Vec3f& normal, int cellX, int cellY, int col, int row, LandCache& cache)
|
|
||||||
{
|
|
||||||
osg::Vec3f n1,n2,n3,n4;
|
|
||||||
fixNormal(n1, cellX, cellY, col+1, row, cache);
|
|
||||||
fixNormal(n2, cellX, cellY, col-1, row, cache);
|
|
||||||
fixNormal(n3, cellX, cellY, col, row+1, cache);
|
|
||||||
fixNormal(n4, cellX, cellY, col, row-1, cache);
|
|
||||||
normal = (n1+n2+n3+n4);
|
|
||||||
normal.normalize();
|
|
||||||
};
|
|
||||||
|
|
||||||
inline float getVertexHeight (const ESM::Land::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];
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const LandObject* getLand(int cellX, int cellY, LandCache& cache)
|
|
||||||
{
|
|
||||||
LandCache::Map::iterator found = cache.mMap.find(std::make_pair(cellX, cellY));
|
|
||||||
if (found != cache.mMap.end())
|
|
||||||
return found->second;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
found = cache.mMap.insert(std::make_pair(std::make_pair(cellX, cellY), getLand(cellX, cellY))).first;
|
|
||||||
return found->second;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue