Fixes bug in terrain loading + collision heightmap works

although terrain rendering is 100% broken right now
macos_ci
florent.teppe 2 years ago
parent c35c7b3640
commit d0211acf9e

@ -767,7 +767,14 @@ namespace MWRender
if (!enable)
mWater->setCullCallback(nullptr);
else
mTerrain = getWorldspaceTerrain(worldspace);
{
Terrain::World* newTerrain = getWorldspaceTerrain(worldspace);
if (newTerrain != mTerrain)
{
mTerrain->enable(false);
mTerrain = newTerrain;
}
}
mTerrain->enable(enable);
}

@ -386,7 +386,6 @@ namespace MWWorld
{
auto visitorRec = [this](ESM4::Reader& reader) { return ESMStoreImp::readRecord(reader, *this); };
ESM4::ReaderUtils::readAll(reader, visitorRec, [](ESM4::Reader&) {});
getWritable<ESM4::Land>().updateLandPositions(get<ESM4::Cell>());
}
void ESMStore::setIdType(const ESM::RefId& id, ESM::RecNameInts type)
@ -449,6 +448,7 @@ namespace MWWorld
getWritable<ESM::Skill>().setUp();
getWritable<ESM::MagicEffect>().setUp();
getWritable<ESM::Attribute>().setUp();
getWritable<ESM4::Land>().updateLandPositions(get<ESM4::Cell>());
getWritable<ESM4::Reference>().preprocessReferences(get<ESM4::Cell>());
}

@ -398,8 +398,9 @@ namespace MWWorld
{
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellIndex);
const ESM::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
const int verts = data->getLandSize();
const int worldsize = data->getSize();
const int verts = ESM::getLandSize(worldspace);
const int worldsize = ESM::getCellSize(worldspace);
if (data)
{
mPhysics->addHeightField(data->getHeights().data(), cellX, cellY, worldsize, verts,

@ -1194,12 +1194,12 @@ namespace MWWorld
void Store<ESM4::Land>::updateLandPositions(const Store<ESM4::Cell>& cells)
{
for (auto it : mStatic)
for (auto& it : mStatic)
{
const ESM4::Cell* cell = cells.find(it.second.mCell);
mLands[cell->getExteriorCellLocation()] = &it.second;
}
for (auto it : mDynamic)
for (auto& it : mDynamic)
{
const ESM4::Cell* cell = cells.find(it.second.mCell);
mLands[cell->getExteriorCellLocation()] = &it.second;

@ -1,4 +1,6 @@
#include "util.hpp"
#include <components/esm3/loadland.hpp>
#include <components/esm4/loadland.hpp>
osg::Vec2 ESM::indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool centre)
{
@ -14,3 +16,8 @@ osg::Vec2 ESM::indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool
}
return osg::Vec2(x, y);
}
int ESM::getLandSize(ESM::RefId worldspaceId)
{
return isEsm4Ext(worldspaceId) ? ESM4::Land::VERTS_PER_SIDE : ESM::Land::LAND_SIZE;
}

@ -89,6 +89,9 @@ namespace ESM
return isEsm4Ext(worldspaceId) ? Constants::ESM4CellSizeInUnits : Constants::CellSizeInUnits;
}
// Vertex count of a side of a land record
int getLandSize(ESM::RefId worldspaceId);
inline ESM::ExteriorCellLocation positionToExteriorCellLocation(
float x, float y, ESM::RefId worldspaceId = ESM::Cell::sDefaultWorldspaceId)
{

@ -76,12 +76,12 @@ namespace ESMTerrain
int cellY = static_cast<int>(std::floor(origin.y()));
osg::ref_ptr<const LandObject> land = getLand(ESM::ExteriorCellLocation(cellX, cellY, worldspace));
const ESM::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
const int landSize = ESM::getLandSize(worldspace);
int startRow = (origin.x() - cellX) * landSize;
int startColumn = (origin.y() - cellY) * landSize;
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;
int endRow = startRow + size * (landSize - 1) + 1;
int endColumn = startColumn + size * (landSize - 1) + 1;
if (data)
{
@ -91,7 +91,7 @@ namespace ESMTerrain
{
for (int col = startColumn; col < endColumn; ++col)
{
float h = data->getHeights()[col * data->getLandSize() + row];
float h = data->getHeights()[col * landSize + row];
if (h > max)
max = h;
if (h < min)
@ -112,7 +112,7 @@ namespace ESMTerrain
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;
const int landSize = ESM::getLandSize(cellLocation.mWorldspace);
while (col >= landSize - 1)
{
@ -163,7 +163,7 @@ namespace ESMTerrain
{
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;
const int landSize = ESM::getLandSize(cellLocation.mWorldspace);
if (col == landSize - 1)
{
@ -201,8 +201,9 @@ namespace ESMTerrain
int startCellX = static_cast<int>(std::floor(origin.x()));
int startCellY = static_cast<int>(std::floor(origin.y()));
const int LandSize = ESM::getLandSize(worldspace);
size_t numVerts = static_cast<size_t>(size * (ESM::Land::LAND_SIZE - 1) / increment + 1);
size_t numVerts = static_cast<size_t>(size * (LandSize - 1) / increment + 1);
positions->resize(numVerts * numVerts);
normals->resize(numVerts * numVerts);
@ -229,7 +230,6 @@ namespace ESMTerrain
const ESM::LandData* heightData = nullptr;
const ESM::LandData* normalData = nullptr;
const ESM::LandData* colourData = nullptr;
const int LandSize = land ? land->getLandSize() : ESM::Land::LAND_SIZE;
const int LandSizeInUnits = land ? land->getRealSize() : Constants::CellSizeInUnits;
if (land)
{
@ -615,14 +615,14 @@ namespace ESMTerrain
return info;
}
float Storage::getCellWorldSize()
float Storage::getCellWorldSize(ESM::RefId worldspace)
{
return static_cast<float>(ESM::Land::REAL_SIZE);
return static_cast<float>(ESM::getCellSize(worldspace));
}
int Storage::getCellVertices()
int Storage::getCellVertices(ESM::RefId worldspace)
{
return ESM::Land::LAND_SIZE;
return ESM::getLandSize(worldspace);
}
int Storage::getBlendmapScale(float chunkSize)

@ -113,10 +113,10 @@ namespace ESMTerrain
float getHeightAt(const osg::Vec3f& worldPos, ESM::RefId worldspace) override;
/// Get the transformation factor for mapping cell units to world units.
float getCellWorldSize() override;
float getCellWorldSize(ESM::RefId worldspace) override;
/// Get the number of vertices on one side for each cell. Should be (power of two)+1
int getCellVertices() override;
int getCellVertices(ESM::RefId worldspace) override;
int getBlendmapScale(float chunkSize) override;

@ -234,21 +234,27 @@ void ESM4::Land::load(ESM4::Reader& reader)
if (!missing)
mDataTypes |= LAND_VTEX;
mMinHeight = -200000.f;
mMaxHeight = 200000.f;
mMinHeight = std::numeric_limits<float>::max();
mMaxHeight = std::numeric_limits<float>::lowest();
float row_offset = mHeightMap.heightOffset;
for (int y = 0; y < VERTS_PER_SIDE; y++)
{
row_offset += mHeightMap.gradientData[y * VERTS_PER_SIDE];
mHeights[y * VERTS_PER_SIDE] = row_offset * HEIGHT_SCALE;
const float heightY = row_offset * HEIGHT_SCALE;
mHeights[y * VERTS_PER_SIDE] = heightY;
mMinHeight = std::min(mMinHeight, heightY);
mMaxHeight = std::max(mMaxHeight, heightY);
float colOffset = row_offset;
for (int x = 1; x < VERTS_PER_SIDE; x++)
{
colOffset += mHeightMap.gradientData[y * VERTS_PER_SIDE + x];
mHeights[x + y * VERTS_PER_SIDE] = colOffset * HEIGHT_SCALE;
const float heightX = colOffset * HEIGHT_SCALE;
mMinHeight = std::min(mMinHeight, heightX);
mMaxHeight = std::max(mMaxHeight, heightX);
mHeights[x + y * VERTS_PER_SIDE] = heightX;
}
}
}

@ -27,10 +27,10 @@
#include "loadwrld.hpp"
#include <stdexcept>
//#include <iostream> // FIXME: debug only
// #include <iostream> // FIXME: debug only
#include "reader.hpp"
//#include "writer.hpp"
// #include "writer.hpp"
void ESM4::World::load(ESM4::Reader& reader)
{

@ -250,7 +250,7 @@ namespace Terrain
if (chunkSize <= 1.f)
geometry->setLightListCallback(new SceneUtil::LightListCallback);
unsigned int numVerts = (mStorage->getCellVertices() - 1) * chunkSize / (1 << lod) + 1;
unsigned int numVerts = (mStorage->getCellVertices(mWorldspace) - 1) * chunkSize / (1 << lod) + 1;
geometry->addPrimitiveSet(mBufferCache.getIndexBuffer(numVerts, lodFlags));
@ -300,7 +300,7 @@ namespace Terrain
}
}
geometry->setupWaterBoundingBox(-1, chunkSize * mStorage->getCellWorldSize() / numVerts);
geometry->setupWaterBoundingBox(-1, chunkSize * mStorage->getCellWorldSize(mWorldspace) / numVerts);
if (!templateGeometry && compile && mSceneManager->getIncrementalCompileOperation())
{

@ -145,7 +145,7 @@ namespace Terrain
addChildren(mRootNode);
mRootNode->initNeighbours();
float cellWorldSize = mStorage->getCellWorldSize();
float cellWorldSize = mStorage->getCellWorldSize(mWorldspace);
mRootNode->setInitialBound(
osg::BoundingSphere(osg::BoundingBox(osg::Vec3(mMinX * cellWorldSize, mMinY * cellWorldSize, 0),
osg::Vec3(mMaxX * cellWorldSize, mMaxY * cellWorldSize, 0))));
@ -218,7 +218,7 @@ namespace Terrain
// height data here.
constexpr float minZ = -std::numeric_limits<float>::max();
constexpr float maxZ = std::numeric_limits<float>::max();
float cellWorldSize = mStorage->getCellWorldSize();
float cellWorldSize = mStorage->getCellWorldSize(mWorldspace);
osg::BoundingBox boundingBox(
osg::Vec3f((center.x() - halfSize) * cellWorldSize, (center.y() - halfSize) * cellWorldSize, minZ),
osg::Vec3f((center.x() + halfSize) * cellWorldSize, (center.y() + halfSize) * cellWorldSize, maxZ));
@ -475,7 +475,7 @@ namespace Terrain
mRootNode->traverseNodes(vd, viewPoint, &lodCallback);
}
const float cellWorldSize = mStorage->getCellWorldSize();
const float cellWorldSize = ESM::getLandSize(mWorldspace);
for (unsigned int i = 0; i < vd->getNumEntries(); ++i)
{
@ -486,7 +486,7 @@ namespace Terrain
if (mHeightCullCallback && isCullVisitor)
updateWaterCullingView(mHeightCullCallback, vd, static_cast<osgUtil::CullVisitor*>(&nv),
mStorage->getCellWorldSize(), !isGridEmpty());
mStorage->getCellWorldSize(mWorldspace), !isGridEmpty());
vd->resetChanged();
@ -534,7 +534,7 @@ namespace Terrain
std::atomic<bool>& abort, Loading::Reporter& reporter)
{
ensureQuadTreeBuilt();
const float cellWorldSize = mStorage->getCellWorldSize();
const float cellWorldSize = mStorage->getCellWorldSize(mWorldspace);
ViewData* vd = static_cast<ViewData*>(view);
vd->setViewPoint(viewPoint);

@ -84,10 +84,10 @@ namespace Terrain
virtual float getHeightAt(const osg::Vec3f& worldPos, ESM::RefId worldspace) = 0;
/// Get the transformation factor for mapping cell units to world units.
virtual float getCellWorldSize() = 0;
virtual float getCellWorldSize(ESM::RefId worldspace) = 0;
/// Get the number of vertices on one side for each cell. Should be (power of two)+1
virtual int getCellVertices() = 0;
virtual int getCellVertices(ESM::RefId worldspace) = 0;
virtual int getBlendmapScale(float chunkSize) = 0;
};

@ -74,7 +74,7 @@ namespace Terrain
if (!node)
return nullptr;
const float cellWorldSize = mStorage->getCellWorldSize();
const float cellWorldSize = mStorage->getCellWorldSize(mWorldspace);
osg::ref_ptr<SceneUtil::PositionAttitudeTransform> pat = new SceneUtil::PositionAttitudeTransform;
pat->setPosition(osg::Vec3f(chunkCenter.x() * cellWorldSize, chunkCenter.y() * cellWorldSize, 0.f));
pat->addChild(node);

Loading…
Cancel
Save