forked from teamnwah/openmw-tes3coop
Readded height fields
This commit is contained in:
parent
c31b416ba1
commit
54c1f19c18
3 changed files with 137 additions and 31 deletions
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include <osg/Group>
|
||||
|
||||
#include <BulletCollision/CollisionShapes/btHeightfieldTerrainShape.h>
|
||||
|
||||
#include <components/nifbullet/bulletnifloader.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
||||
|
@ -187,7 +189,7 @@ namespace MWPhysics
|
|||
if(stepper.mFraction < 1.0f && getSlope(stepper.mPlaneNormal) <= sMaxSlope)
|
||||
{
|
||||
// don't allow stepping up other actors
|
||||
if (stepper.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup == OEngine::Physic::CollisionType_Actor)
|
||||
if (stepper.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor)
|
||||
return false;
|
||||
// only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall.
|
||||
// TODO: stepper.mPlaneNormal does not appear to be reliable - needs more testing
|
||||
|
@ -246,7 +248,7 @@ namespace MWPhysics
|
|||
|
||||
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
|
||||
resultCallback1.m_collisionFilterGroup = 0xff;
|
||||
resultCallback1.m_collisionFilterMask = OEngine::Physic::CollisionType_World|OEngine::Physic::CollisionType_HeightMap;
|
||||
resultCallback1.m_collisionFilterMask = CollisionType_World|CollisionType_HeightMap;
|
||||
|
||||
engine->mDynamicsWorld->rayTest(from, to, resultCallback1);
|
||||
if (resultCallback1.hasHit() &&
|
||||
|
@ -437,14 +439,14 @@ namespace MWPhysics
|
|||
Ogre::Vector3(0,0,sStepSizeDown+2.f) : Ogre::Vector3(0,0,2.f));
|
||||
tracer.doTrace(colobj, from, to, engine);
|
||||
if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope
|
||||
&& tracer.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup != OEngine::Physic::CollisionType_Actor)
|
||||
&& tracer.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup != CollisionType_Actor)
|
||||
{
|
||||
const btCollisionObject* standingOn = tracer.mHitObject;
|
||||
if (const OEngine::Physic::RigidBody* body = dynamic_cast<const OEngine::Physic::RigidBody*>(standingOn))
|
||||
{
|
||||
standingCollisionTracker[ptr.getRefData().getHandle()] = body->mName;
|
||||
}
|
||||
if (standingOn->getBroadphaseHandle()->m_collisionFilterGroup == OEngine::Physic::CollisionType_Water)
|
||||
if (standingOn->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Water)
|
||||
physicActor->setWalkingOnWater(true);
|
||||
|
||||
if (!isFlying)
|
||||
|
@ -457,7 +459,7 @@ namespace MWPhysics
|
|||
// standing on actors is not allowed (see above).
|
||||
// in addition to that, apply a sliding effect away from the center of the actor,
|
||||
// so that we do not stay suspended in air indefinitely.
|
||||
if (tracer.mFraction < 1.0f && tracer.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup == OEngine::Physic::CollisionType_Actor)
|
||||
if (tracer.mFraction < 1.0f && tracer.mHitObject->getBroadphaseHandle()->m_collisionFilterGroup == CollisionType_Actor)
|
||||
{
|
||||
if (Ogre::Vector3(velocity.x, velocity.y, 0).squaredLength() < 100.f*100.f)
|
||||
{
|
||||
|
@ -492,15 +494,94 @@ namespace MWPhysics
|
|||
};
|
||||
|
||||
|
||||
PhysicsSystem::PhysicsSystem(osg::ref_ptr<osg::Group> parentNode) :
|
||||
mTimeAccum(0.0f), mWaterEnabled(false), mWaterHeight(0), mDebugDrawEnabled(false), mParentNode(parentNode)
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
class HeightField
|
||||
{
|
||||
public:
|
||||
HeightField(float* heights, int x, int y, float triSize, float sqrtVerts)
|
||||
{
|
||||
// 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(
|
||||
sqrtVerts, sqrtVerts, heights, 1,
|
||||
minh, maxh, 2,
|
||||
PHY_FLOAT, true
|
||||
);
|
||||
mShape->setUseDiamondSubdivision(true);
|
||||
mShape->setLocalScaling(btVector3(triSize, triSize, 1));
|
||||
|
||||
btTransform transform(btQuaternion::getIdentity(),
|
||||
btVector3((x+0.5f) * triSize * (sqrtVerts-1),
|
||||
(y+0.5f) * triSize * (sqrtVerts-1),
|
||||
(maxh+minh)*0.5f));
|
||||
|
||||
mCollisionObject = new btCollisionObject;
|
||||
mCollisionObject->setCollisionShape(mShape);
|
||||
mCollisionObject->setWorldTransform(transform);
|
||||
}
|
||||
~HeightField()
|
||||
{
|
||||
delete mCollisionObject;
|
||||
delete mShape;
|
||||
}
|
||||
btCollisionObject* getCollisionObject()
|
||||
{
|
||||
return mCollisionObject;
|
||||
}
|
||||
|
||||
private:
|
||||
btHeightfieldTerrainShape* mShape;
|
||||
btCollisionObject* mCollisionObject;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
|
||||
PhysicsSystem::PhysicsSystem(osg::ref_ptr<osg::Group> parentNode)
|
||||
: mTimeAccum(0.0f)
|
||||
, mWaterEnabled(false)
|
||||
, mWaterHeight(0)
|
||||
, mDebugDrawEnabled(false)
|
||||
, mParentNode(parentNode)
|
||||
{
|
||||
mCollisionConfiguration = new btDefaultCollisionConfiguration();
|
||||
mDispatcher = new btCollisionDispatcher(mCollisionConfiguration);
|
||||
mSolver = new btSequentialImpulseConstraintSolver;
|
||||
mBroadphase = new btDbvtBroadphase();
|
||||
mDynamicsWorld = new btDiscreteDynamicsWorld(mDispatcher,mBroadphase,mSolver,mCollisionConfiguration);
|
||||
|
||||
// Don't update AABBs of all objects every frame. Most objects in MW are static, so we don't need this.
|
||||
// Should a "static" object ever be moved, we have to update its AABB manually using DynamicsWorld::updateSingleAabb.
|
||||
mDynamicsWorld->setForceUpdateAllAabbs(false);
|
||||
|
||||
mDynamicsWorld->setGravity(btVector3(0,0,-10));
|
||||
}
|
||||
|
||||
PhysicsSystem::~PhysicsSystem()
|
||||
{
|
||||
//if (mWaterCollisionObject.get())
|
||||
// mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||
if (mWaterCollisionObject.get())
|
||||
mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||
|
||||
for (HeightFieldMap::iterator it = mHeightFields.begin(); it != mHeightFields.end(); ++it)
|
||||
{
|
||||
mDynamicsWorld->removeCollisionObject(it->second->getCollisionObject());
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
delete mDynamicsWorld;
|
||||
delete mSolver;
|
||||
delete mCollisionConfiguration;
|
||||
delete mDispatcher;
|
||||
delete mBroadphase;
|
||||
}
|
||||
|
||||
bool PhysicsSystem::toggleDebugRendering()
|
||||
|
@ -509,9 +590,9 @@ namespace MWPhysics
|
|||
|
||||
if (mDebugDrawEnabled && !mDebugDrawer.get())
|
||||
{
|
||||
//mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mEngine->mDynamicsWorld));
|
||||
//mEngine->mDynamicsWorld->setDebugDrawer(mDebugDrawer.get());
|
||||
//mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
||||
mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mDynamicsWorld));
|
||||
mDynamicsWorld->setDebugDrawer(mDebugDrawer.get());
|
||||
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
||||
}
|
||||
else if (mDebugDrawer.get())
|
||||
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
||||
|
@ -592,14 +673,24 @@ namespace MWPhysics
|
|||
return Ogre::Vector3();//MovementSolver::traceDown(ptr, mEngine, maxHeight);
|
||||
}
|
||||
|
||||
void PhysicsSystem::addHeightField (float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts)
|
||||
void PhysicsSystem::addHeightField (float* heights, int x, int y, float triSize, float sqrtVerts)
|
||||
{
|
||||
HeightField *heightfield = new HeightField(heights, x, y, triSize, sqrtVerts);
|
||||
mHeightFields[std::make_pair(x,y)] = heightfield;
|
||||
|
||||
mDynamicsWorld->addCollisionObject(heightfield->getCollisionObject(), CollisionType_HeightMap,
|
||||
CollisionType_Actor|CollisionType_Projectile);
|
||||
}
|
||||
|
||||
void PhysicsSystem::removeHeightField (int x, int y)
|
||||
{
|
||||
HeightFieldMap::iterator heightfield = mHeightFields.find(std::make_pair(x,y));
|
||||
if(heightfield != mHeightFields.end())
|
||||
{
|
||||
mDynamicsWorld->removeCollisionObject(heightfield->second->getCollisionObject());
|
||||
delete heightfield->second;
|
||||
mHeightFields.erase(heightfield);
|
||||
}
|
||||
}
|
||||
|
||||
void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh, bool placeable)
|
||||
|
@ -726,9 +817,10 @@ namespace MWPhysics
|
|||
|
||||
void PhysicsSystem::stepSimulation(float dt)
|
||||
{
|
||||
//animateCollisionShapes(mEngine->mAnimatedShapes, mEngine->mDynamicsWorld);
|
||||
//animateCollisionShapes(mEngine->mAnimatedShapes, mDynamicsWorld);
|
||||
|
||||
//mEngine->stepSimulation(dt);
|
||||
// We have nothing to simulate, but character controllers aren't working without this call. Might be related to updating AABBs.
|
||||
mDynamicsWorld->stepSimulation(static_cast<btScalar>(dt), 1, 1 / 60.0f);
|
||||
|
||||
if (mDebugDrawer.get())
|
||||
mDebugDrawer->step();
|
||||
|
@ -818,7 +910,7 @@ namespace MWPhysics
|
|||
{
|
||||
if (mWaterCollisionObject.get())
|
||||
{
|
||||
//mEngine->mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||
mDynamicsWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||
}
|
||||
|
||||
if (!mWaterEnabled)
|
||||
|
@ -827,7 +919,7 @@ namespace MWPhysics
|
|||
mWaterCollisionObject.reset(new btCollisionObject());
|
||||
mWaterCollisionShape.reset(new btStaticPlaneShape(btVector3(0,0,1), mWaterHeight));
|
||||
mWaterCollisionObject->setCollisionShape(mWaterCollisionShape.get());
|
||||
//mEngine->mDynamicsWorld->addCollisionObject(mWaterCollisionObject.get(), OEngine::Physic::CollisionType_Water,
|
||||
// OEngine::Physic::CollisionType_Actor);
|
||||
mDynamicsWorld->addCollisionObject(mWaterCollisionObject.get(), CollisionType_Water,
|
||||
CollisionType_Actor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,23 @@ namespace MWRender
|
|||
class DebugDrawer;
|
||||
}
|
||||
|
||||
class btSequentialImpulseConstraintSolver;
|
||||
class btDiscreteDynamicsWorld;
|
||||
|
||||
namespace MWPhysics
|
||||
{
|
||||
typedef std::vector<std::pair<MWWorld::Ptr,Ogre::Vector3> > PtrVelocityList;
|
||||
|
||||
enum CollisionType {
|
||||
CollisionType_World = 1<<0,
|
||||
CollisionType_Actor = 1<<1,
|
||||
CollisionType_HeightMap = 1<<2,
|
||||
CollisionType_Projectile = 1<<4,
|
||||
CollisionType_Water = 1<<5
|
||||
};
|
||||
|
||||
class HeightField;
|
||||
|
||||
class PhysicsSystem
|
||||
{
|
||||
public:
|
||||
|
@ -39,9 +52,7 @@ namespace MWPhysics
|
|||
|
||||
void addActor (const MWWorld::Ptr& ptr, const std::string& mesh);
|
||||
|
||||
void addHeightField (float* heights,
|
||||
int x, int y, float yoffset,
|
||||
float triSize, float sqrtVerts);
|
||||
void addHeightField (float* heights, int x, int y, float triSize, float sqrtVerts);
|
||||
|
||||
void removeHeightField (int x, int y);
|
||||
|
||||
|
@ -94,6 +105,15 @@ namespace MWPhysics
|
|||
|
||||
void updateWater();
|
||||
|
||||
btBroadphaseInterface* mBroadphase;
|
||||
btDefaultCollisionConfiguration* mCollisionConfiguration;
|
||||
btSequentialImpulseConstraintSolver* mSolver;
|
||||
btCollisionDispatcher* mDispatcher;
|
||||
btDiscreteDynamicsWorld* mDynamicsWorld;
|
||||
|
||||
typedef std::map<std::pair<int, int>, HeightField*> HeightFieldMap;
|
||||
HeightFieldMap mHeightFields;
|
||||
|
||||
bool mDebugDrawEnabled;
|
||||
|
||||
std::map<std::string, std::string> handleToMesh;
|
||||
|
|
|
@ -246,14 +246,8 @@ namespace MWWorld
|
|||
const int flags = ESM::Land::DATA_VCLR|ESM::Land::DATA_VHGT|ESM::Land::DATA_VNML|ESM::Land::DATA_VTEX;
|
||||
if (!land->isDataLoaded(flags))
|
||||
land->loadData(flags);
|
||||
mPhysics->addHeightField (
|
||||
land->mLandData->mHeights,
|
||||
cell->getCell()->getGridX(),
|
||||
cell->getCell()->getGridY(),
|
||||
0,
|
||||
worldsize / (verts-1),
|
||||
verts)
|
||||
;
|
||||
mPhysics->addHeightField (land->mLandData->mHeights, cell->getCell()->getGridX(), cell->getCell()->getGridY(),
|
||||
worldsize / (verts-1), verts);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue