mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-16 15:29:55 +00:00
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.
This commit is contained in:
parent
d6613d3677
commit
7c5a590890
6 changed files with 38 additions and 20 deletions
|
@ -1,6 +1,8 @@
|
||||||
#include "heightfield.hpp"
|
#include "heightfield.hpp"
|
||||||
#include "mtphysics.hpp"
|
#include "mtphysics.hpp"
|
||||||
|
|
||||||
|
#include <components/bullethelpers/heightfield.hpp>
|
||||||
|
|
||||||
#include <osg/Object>
|
#include <osg/Object>
|
||||||
|
|
||||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||||
|
@ -19,17 +21,17 @@
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
template <class T>
|
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>>
|
-> std::enable_if_t<std::is_same<btScalar, T>::value, std::vector<btScalar>>
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
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>>
|
-> 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>
|
template <class T>
|
||||||
|
@ -50,16 +52,17 @@ namespace
|
||||||
|
|
||||||
namespace MWPhysics
|
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)
|
: mHoldObject(holdObject)
|
||||||
#if BT_BULLET_VERSION < 310
|
#if BT_BULLET_VERSION < 310
|
||||||
, mHeights(makeHeights(heights, sqrtVerts))
|
, mHeights(makeHeights(heights, verts))
|
||||||
#endif
|
#endif
|
||||||
, mTaskScheduler(scheduler)
|
, mTaskScheduler(scheduler)
|
||||||
{
|
{
|
||||||
#if BT_BULLET_VERSION < 310
|
#if BT_BULLET_VERSION < 310
|
||||||
mShape = std::make_unique<btHeightfieldTerrainShape>(
|
mShape = std::make_unique<btHeightfieldTerrainShape>(
|
||||||
sqrtVerts, sqrtVerts,
|
verts, verts,
|
||||||
getHeights(heights, mHeights),
|
getHeights(heights, mHeights),
|
||||||
1,
|
1,
|
||||||
minH, maxH, 2,
|
minH, maxH, 2,
|
||||||
|
@ -67,10 +70,12 @@ namespace MWPhysics
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
mShape = std::make_unique<btHeightfieldTerrainShape>(
|
mShape = std::make_unique<btHeightfieldTerrainShape>(
|
||||||
sqrtVerts, sqrtVerts, heights, minH, maxH, 2, false);
|
verts, verts, heights, minH, maxH, 2, false);
|
||||||
#endif
|
#endif
|
||||||
mShape->setUseDiamondSubdivision(true);
|
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
|
#if BT_BULLET_VERSION >= 289
|
||||||
// Accelerates some collision tests.
|
// Accelerates some collision tests.
|
||||||
|
@ -81,10 +86,8 @@ namespace MWPhysics
|
||||||
mShape->buildAccelerator();
|
mShape->buildAccelerator();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
btTransform transform(btQuaternion::getIdentity(),
|
const btTransform transform(btQuaternion::getIdentity(),
|
||||||
btVector3((x+0.5f) * triSize * (sqrtVerts-1),
|
BulletHelpers::getHeightfieldShift(x, y, size, minH, maxH));
|
||||||
(y+0.5f) * triSize * (sqrtVerts-1),
|
|
||||||
(maxH+minH)*0.5f));
|
|
||||||
|
|
||||||
mCollisionObject = std::make_unique<btCollisionObject>();
|
mCollisionObject = std::make_unique<btCollisionObject>();
|
||||||
mCollisionObject->setCollisionShape(mShape.get());
|
mCollisionObject->setCollisionShape(mShape.get());
|
||||||
|
|
|
@ -23,7 +23,8 @@ namespace MWPhysics
|
||||||
class HeightField
|
class HeightField
|
||||||
{
|
{
|
||||||
public:
|
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();
|
~HeightField();
|
||||||
|
|
||||||
btCollisionObject* getCollisionObject();
|
btCollisionObject* getCollisionObject();
|
||||||
|
|
|
@ -472,9 +472,9 @@ namespace MWPhysics
|
||||||
return MovementSolver::traceDown(ptr, position, found->second.get(), mCollisionWorld.get(), maxHeight);
|
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)
|
void PhysicsSystem::removeHeightField (int x, int y)
|
||||||
|
|
|
@ -150,7 +150,7 @@ namespace MWPhysics
|
||||||
void updateRotation (const MWWorld::Ptr& ptr, osg::Quat rotate);
|
void updateRotation (const MWWorld::Ptr& ptr, osg::Quat rotate);
|
||||||
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, 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);
|
void removeHeightField (int x, int y);
|
||||||
|
|
||||||
|
|
|
@ -383,17 +383,17 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
osg::ref_ptr<const ESMTerrain::LandObject> land = mRendering.getLandManager()->getLand(cellX, cellY);
|
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 ESM::Land::LandData* data = land ? land->getData(ESM::Land::DATA_VHGT) : nullptr;
|
||||||
const float verts = ESM::Land::LAND_SIZE;
|
const int verts = ESM::Land::LAND_SIZE;
|
||||||
const float worldsize = ESM::Land::REAL_SIZE;
|
const int worldsize = ESM::Land::REAL_SIZE;
|
||||||
if (data)
|
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
|
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], 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))
|
if (const auto heightField = mPhysics->getHeightField(cellX, cellY))
|
||||||
{
|
{
|
||||||
|
|
14
components/bullethelpers/heightfield.hpp
Normal file
14
components/bullethelpers/heightfield.hpp
Normal file
|
@ -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…
Reference in a new issue