2018-03-18 11:32:45 +00:00
|
|
|
#include "heightfield.hpp"
|
2020-12-25 17:20:42 +00:00
|
|
|
#include "mtphysics.hpp"
|
2018-03-18 11:32:45 +00:00
|
|
|
|
2021-10-11 17:23:08 +00:00
|
|
|
#include <components/bullethelpers/heightfield.hpp>
|
|
|
|
|
2018-03-18 11:32:45 +00:00
|
|
|
#include <osg/Object>
|
|
|
|
|
|
|
|
#include <BulletCollision/CollisionDispatch/btCollisionObject.h>
|
|
|
|
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
|
|
|
|
|
|
|
#include <LinearMath/btTransform.h>
|
|
|
|
|
2018-11-25 08:46:09 +00:00
|
|
|
#include <type_traits>
|
|
|
|
|
2021-03-11 23:27:42 +00:00
|
|
|
#if BT_BULLET_VERSION < 310
|
|
|
|
// Older Bullet versions only support `btScalar` heightfields.
|
|
|
|
// Our heightfield data is `float`.
|
|
|
|
//
|
|
|
|
// These functions handle conversion from `float` to `double` when
|
|
|
|
// `btScalar` is `double` (`BT_USE_DOUBLE_PRECISION`).
|
2018-11-25 08:46:09 +00:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
template <class T>
|
2021-10-11 17:23:08 +00:00
|
|
|
auto makeHeights(const T* heights, int verts)
|
2018-11-25 08:46:09 +00:00
|
|
|
-> std::enable_if_t<std::is_same<btScalar, T>::value, std::vector<btScalar>>
|
|
|
|
{
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
2021-10-11 17:23:08 +00:00
|
|
|
auto makeHeights(const T* heights, int verts)
|
2018-11-25 08:46:09 +00:00
|
|
|
-> std::enable_if_t<!std::is_same<btScalar, T>::value, std::vector<btScalar>>
|
|
|
|
{
|
2021-10-11 17:23:08 +00:00
|
|
|
return std::vector<btScalar>(heights, heights + static_cast<std::ptrdiff_t>(verts * verts));
|
2018-11-25 08:46:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
auto getHeights(const T* floatHeights, const std::vector<btScalar>&)
|
|
|
|
-> std::enable_if_t<std::is_same<btScalar, T>::value, const btScalar*>
|
|
|
|
{
|
|
|
|
return floatHeights;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
auto getHeights(const T*, const std::vector<btScalar>& btScalarHeights)
|
|
|
|
-> std::enable_if_t<!std::is_same<btScalar, T>::value, const btScalar*>
|
|
|
|
{
|
|
|
|
return btScalarHeights.data();
|
|
|
|
}
|
|
|
|
}
|
2021-03-11 23:27:42 +00:00
|
|
|
#endif
|
2018-11-25 08:46:09 +00:00
|
|
|
|
2018-03-18 11:32:45 +00:00
|
|
|
namespace MWPhysics
|
|
|
|
{
|
2021-10-11 17:23:08 +00:00
|
|
|
HeightField::HeightField(const float* heights, int x, int y, int size, int verts, float minH, float maxH,
|
|
|
|
const osg::Object* holdObject, PhysicsTaskScheduler* scheduler)
|
2020-12-25 17:20:42 +00:00
|
|
|
: mHoldObject(holdObject)
|
2021-03-11 23:27:42 +00:00
|
|
|
#if BT_BULLET_VERSION < 310
|
2021-10-11 17:23:08 +00:00
|
|
|
, mHeights(makeHeights(heights, verts))
|
2021-03-11 23:27:42 +00:00
|
|
|
#endif
|
2020-12-25 17:20:42 +00:00
|
|
|
, mTaskScheduler(scheduler)
|
2018-03-18 11:32:45 +00:00
|
|
|
{
|
2021-03-11 23:27:42 +00:00
|
|
|
#if BT_BULLET_VERSION < 310
|
2020-12-25 17:20:42 +00:00
|
|
|
mShape = std::make_unique<btHeightfieldTerrainShape>(
|
2018-11-25 08:46:09 +00:00
|
|
|
verts, verts, getHeights(heights, mHeights), 1, minH, maxH, 2, PHY_FLOAT, false);
|
2021-03-11 23:27:42 +00:00
|
|
|
#else
|
|
|
|
mShape = std::make_unique<btHeightfieldTerrainShape>(verts, verts, heights, minH, maxH, 2, false);
|
|
|
|
#endif
|
2018-03-18 11:32:45 +00:00
|
|
|
mShape->setUseDiamondSubdivision(true);
|
2021-10-11 17:23:08 +00:00
|
|
|
|
|
|
|
const float scaling = static_cast<float>(size) / static_cast<float>(verts - 1);
|
|
|
|
mShape->setLocalScaling(btVector3(scaling, scaling, 1));
|
2018-03-18 11:32:45 +00:00
|
|
|
|
2021-03-01 08:12:43 +00:00
|
|
|
#if BT_BULLET_VERSION >= 289
|
|
|
|
// Accelerates some collision tests.
|
2021-02-26 09:54:02 +00:00
|
|
|
//
|
2021-03-01 08:12:43 +00:00
|
|
|
// Note: The accelerator data structure in Bullet is only used
|
|
|
|
// in some operations. This could be improved, see:
|
|
|
|
// https://github.com/bulletphysics/bullet3/issues/3276
|
2021-02-26 09:54:02 +00:00
|
|
|
mShape->buildAccelerator();
|
2021-03-01 08:12:43 +00:00
|
|
|
#endif
|
2021-02-26 09:54:02 +00:00
|
|
|
|
2021-10-11 17:23:08 +00:00
|
|
|
const btTransform transform(
|
|
|
|
btQuaternion::getIdentity(), BulletHelpers::getHeightfieldShift(x, y, size, minH, maxH));
|
2018-03-18 11:32:45 +00:00
|
|
|
|
2020-12-25 17:20:42 +00:00
|
|
|
mCollisionObject = std::make_unique<btCollisionObject>();
|
|
|
|
mCollisionObject->setCollisionShape(mShape.get());
|
2018-03-18 11:32:45 +00:00
|
|
|
mCollisionObject->setWorldTransform(transform);
|
2020-12-25 17:20:42 +00:00
|
|
|
mTaskScheduler->addCollisionObject(
|
|
|
|
mCollisionObject.get(), CollisionType_HeightMap, CollisionType_Actor | CollisionType_Projectile);
|
2018-03-18 11:32:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
HeightField::~HeightField()
|
|
|
|
{
|
2020-12-25 17:20:42 +00:00
|
|
|
mTaskScheduler->removeCollisionObject(mCollisionObject.get());
|
2018-03-18 11:32:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
btCollisionObject* HeightField::getCollisionObject()
|
|
|
|
{
|
2020-12-25 17:20:42 +00:00
|
|
|
return mCollisionObject.get();
|
2018-03-18 11:32:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const btCollisionObject* HeightField::getCollisionObject() const
|
|
|
|
{
|
2020-12-25 17:20:42 +00:00
|
|
|
return mCollisionObject.get();
|
2018-03-18 11:32:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const btHeightfieldTerrainShape* HeightField::getShape() const
|
|
|
|
{
|
2020-12-25 17:20:42 +00:00
|
|
|
return mShape.get();
|
2018-03-18 11:32:45 +00:00
|
|
|
}
|
|
|
|
}
|