Replace float type for arguments to create heightfield with int

To reduce amount of computations on the caller side and restrict possible
values.

* verts can't be non-int because it's a number of things.
* worldsize is initially defined as int by ESM::Land::REAL_SIZE.
* Put function to calculate heightfied shift into components to be able to
  reuse by other binaries.
pull/3174/head
elsid 3 years ago
parent d6613d3677
commit 7c5a590890
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40

@ -1,6 +1,8 @@
#include "heightfield.hpp"
#include "mtphysics.hpp"
#include <components/bullethelpers/heightfield.hpp>
#include <osg/Object>
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
@ -19,17 +21,17 @@
namespace
{
template <class T>
auto makeHeights(const T* heights, float sqrtVerts)
auto makeHeights(const T* heights, int verts)
-> std::enable_if_t<std::is_same<btScalar, T>::value, std::vector<btScalar>>
{
return {};
}
template <class T>
auto makeHeights(const T* heights, float sqrtVerts)
auto makeHeights(const T* heights, int verts)
-> std::enable_if_t<!std::is_same<btScalar, T>::value, std::vector<btScalar>>
{
return std::vector<btScalar>(heights, heights + static_cast<std::ptrdiff_t>(sqrtVerts * sqrtVerts));
return std::vector<btScalar>(heights, heights + static_cast<std::ptrdiff_t>(verts * verts));
}
template <class T>
@ -50,16 +52,17 @@ namespace
namespace MWPhysics
{
HeightField::HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject, PhysicsTaskScheduler* scheduler)
HeightField::HeightField(const float* heights, int x, int y, int size, int verts, float minH, float maxH,
const osg::Object* holdObject, PhysicsTaskScheduler* scheduler)
: mHoldObject(holdObject)
#if BT_BULLET_VERSION < 310
, mHeights(makeHeights(heights, sqrtVerts))
, mHeights(makeHeights(heights, verts))
#endif
, mTaskScheduler(scheduler)
{
#if BT_BULLET_VERSION < 310
mShape = std::make_unique<btHeightfieldTerrainShape>(
sqrtVerts, sqrtVerts,
verts, verts,
getHeights(heights, mHeights),
1,
minH, maxH, 2,
@ -67,10 +70,12 @@ namespace MWPhysics
);
#else
mShape = std::make_unique<btHeightfieldTerrainShape>(
sqrtVerts, sqrtVerts, heights, minH, maxH, 2, false);
verts, verts, heights, minH, maxH, 2, false);
#endif
mShape->setUseDiamondSubdivision(true);
mShape->setLocalScaling(btVector3(triSize, triSize, 1));
const float scaling = static_cast<float>(size) / static_cast<float>(verts - 1);
mShape->setLocalScaling(btVector3(scaling, scaling, 1));
#if BT_BULLET_VERSION >= 289
// Accelerates some collision tests.
@ -81,10 +86,8 @@ namespace MWPhysics
mShape->buildAccelerator();
#endif
btTransform transform(btQuaternion::getIdentity(),
btVector3((x+0.5f) * triSize * (sqrtVerts-1),
(y+0.5f) * triSize * (sqrtVerts-1),
(maxH+minH)*0.5f));
const btTransform transform(btQuaternion::getIdentity(),
BulletHelpers::getHeightfieldShift(x, y, size, minH, maxH));
mCollisionObject = std::make_unique<btCollisionObject>();
mCollisionObject->setCollisionShape(mShape.get());

@ -23,7 +23,8 @@ namespace MWPhysics
class HeightField
{
public:
HeightField(const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject, PhysicsTaskScheduler* scheduler);
HeightField(const float* heights, int x, int y, int size, int verts, float minH, float maxH,
const osg::Object* holdObject, PhysicsTaskScheduler* scheduler);
~HeightField();
btCollisionObject* getCollisionObject();

@ -472,9 +472,9 @@ namespace MWPhysics
return MovementSolver::traceDown(ptr, position, found->second.get(), mCollisionWorld.get(), maxHeight);
}
void PhysicsSystem::addHeightField (const float* heights, int x, int y, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject)
void PhysicsSystem::addHeightField(const float* heights, int x, int y, int size, int verts, float minH, float maxH, const osg::Object* holdObject)
{
mHeightFields[std::make_pair(x,y)] = std::make_unique<HeightField>(heights, x, y, triSize, sqrtVerts, minH, maxH, holdObject, mTaskScheduler.get());
mHeightFields[std::make_pair(x,y)] = std::make_unique<HeightField>(heights, x, y, size, verts, minH, maxH, holdObject, mTaskScheduler.get());
}
void PhysicsSystem::removeHeightField (int x, int y)

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

@ -383,17 +383,17 @@ namespace MWWorld
{
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellX, cellY);
const ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
const float verts = ESM::Land::LAND_SIZE;
const float worldsize = ESM::Land::REAL_SIZE;
const int verts = ESM::Land::LAND_SIZE;
const int worldsize = ESM::Land::REAL_SIZE;
if (data)
{
mPhysics->addHeightField (data->mHeights, cellX, cellY, worldsize / (verts-1), verts, data->mMinHeight, data->mMaxHeight, land.get());
mPhysics->addHeightField(data->mHeights, cellX, cellY, worldsize, verts, data->mMinHeight, data->mMaxHeight, land.get());
}
else
{
static std::vector<float> defaultHeight;
defaultHeight.resize(verts*verts, ESM::Land::DEFAULT_HEIGHT);
mPhysics->addHeightField (&defaultHeight[0], cellX, cellY, worldsize / (verts-1), verts, ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get());
mPhysics->addHeightField(defaultHeight.data(), cellX, cellY, worldsize, verts, ESM::Land::DEFAULT_HEIGHT, ESM::Land::DEFAULT_HEIGHT, land.get());
}
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
{

@ -0,0 +1,14 @@
#ifndef OPENMW_COMPONENTS_BULLETHELPERS_HEIGHTFIELD_H
#define OPENMW_COMPONENTS_BULLETHELPERS_HEIGHTFIELD_H
#include <LinearMath/btVector3.h>
namespace BulletHelpers
{
inline btVector3 getHeightfieldShift(int x, int y, int size, float minHeight, float maxHeight)
{
return btVector3((x + 0.5f) * size, (y + 0.5f) * size, (maxHeight + minHeight) * 0.5f);
}
}
#endif
Loading…
Cancel
Save