Store the min/max height in LandData

0.6.1
scrawl 8 years ago
parent 051c17a184
commit 0fc465da59

@ -516,21 +516,11 @@ namespace MWPhysics
class HeightField class HeightField
{ {
public: public:
HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, const osg::Object* holdObject) HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject)
{ {
// find the minimum and maximum heights (needed for bullet)
float minh = heights[0];
float maxh = heights[0];
for(int i = 1;i < sqrtVerts*sqrtVerts;++i)
{
float h = heights[i];
if(h > maxh) maxh = h;
if(h < minh) minh = h;
}
mShape = new btHeightfieldTerrainShape( mShape = new btHeightfieldTerrainShape(
sqrtVerts, sqrtVerts, heights, 1, sqrtVerts, sqrtVerts, heights, 1,
minh, maxh, 2, minH, maxH, 2,
PHY_FLOAT, false PHY_FLOAT, false
); );
mShape->setUseDiamondSubdivision(true); mShape->setUseDiamondSubdivision(true);
@ -539,7 +529,7 @@ namespace MWPhysics
btTransform transform(btQuaternion::getIdentity(), btTransform transform(btQuaternion::getIdentity(),
btVector3((x+0.5f) * triSize * (sqrtVerts-1), btVector3((x+0.5f) * triSize * (sqrtVerts-1),
(y+0.5f) * triSize * (sqrtVerts-1), (y+0.5f) * triSize * (sqrtVerts-1),
(maxh+minh)*0.5f)); (maxH+minH)*0.5f));
mCollisionObject = new btCollisionObject; mCollisionObject = new btCollisionObject;
mCollisionObject->setCollisionShape(mShape); mCollisionObject->setCollisionShape(mShape);
@ -1143,9 +1133,9 @@ namespace MWPhysics
return MovementSolver::traceDown(ptr, position, found->second, mCollisionWorld, maxHeight); return MovementSolver::traceDown(ptr, position, found->second, mCollisionWorld, maxHeight);
} }
void PhysicsSystem::addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, const osg::Object* holdObject) void PhysicsSystem::addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject)
{ {
HeightField *heightfield = new HeightField(heights, x, y, triSize, sqrtVerts, holdObject); HeightField *heightfield = new HeightField(heights, x, y, triSize, sqrtVerts, minH, maxH, holdObject);
mHeightFields[std::make_pair(x,y)] = heightfield; mHeightFields[std::make_pair(x,y)] = heightfield;
mCollisionWorld->addCollisionObject(heightfield->getCollisionObject(), CollisionType_HeightMap, mCollisionWorld->addCollisionObject(heightfield->getCollisionObject(), CollisionType_HeightMap,

@ -81,7 +81,7 @@ namespace MWPhysics
void updatePosition (const MWWorld::Ptr& ptr); void updatePosition (const MWWorld::Ptr& ptr);
void addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, const osg::Object* holdObject); void addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject);
void removeHeightField (int x, int y); void removeHeightField (int x, int y);

@ -278,13 +278,13 @@ namespace MWWorld
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : 0; const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : 0;
if (data) if (data)
{ {
mPhysics->addHeightField (data->mHeights, cellX, cell->getCell()->getGridY(), worldsize / (verts-1), verts, land.get()); mPhysics->addHeightField (data->mHeights, cellX, cell->getCell()->getGridY(), worldsize / (verts-1), verts, data->mMinHeight, data->mMaxHeight, land.get());
} }
else else
{ {
static std::vector<float> defaultHeight; static std::vector<float> defaultHeight;
defaultHeight.resize(verts*verts, ESM::Land::DEFAULT_HEIGHT); defaultHeight.resize(verts*verts, ESM::Land::DEFAULT_HEIGHT);
mPhysics->addHeightField (&defaultHeight[0], cell->getCell()->getGridX(), cell->getCell()->getGridY(), worldsize / (verts-1), verts, land.get()); mPhysics->addHeightField (&defaultHeight[0], cell->getCell()->getGridX(), cell->getCell()->getGridY(), worldsize / (verts-1), verts, ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get());
} }
} }

@ -203,16 +203,27 @@ namespace ESM
if (reader.isNextSub("VHGT")) { if (reader.isNextSub("VHGT")) {
VHGT vhgt; VHGT vhgt;
if (condLoad(reader, flags, target->mDataLoaded, DATA_VHGT, &vhgt, sizeof(vhgt))) { if (condLoad(reader, flags, target->mDataLoaded, DATA_VHGT, &vhgt, sizeof(vhgt))) {
target->mMinHeight = FLT_MAX;
target->mMaxHeight = -FLT_MAX;
float rowOffset = vhgt.mHeightOffset; float rowOffset = vhgt.mHeightOffset;
for (int y = 0; y < LAND_SIZE; y++) { for (int y = 0; y < LAND_SIZE; y++) {
rowOffset += vhgt.mHeightData[y * LAND_SIZE]; rowOffset += vhgt.mHeightData[y * LAND_SIZE];
target->mHeights[y * LAND_SIZE] = rowOffset * HEIGHT_SCALE; target->mHeights[y * LAND_SIZE] = rowOffset * HEIGHT_SCALE;
if (rowOffset * HEIGHT_SCALE > target->mMaxHeight)
target->mMaxHeight = rowOffset * HEIGHT_SCALE;
if (rowOffset * HEIGHT_SCALE < target->mMinHeight)
target->mMinHeight = rowOffset * HEIGHT_SCALE;
float colOffset = rowOffset; float colOffset = rowOffset;
for (int x = 1; x < LAND_SIZE; x++) { for (int x = 1; x < LAND_SIZE; x++) {
colOffset += vhgt.mHeightData[y * LAND_SIZE + x]; colOffset += vhgt.mHeightData[y * LAND_SIZE + x];
target->mHeights[x + y * LAND_SIZE] = colOffset * HEIGHT_SCALE; target->mHeights[x + y * LAND_SIZE] = colOffset * HEIGHT_SCALE;
if (colOffset * HEIGHT_SCALE > target->mMaxHeight)
target->mMaxHeight = colOffset * HEIGHT_SCALE;
if (colOffset * HEIGHT_SCALE < target->mMinHeight)
target->mMinHeight = colOffset * HEIGHT_SCALE;
} }
} }
target->mUnk1 = vhgt.mUnk1; target->mUnk1 = vhgt.mUnk1;

@ -87,6 +87,8 @@ struct Land
float mHeightOffset; float mHeightOffset;
// Height in world space for each vertex // Height in world space for each vertex
float mHeights[LAND_NUM_VERTS]; float mHeights[LAND_NUM_VERTS];
float mMinHeight;
float mMaxHeight;
// 24-bit normals, these aren't always correct though. Edge and corner normals may be garbage. // 24-bit normals, these aren't always correct though. Edge and corner normals may be garbage.
VNML mNormals[LAND_NUM_VERTS * 3]; VNML mNormals[LAND_NUM_VERTS * 3];

@ -65,8 +65,6 @@ namespace ESMTerrain
{ {
assert (size <= 1 && "Storage::getMinMaxHeights, chunk size should be <= 1 cell"); assert (size <= 1 && "Storage::getMinMaxHeights, chunk size should be <= 1 cell");
/// \todo investigate if min/max heights should be stored at load time in ESM::Land instead
osg::Vec2f origin = center - osg::Vec2f(size/2.f, size/2.f); osg::Vec2f origin = center - osg::Vec2f(size/2.f, size/2.f);
int cellX = static_cast<int>(std::floor(origin.x())); int cellX = static_cast<int>(std::floor(origin.x()));

Loading…
Cancel
Save