diff --git a/apps/openmw/mwphysics/heightfield.cpp b/apps/openmw/mwphysics/heightfield.cpp index e210bc3903..d363ddef11 100644 --- a/apps/openmw/mwphysics/heightfield.cpp +++ b/apps/openmw/mwphysics/heightfield.cpp @@ -1,6 +1,8 @@ #include "heightfield.hpp" #include "mtphysics.hpp" +#include + #include #include @@ -19,17 +21,17 @@ namespace { template - auto makeHeights(const T* heights, float sqrtVerts) + auto makeHeights(const T* heights, int verts) -> std::enable_if_t::value, std::vector> { return {}; } template - auto makeHeights(const T* heights, float sqrtVerts) + auto makeHeights(const T* heights, int verts) -> std::enable_if_t::value, std::vector> { - return std::vector(heights, heights + static_cast(sqrtVerts * sqrtVerts)); + return std::vector(heights, heights + static_cast(verts * verts)); } template @@ -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( - sqrtVerts, sqrtVerts, + verts, verts, getHeights(heights, mHeights), 1, minH, maxH, 2, @@ -67,10 +70,12 @@ namespace MWPhysics ); #else mShape = std::make_unique( - 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(size) / static_cast(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(); mCollisionObject->setCollisionShape(mShape.get()); diff --git a/apps/openmw/mwphysics/heightfield.hpp b/apps/openmw/mwphysics/heightfield.hpp index 93b2733f31..c320225258 100644 --- a/apps/openmw/mwphysics/heightfield.hpp +++ b/apps/openmw/mwphysics/heightfield.hpp @@ -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(); diff --git a/apps/openmw/mwphysics/physicssystem.cpp b/apps/openmw/mwphysics/physicssystem.cpp index 6b2600069a..5f7ee0523a 100644 --- a/apps/openmw/mwphysics/physicssystem.cpp +++ b/apps/openmw/mwphysics/physicssystem.cpp @@ -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(heights, x, y, triSize, sqrtVerts, minH, maxH, holdObject, mTaskScheduler.get()); + mHeightFields[std::make_pair(x,y)] = std::make_unique(heights, x, y, size, verts, minH, maxH, holdObject, mTaskScheduler.get()); } void PhysicsSystem::removeHeightField (int x, int y) diff --git a/apps/openmw/mwphysics/physicssystem.hpp b/apps/openmw/mwphysics/physicssystem.hpp index cf4ca40a54..30fdbcc122 100644 --- a/apps/openmw/mwphysics/physicssystem.hpp +++ b/apps/openmw/mwphysics/physicssystem.hpp @@ -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); diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index ed68a46059..b94a729faf 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -383,17 +383,17 @@ namespace MWWorld { osg::ref_ptr 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 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)) { diff --git a/components/bullethelpers/heightfield.hpp b/components/bullethelpers/heightfield.hpp new file mode 100644 index 0000000000..6b1f0ccc2e --- /dev/null +++ b/components/bullethelpers/heightfield.hpp @@ -0,0 +1,14 @@ +#ifndef OPENMW_COMPONENTS_BULLETHELPERS_HEIGHTFIELD_H +#define OPENMW_COMPONENTS_BULLETHELPERS_HEIGHTFIELD_H + +#include + +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