mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-21 23:09:42 +00:00
Non functionnal changes in preparation for async physics feature
This commit is contained in:
parent
72549651e0
commit
82da2045a9
7 changed files with 101 additions and 111 deletions
|
@ -17,32 +17,29 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr<const Resource::BulletShape> shape, btCollisionWorld* world)
|
Actor::Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, btCollisionWorld* world)
|
||||||
: mCanWaterWalk(false), mWalkingOnWater(false)
|
: mCanWaterWalk(false), mWalkingOnWater(false)
|
||||||
, mCollisionObject(nullptr), mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false)
|
, mCollisionObject(nullptr), mMeshTranslation(shape->mCollisionBoxTranslate), mHalfExtents(shape->mCollisionBoxHalfExtents)
|
||||||
|
, mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false)
|
||||||
, mInternalCollisionMode(true)
|
, mInternalCollisionMode(true)
|
||||||
, mExternalCollisionMode(true)
|
, mExternalCollisionMode(true)
|
||||||
, mCollisionWorld(world)
|
, mCollisionWorld(world)
|
||||||
{
|
{
|
||||||
mPtr = ptr;
|
mPtr = ptr;
|
||||||
|
|
||||||
mHalfExtents = shape->mCollisionBoxHalfExtents;
|
|
||||||
mMeshTranslation = shape->mCollisionBoxTranslate;
|
|
||||||
|
|
||||||
// We can not create actor without collisions - he will fall through the ground.
|
// We can not create actor without collisions - he will fall through the ground.
|
||||||
// In this case we should autogenerate collision box based on mesh shape
|
// In this case we should autogenerate collision box based on mesh shape
|
||||||
// (NPCs have bodyparts and use a different approach)
|
// (NPCs have bodyparts and use a different approach)
|
||||||
if (!ptr.getClass().isNpc() && mHalfExtents.length2() == 0.f)
|
if (!ptr.getClass().isNpc() && mHalfExtents.length2() == 0.f)
|
||||||
{
|
{
|
||||||
const Resource::BulletShape* collisionShape = shape.get();
|
if (shape->mCollisionShape)
|
||||||
if (collisionShape && collisionShape->mCollisionShape)
|
|
||||||
{
|
{
|
||||||
btTransform transform;
|
btTransform transform;
|
||||||
transform.setIdentity();
|
transform.setIdentity();
|
||||||
btVector3 min;
|
btVector3 min;
|
||||||
btVector3 max;
|
btVector3 max;
|
||||||
|
|
||||||
collisionShape->mCollisionShape->getAabb(transform, min, max);
|
shape->mCollisionShape->getAabb(transform, min, max);
|
||||||
mHalfExtents.x() = (max[0] - min[0])/2.f;
|
mHalfExtents.x() = (max[0] - min[0])/2.f;
|
||||||
mHalfExtents.y() = (max[1] - min[1])/2.f;
|
mHalfExtents.y() = (max[1] - min[1])/2.f;
|
||||||
mHalfExtents.z() = (max[2] - min[2])/2.f;
|
mHalfExtents.z() = (max[2] - min[2])/2.f;
|
||||||
|
@ -83,7 +80,7 @@ Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr<const Resource::BulletShape>
|
||||||
|
|
||||||
Actor::~Actor()
|
Actor::~Actor()
|
||||||
{
|
{
|
||||||
if (mCollisionObject.get())
|
if (mCollisionObject)
|
||||||
mCollisionWorld->removeCollisionObject(mCollisionObject.get());
|
mCollisionWorld->removeCollisionObject(mCollisionObject.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +109,7 @@ void Actor::updateCollisionMask()
|
||||||
addCollisionMask(getCollisionMask());
|
addCollisionMask(getCollisionMask());
|
||||||
}
|
}
|
||||||
|
|
||||||
int Actor::getCollisionMask()
|
int Actor::getCollisionMask() const
|
||||||
{
|
{
|
||||||
int collisionMask = CollisionType_World | CollisionType_HeightMap;
|
int collisionMask = CollisionType_World | CollisionType_HeightMap;
|
||||||
if (mExternalCollisionMode)
|
if (mExternalCollisionMode)
|
||||||
|
@ -120,7 +117,6 @@ int Actor::getCollisionMask()
|
||||||
if (mCanWaterWalk)
|
if (mCanWaterWalk)
|
||||||
collisionMask |= CollisionType_Water;
|
collisionMask |= CollisionType_Water;
|
||||||
return collisionMask;
|
return collisionMask;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actor::updatePosition()
|
void Actor::updatePosition()
|
||||||
|
|
|
@ -21,12 +21,13 @@ namespace Resource
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
{
|
{
|
||||||
|
class PhysicsTaskScheduler;
|
||||||
|
|
||||||
class Actor : public PtrHolder
|
class Actor final : public PtrHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Actor(const MWWorld::Ptr& ptr, osg::ref_ptr<const Resource::BulletShape> shape, btCollisionWorld* world);
|
Actor(const MWWorld::Ptr& ptr, const Resource::BulletShape* shape, btCollisionWorld* world);
|
||||||
~Actor();
|
~Actor() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry.
|
* Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry.
|
||||||
|
@ -136,7 +137,7 @@ namespace MWPhysics
|
||||||
/// Removes then re-adds the collision object to the dynamics world
|
/// Removes then re-adds the collision object to the dynamics world
|
||||||
void updateCollisionMask();
|
void updateCollisionMask();
|
||||||
void addCollisionMask(int collisionMask);
|
void addCollisionMask(int collisionMask);
|
||||||
int getCollisionMask();
|
int getCollisionMask() const;
|
||||||
|
|
||||||
bool mCanWaterWalk;
|
bool mCanWaterWalk;
|
||||||
bool mWalkingOnWater;
|
bool mWalkingOnWater;
|
||||||
|
|
|
@ -14,9 +14,10 @@
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
{
|
{
|
||||||
Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance)
|
Object::Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance, btCollisionWorld* world)
|
||||||
: mShapeInstance(shapeInstance)
|
: mShapeInstance(shapeInstance)
|
||||||
, mSolid(true)
|
, mSolid(true)
|
||||||
|
, mCollisionWorld(world)
|
||||||
{
|
{
|
||||||
mPtr = ptr;
|
mPtr = ptr;
|
||||||
|
|
||||||
|
@ -31,6 +32,12 @@ namespace MWPhysics
|
||||||
setOrigin(btVector3(pos[0], pos[1], pos[2]));
|
setOrigin(btVector3(pos[0], pos[1], pos[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object::~Object()
|
||||||
|
{
|
||||||
|
if (mCollisionObject)
|
||||||
|
mCollisionWorld->removeCollisionObject(mCollisionObject.get());
|
||||||
|
}
|
||||||
|
|
||||||
const Resource::BulletShapeInstance* Object::getShapeInstance() const
|
const Resource::BulletShapeInstance* Object::getShapeInstance() const
|
||||||
{
|
{
|
||||||
return mShapeInstance.get();
|
return mShapeInstance.get();
|
||||||
|
|
|
@ -20,10 +20,11 @@ class btVector3;
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
{
|
{
|
||||||
class Object : public PtrHolder
|
class Object final : public PtrHolder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance);
|
Object(const MWWorld::Ptr& ptr, osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance, btCollisionWorld* world);
|
||||||
|
~Object() override;
|
||||||
|
|
||||||
const Resource::BulletShapeInstance* getShapeInstance() const;
|
const Resource::BulletShapeInstance* getShapeInstance() const;
|
||||||
void setScale(float scale);
|
void setScale(float scale);
|
||||||
|
@ -42,6 +43,7 @@ namespace MWPhysics
|
||||||
osg::ref_ptr<Resource::BulletShapeInstance> mShapeInstance;
|
osg::ref_ptr<Resource::BulletShapeInstance> mShapeInstance;
|
||||||
std::map<int, osg::NodePath> mRecIndexToNodePath;
|
std::map<int, osg::NodePath> mRecIndexToNodePath;
|
||||||
bool mSolid;
|
bool mSolid;
|
||||||
|
btCollisionWorld* mCollisionWorld;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,11 +65,11 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
mResourceSystem->addResourceManager(mShapeManager.get());
|
mResourceSystem->addResourceManager(mShapeManager.get());
|
||||||
|
|
||||||
mCollisionConfiguration = new btDefaultCollisionConfiguration();
|
mCollisionConfiguration = std::make_unique<btDefaultCollisionConfiguration>();
|
||||||
mDispatcher = new btCollisionDispatcher(mCollisionConfiguration);
|
mDispatcher = std::make_unique<btCollisionDispatcher>(mCollisionConfiguration.get());
|
||||||
mBroadphase = new btDbvtBroadphase();
|
mBroadphase = std::make_unique<btDbvtBroadphase>();
|
||||||
|
|
||||||
mCollisionWorld = new btCollisionWorld(mDispatcher, mBroadphase, mCollisionConfiguration);
|
mCollisionWorld = std::make_shared<btCollisionWorld>(mDispatcher.get(), mBroadphase.get(), mCollisionConfiguration.get());
|
||||||
|
|
||||||
// Don't update AABBs of all objects every frame. Most objects in MW are static, so we don't need this.
|
// 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.
|
// Should a "static" object ever be moved, we have to update its AABB manually using DynamicsWorld::updateSingleAabb.
|
||||||
|
@ -92,7 +92,7 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
mResourceSystem->removeResourceManager(mShapeManager.get());
|
mResourceSystem->removeResourceManager(mShapeManager.get());
|
||||||
|
|
||||||
if (mWaterCollisionObject.get())
|
if (mWaterCollisionObject)
|
||||||
mCollisionWorld->removeCollisionObject(mWaterCollisionObject.get());
|
mCollisionWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||||
|
|
||||||
for (auto& heightField : mHeightFields)
|
for (auto& heightField : mHeightFields)
|
||||||
|
@ -101,21 +101,9 @@ namespace MWPhysics
|
||||||
delete heightField.second;
|
delete heightField.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& object : mObjects)
|
mObjects.clear();
|
||||||
{
|
mActors.clear();
|
||||||
mCollisionWorld->removeCollisionObject(object.second->getCollisionObject());
|
|
||||||
delete object.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& actor : mActors)
|
|
||||||
{
|
|
||||||
delete actor.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete mCollisionWorld;
|
|
||||||
delete mCollisionConfiguration;
|
|
||||||
delete mDispatcher;
|
|
||||||
delete mBroadphase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::setUnrefQueue(SceneUtil::UnrefQueue *unrefQueue)
|
void PhysicsSystem::setUnrefQueue(SceneUtil::UnrefQueue *unrefQueue)
|
||||||
|
@ -132,13 +120,13 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
mDebugDrawEnabled = !mDebugDrawEnabled;
|
mDebugDrawEnabled = !mDebugDrawEnabled;
|
||||||
|
|
||||||
if (mDebugDrawEnabled && !mDebugDrawer.get())
|
if (mDebugDrawEnabled && !mDebugDrawer)
|
||||||
{
|
{
|
||||||
mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mCollisionWorld));
|
mDebugDrawer.reset(new MWRender::DebugDrawer(mParentNode, mCollisionWorld.get()));
|
||||||
mCollisionWorld->setDebugDrawer(mDebugDrawer.get());
|
mCollisionWorld->setDebugDrawer(mDebugDrawer.get());
|
||||||
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
||||||
}
|
}
|
||||||
else if (mDebugDrawer.get())
|
else if (mDebugDrawer)
|
||||||
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
mDebugDrawer->setDebugMode(mDebugDrawEnabled);
|
||||||
return mDebugDrawEnabled;
|
return mDebugDrawEnabled;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +163,7 @@ namespace MWPhysics
|
||||||
std::pair<MWWorld::Ptr, osg::Vec3f> PhysicsSystem::getHitContact(const MWWorld::ConstPtr& actor,
|
std::pair<MWWorld::Ptr, osg::Vec3f> PhysicsSystem::getHitContact(const MWWorld::ConstPtr& actor,
|
||||||
const osg::Vec3f &origin,
|
const osg::Vec3f &origin,
|
||||||
const osg::Quat &orient,
|
const osg::Quat &orient,
|
||||||
float queryDistance, std::vector<MWWorld::Ptr> targets)
|
float queryDistance, std::vector<MWWorld::Ptr>& targets)
|
||||||
{
|
{
|
||||||
// First of all, try to hit where you aim to
|
// First of all, try to hit where you aim to
|
||||||
int hitmask = CollisionType_World | CollisionType_Door | CollisionType_HeightMap | CollisionType_Actor;
|
int hitmask = CollisionType_World | CollisionType_Door | CollisionType_HeightMap | CollisionType_Actor;
|
||||||
|
@ -373,7 +361,7 @@ namespace MWPhysics
|
||||||
const osg::Vec3f startingPosition(actorPosition.x(), actorPosition.y(), actorPosition.z() + halfZ);
|
const osg::Vec3f startingPosition(actorPosition.x(), actorPosition.y(), actorPosition.z() + halfZ);
|
||||||
const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel + halfZ);
|
const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel + halfZ);
|
||||||
ActorTracer tracer;
|
ActorTracer tracer;
|
||||||
tracer.doTrace(physicActor->getCollisionObject(), startingPosition, destinationPosition, mCollisionWorld);
|
tracer.doTrace(physicActor->getCollisionObject(), startingPosition, destinationPosition, mCollisionWorld.get());
|
||||||
return (tracer.mFraction >= 1.0f);
|
return (tracer.mFraction >= 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -444,7 +432,7 @@ namespace MWPhysics
|
||||||
if (found == mActors.end())
|
if (found == mActors.end())
|
||||||
return ptr.getRefData().getPosition().asVec3();
|
return ptr.getRefData().getPosition().asVec3();
|
||||||
else
|
else
|
||||||
return MovementSolver::traceDown(ptr, position, found->second, mCollisionWorld, 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, float triSize, float sqrtVerts, float minH, float maxH, const osg::Object* holdObject)
|
||||||
|
@ -481,11 +469,11 @@ namespace MWPhysics
|
||||||
if (!shapeInstance || !shapeInstance->getCollisionShape())
|
if (!shapeInstance || !shapeInstance->getCollisionShape())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Object *obj = new Object(ptr, shapeInstance);
|
auto obj = std::make_shared<Object>(ptr, shapeInstance, mCollisionWorld.get());
|
||||||
mObjects.emplace(ptr, obj);
|
mObjects.emplace(ptr, obj);
|
||||||
|
|
||||||
if (obj->isAnimated())
|
if (obj->isAnimated())
|
||||||
mAnimatedObjects.insert(obj);
|
mAnimatedObjects.insert(obj.get());
|
||||||
|
|
||||||
mCollisionWorld->addCollisionObject(obj->getCollisionObject(), collisionType,
|
mCollisionWorld->addCollisionObject(obj->getCollisionObject(), collisionType,
|
||||||
CollisionType_Actor|CollisionType_HeightMap|CollisionType_Projectile);
|
CollisionType_Actor|CollisionType_HeightMap|CollisionType_Projectile);
|
||||||
|
@ -496,21 +484,17 @@ namespace MWPhysics
|
||||||
ObjectMap::iterator found = mObjects.find(ptr);
|
ObjectMap::iterator found = mObjects.find(ptr);
|
||||||
if (found != mObjects.end())
|
if (found != mObjects.end())
|
||||||
{
|
{
|
||||||
mCollisionWorld->removeCollisionObject(found->second->getCollisionObject());
|
|
||||||
|
|
||||||
if (mUnrefQueue.get())
|
if (mUnrefQueue.get())
|
||||||
mUnrefQueue->push(found->second->getShapeInstance());
|
mUnrefQueue->push(found->second->getShapeInstance());
|
||||||
|
|
||||||
mAnimatedObjects.erase(found->second);
|
mAnimatedObjects.erase(found->second.get());
|
||||||
|
|
||||||
delete found->second;
|
|
||||||
mObjects.erase(found);
|
mObjects.erase(found);
|
||||||
}
|
}
|
||||||
|
|
||||||
ActorMap::iterator foundActor = mActors.find(ptr);
|
ActorMap::iterator foundActor = mActors.find(ptr);
|
||||||
if (foundActor != mActors.end())
|
if (foundActor != mActors.end())
|
||||||
{
|
{
|
||||||
delete foundActor->second;
|
|
||||||
mActors.erase(foundActor);
|
mActors.erase(foundActor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -536,19 +520,19 @@ namespace MWPhysics
|
||||||
ObjectMap::iterator found = mObjects.find(old);
|
ObjectMap::iterator found = mObjects.find(old);
|
||||||
if (found != mObjects.end())
|
if (found != mObjects.end())
|
||||||
{
|
{
|
||||||
Object* obj = found->second;
|
auto obj = found->second;
|
||||||
obj->updatePtr(updated);
|
obj->updatePtr(updated);
|
||||||
mObjects.erase(found);
|
mObjects.erase(found);
|
||||||
mObjects.emplace(updated, obj);
|
mObjects.emplace(updated, std::move(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
ActorMap::iterator foundActor = mActors.find(old);
|
ActorMap::iterator foundActor = mActors.find(old);
|
||||||
if (foundActor != mActors.end())
|
if (foundActor != mActors.end())
|
||||||
{
|
{
|
||||||
Actor* actor = foundActor->second;
|
auto actor = foundActor->second;
|
||||||
actor->updatePtr(updated);
|
actor->updatePtr(updated);
|
||||||
mActors.erase(foundActor);
|
mActors.erase(foundActor);
|
||||||
mActors.emplace(updated, actor);
|
mActors.emplace(updated, std::move(actor));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateCollisionMapPtr(mStandingCollisions, old, updated);
|
updateCollisionMapPtr(mStandingCollisions, old, updated);
|
||||||
|
@ -558,7 +542,7 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
ActorMap::iterator found = mActors.find(ptr);
|
ActorMap::iterator found = mActors.find(ptr);
|
||||||
if (found != mActors.end())
|
if (found != mActors.end())
|
||||||
return found->second;
|
return found->second.get();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,7 +550,7 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
ActorMap::const_iterator found = mActors.find(ptr);
|
ActorMap::const_iterator found = mActors.find(ptr);
|
||||||
if (found != mActors.end())
|
if (found != mActors.end())
|
||||||
return found->second;
|
return found->second.get();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,7 +558,7 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
ObjectMap::const_iterator found = mObjects.find(ptr);
|
ObjectMap::const_iterator found = mObjects.find(ptr);
|
||||||
if (found != mObjects.end())
|
if (found != mObjects.end())
|
||||||
return found->second;
|
return found->second.get();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,11 +623,9 @@ namespace MWPhysics
|
||||||
void PhysicsSystem::addActor (const MWWorld::Ptr& ptr, const std::string& mesh)
|
void PhysicsSystem::addActor (const MWWorld::Ptr& ptr, const std::string& mesh)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<const Resource::BulletShape> shape = mShapeManager->getShape(mesh);
|
osg::ref_ptr<const Resource::BulletShape> shape = mShapeManager->getShape(mesh);
|
||||||
if (!shape)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Try to get shape from basic model as fallback for creatures
|
// Try to get shape from basic model as fallback for creatures
|
||||||
if (!ptr.getClass().isNpc() && shape->mCollisionBoxHalfExtents.length2() == 0)
|
if (!ptr.getClass().isNpc() && shape && shape->mCollisionBoxHalfExtents.length2() == 0)
|
||||||
{
|
{
|
||||||
const std::string fallbackModel = ptr.getClass().getModel(ptr);
|
const std::string fallbackModel = ptr.getClass().getModel(ptr);
|
||||||
if (fallbackModel != mesh)
|
if (fallbackModel != mesh)
|
||||||
|
@ -652,8 +634,11 @@ namespace MWPhysics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Actor* actor = new Actor(ptr, shape, mCollisionWorld);
|
if (!shape)
|
||||||
mActors.emplace(ptr, actor);
|
return;
|
||||||
|
|
||||||
|
auto actor = std::make_shared<Actor>(ptr, shape, mCollisionWorld.get());
|
||||||
|
mActors.emplace(ptr, std::move(actor));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PhysicsSystem::toggleCollisionMode()
|
bool PhysicsSystem::toggleCollisionMode()
|
||||||
|
@ -691,14 +676,14 @@ namespace MWPhysics
|
||||||
mStandingCollisions.clear();
|
mStandingCollisions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
const PtrVelocityList& PhysicsSystem::applyQueuedMovement(float dt)
|
const PtrPositionList& PhysicsSystem::applyQueuedMovement(float dt)
|
||||||
{
|
{
|
||||||
mMovementResults.clear();
|
mMovementResults.clear();
|
||||||
|
|
||||||
mTimeAccum += dt;
|
mTimeAccum += dt;
|
||||||
|
|
||||||
const int maxAllowedSteps = 20;
|
const int maxAllowedSteps = 20;
|
||||||
int numSteps = mTimeAccum / (mPhysicsDt);
|
int numSteps = mTimeAccum / mPhysicsDt;
|
||||||
numSteps = std::min(numSteps, maxAllowedSteps);
|
numSteps = std::min(numSteps, maxAllowedSteps);
|
||||||
|
|
||||||
mTimeAccum -= numSteps * mPhysicsDt;
|
mTimeAccum -= numSteps * mPhysicsDt;
|
||||||
|
@ -711,26 +696,28 @@ namespace MWPhysics
|
||||||
|
|
||||||
const MWWorld::Ptr player = MWMechanics::getPlayer();
|
const MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
for(auto& movementItem : mMovementQueue)
|
for (const auto& m : mMovementQueue)
|
||||||
{
|
{
|
||||||
ActorMap::iterator foundActor = mActors.find(movementItem.first);
|
const auto& character = m.first;
|
||||||
|
const auto& movement = m.second;
|
||||||
|
const auto foundActor = mActors.find(character);
|
||||||
if (foundActor == mActors.end()) // actor was already removed from the scene
|
if (foundActor == mActors.end()) // actor was already removed from the scene
|
||||||
continue;
|
continue;
|
||||||
Actor* physicActor = foundActor->second;
|
auto physicActor = foundActor->second;
|
||||||
|
|
||||||
float waterlevel = -std::numeric_limits<float>::max();
|
float waterlevel = -std::numeric_limits<float>::max();
|
||||||
const MWWorld::CellStore *cell = movementItem.first.getCell();
|
const MWWorld::CellStore *cell = character.getCell();
|
||||||
if(cell->getCell()->hasWater())
|
if(cell->getCell()->hasWater())
|
||||||
waterlevel = cell->getWaterLevel();
|
waterlevel = cell->getWaterLevel();
|
||||||
|
|
||||||
const MWMechanics::MagicEffects& effects = movementItem.first.getClass().getCreatureStats(movementItem.first).getMagicEffects();
|
const MWMechanics::MagicEffects& effects = character.getClass().getCreatureStats(character).getMagicEffects();
|
||||||
|
|
||||||
bool waterCollision = false;
|
bool waterCollision = false;
|
||||||
if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude())
|
if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude())
|
||||||
{
|
{
|
||||||
if (!world->isUnderwater(movementItem.first.getCell(), osg::Vec3f(movementItem.first.getRefData().getPosition().asVec3())))
|
if (!world->isUnderwater(character.getCell(), osg::Vec3f(character.getRefData().getPosition().asVec3())))
|
||||||
waterCollision = true;
|
waterCollision = true;
|
||||||
else if (physicActor->getCollisionMode() && canMoveToWaterSurface(movementItem.first, waterlevel))
|
else if (physicActor->getCollisionMode() && canMoveToWaterSurface(character, waterlevel))
|
||||||
{
|
{
|
||||||
const osg::Vec3f actorPosition = physicActor->getPosition();
|
const osg::Vec3f actorPosition = physicActor->getPosition();
|
||||||
physicActor->setPosition(osg::Vec3f(actorPosition.x(), actorPosition.y(), waterlevel));
|
physicActor->setPosition(osg::Vec3f(actorPosition.x(), actorPosition.y(), waterlevel));
|
||||||
|
@ -742,8 +729,8 @@ namespace MWPhysics
|
||||||
// Slow fall reduces fall speed by a factor of (effect magnitude / 200)
|
// Slow fall reduces fall speed by a factor of (effect magnitude / 200)
|
||||||
float slowFall = 1.f - std::max(0.f, std::min(1.f, effects.get(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f));
|
float slowFall = 1.f - std::max(0.f, std::min(1.f, effects.get(ESM::MagicEffect::SlowFall).getMagnitude() * 0.005f));
|
||||||
|
|
||||||
bool flying = world->isFlying(movementItem.first);
|
bool flying = world->isFlying(character);
|
||||||
bool swimming = world->isSwimming(movementItem.first);
|
bool swimming = world->isSwimming(character);
|
||||||
|
|
||||||
bool wasOnGround = physicActor->getOnGround();
|
bool wasOnGround = physicActor->getOnGround();
|
||||||
osg::Vec3f position = physicActor->getPosition();
|
osg::Vec3f position = physicActor->getPosition();
|
||||||
|
@ -751,8 +738,8 @@ namespace MWPhysics
|
||||||
bool positionChanged = false;
|
bool positionChanged = false;
|
||||||
for (int i=0; i<numSteps; ++i)
|
for (int i=0; i<numSteps; ++i)
|
||||||
{
|
{
|
||||||
position = MovementSolver::move(position, physicActor->getPtr(), physicActor, movementItem.second, mPhysicsDt,
|
position = MovementSolver::move(position, physicActor->getPtr(), physicActor.get(), movement, mPhysicsDt,
|
||||||
flying, waterlevel, slowFall, mCollisionWorld, mStandingCollisions);
|
flying, waterlevel, slowFall, mCollisionWorld.get(), mStandingCollisions);
|
||||||
if (position != physicActor->getPosition())
|
if (position != physicActor->getPosition())
|
||||||
positionChanged = true;
|
positionChanged = true;
|
||||||
physicActor->setPosition(position); // always set even if unchanged to make sure interpolation is correct
|
physicActor->setPosition(position); // always set even if unchanged to make sure interpolation is correct
|
||||||
|
@ -765,25 +752,23 @@ namespace MWPhysics
|
||||||
|
|
||||||
float heightDiff = position.z() - oldHeight;
|
float heightDiff = position.z() - oldHeight;
|
||||||
|
|
||||||
MWMechanics::CreatureStats& stats = movementItem.first.getClass().getCreatureStats(movementItem.first);
|
MWMechanics::CreatureStats& stats = character.getClass().getCreatureStats(character);
|
||||||
bool isStillOnGround = (numSteps > 0 && wasOnGround && physicActor->getOnGround());
|
bool isStillOnGround = (numSteps > 0 && wasOnGround && physicActor->getOnGround());
|
||||||
if (isStillOnGround || flying || swimming || slowFall < 1)
|
if (isStillOnGround || flying || swimming || slowFall < 1)
|
||||||
stats.land(movementItem.first == player && (flying || swimming));
|
stats.land(character == player && (flying || swimming));
|
||||||
else if (heightDiff < 0)
|
else if (heightDiff < 0)
|
||||||
stats.addToFallHeight(-heightDiff);
|
stats.addToFallHeight(-heightDiff);
|
||||||
|
|
||||||
mMovementResults.emplace_back(movementItem.first, interpolated);
|
mMovementResults.emplace(character, interpolated);
|
||||||
}
|
}
|
||||||
|
|
||||||
mMovementQueue.clear();
|
mMovementQueue.clear();
|
||||||
|
|
||||||
return mMovementResults;
|
return mMovementResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::stepSimulation(float dt)
|
void PhysicsSystem::stepSimulation()
|
||||||
{
|
{
|
||||||
for (Object* animatedObject : mAnimatedObjects)
|
for (Object* animatedObject : mAnimatedObjects)
|
||||||
animatedObject->animateCollisionShapes(mCollisionWorld);
|
animatedObject->animateCollisionShapes(mCollisionWorld.get());
|
||||||
|
|
||||||
#ifndef BT_NO_PROFILE
|
#ifndef BT_NO_PROFILE
|
||||||
CProfileManager::Reset();
|
CProfileManager::Reset();
|
||||||
|
@ -795,12 +780,12 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
ObjectMap::iterator found = mObjects.find(object);
|
ObjectMap::iterator found = mObjects.find(object);
|
||||||
if (found != mObjects.end())
|
if (found != mObjects.end())
|
||||||
found->second->animateCollisionShapes(mCollisionWorld);
|
found->second->animateCollisionShapes(mCollisionWorld.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsSystem::debugDraw()
|
void PhysicsSystem::debugDraw()
|
||||||
{
|
{
|
||||||
if (mDebugDrawer.get())
|
if (mDebugDrawer)
|
||||||
mDebugDrawer->step();
|
mDebugDrawer->step();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -865,7 +850,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
void PhysicsSystem::updateWater()
|
void PhysicsSystem::updateWater()
|
||||||
{
|
{
|
||||||
if (mWaterCollisionObject.get())
|
if (mWaterCollisionObject)
|
||||||
{
|
{
|
||||||
mCollisionWorld->removeCollisionObject(mWaterCollisionObject.get());
|
mCollisionWorld->removeCollisionObject(mWaterCollisionObject.get());
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,8 @@ class btCollisionShape;
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
{
|
{
|
||||||
typedef std::vector<std::pair<MWWorld::Ptr,osg::Vec3f> > PtrVelocityList;
|
using PtrPositionList = std::map<MWWorld::Ptr, osg::Vec3f>;
|
||||||
|
using CollisionMap = std::map<MWWorld::Ptr, MWWorld::Ptr>;
|
||||||
|
|
||||||
class HeightField;
|
class HeightField;
|
||||||
class Object;
|
class Object;
|
||||||
|
@ -93,7 +94,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
bool toggleCollisionMode();
|
bool toggleCollisionMode();
|
||||||
|
|
||||||
void stepSimulation(float dt);
|
void stepSimulation();
|
||||||
void debugDraw();
|
void debugDraw();
|
||||||
|
|
||||||
std::vector<MWWorld::Ptr> getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const; ///< get handles this object collides with
|
std::vector<MWWorld::Ptr> getCollisions(const MWWorld::ConstPtr &ptr, int collisionGroup, int collisionMask) const; ///< get handles this object collides with
|
||||||
|
@ -102,7 +103,7 @@ namespace MWPhysics
|
||||||
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::ConstPtr& actor,
|
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::ConstPtr& actor,
|
||||||
const osg::Vec3f &origin,
|
const osg::Vec3f &origin,
|
||||||
const osg::Quat &orientation,
|
const osg::Quat &orientation,
|
||||||
float queryDistance, std::vector<MWWorld::Ptr> targets = std::vector<MWWorld::Ptr>());
|
float queryDistance, std::vector<MWWorld::Ptr>& targets);
|
||||||
|
|
||||||
|
|
||||||
/// Get distance from \a point to the collision shape of \a target. Uses a raycast to find where the
|
/// Get distance from \a point to the collision shape of \a target. Uses a raycast to find where the
|
||||||
|
@ -146,7 +147,7 @@ namespace MWPhysics
|
||||||
void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity);
|
void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity);
|
||||||
|
|
||||||
/// Apply all queued movements, then clear the list.
|
/// Apply all queued movements, then clear the list.
|
||||||
const PtrVelocityList& applyQueuedMovement(float dt);
|
const PtrPositionList& applyQueuedMovement(float dt);
|
||||||
|
|
||||||
/// Clear the queued movements list without applying.
|
/// Clear the queued movements list without applying.
|
||||||
void clearQueuedMovement();
|
void clearQueuedMovement();
|
||||||
|
@ -192,37 +193,37 @@ namespace MWPhysics
|
||||||
|
|
||||||
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
||||||
|
|
||||||
btBroadphaseInterface* mBroadphase;
|
std::unique_ptr<btBroadphaseInterface> mBroadphase;
|
||||||
btDefaultCollisionConfiguration* mCollisionConfiguration;
|
std::unique_ptr<btDefaultCollisionConfiguration> mCollisionConfiguration;
|
||||||
btCollisionDispatcher* mDispatcher;
|
std::unique_ptr<btCollisionDispatcher> mDispatcher;
|
||||||
btCollisionWorld* mCollisionWorld;
|
std::shared_ptr<btCollisionWorld> mCollisionWorld;
|
||||||
|
|
||||||
std::unique_ptr<Resource::BulletShapeManager> mShapeManager;
|
std::unique_ptr<Resource::BulletShapeManager> mShapeManager;
|
||||||
Resource::ResourceSystem* mResourceSystem;
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
|
||||||
typedef std::map<MWWorld::ConstPtr, Object*> ObjectMap;
|
using ObjectMap = std::map<MWWorld::ConstPtr, std::shared_ptr<Object>>;
|
||||||
ObjectMap mObjects;
|
ObjectMap mObjects;
|
||||||
|
|
||||||
std::set<Object*> mAnimatedObjects; // stores pointers to elements in mObjects
|
std::set<Object*> mAnimatedObjects; // stores pointers to elements in mObjects
|
||||||
|
|
||||||
typedef std::map<MWWorld::ConstPtr, Actor*> ActorMap;
|
using ActorMap = std::map<MWWorld::ConstPtr, std::shared_ptr<Actor>>;
|
||||||
ActorMap mActors;
|
ActorMap mActors;
|
||||||
|
|
||||||
typedef std::map<std::pair<int, int>, HeightField*> HeightFieldMap;
|
using HeightFieldMap = std::map<std::pair<int, int>, HeightField *>;
|
||||||
HeightFieldMap mHeightFields;
|
HeightFieldMap mHeightFields;
|
||||||
|
|
||||||
bool mDebugDrawEnabled;
|
bool mDebugDrawEnabled;
|
||||||
|
|
||||||
// Tracks standing collisions happening during a single frame. <actor handle, collided handle>
|
// Tracks standing collisions happening during a single frame. <actor handle, collided handle>
|
||||||
// This will detect standing on an object, but won't detect running e.g. against a wall.
|
// This will detect standing on an object, but won't detect running e.g. against a wall.
|
||||||
typedef std::map<MWWorld::Ptr, MWWorld::Ptr> CollisionMap;
|
|
||||||
CollisionMap mStandingCollisions;
|
CollisionMap mStandingCollisions;
|
||||||
|
|
||||||
// replaces all occurrences of 'old' in the map by 'updated', no matter if it's a key or value
|
// replaces all occurrences of 'old' in the map by 'updated', no matter if it's a key or value
|
||||||
void updateCollisionMapPtr(CollisionMap& map, const MWWorld::Ptr &old, const MWWorld::Ptr &updated);
|
void updateCollisionMapPtr(CollisionMap& map, const MWWorld::Ptr &old, const MWWorld::Ptr &updated);
|
||||||
|
|
||||||
|
using PtrVelocityList = std::vector<std::pair<MWWorld::Ptr, osg::Vec3f>>;
|
||||||
PtrVelocityList mMovementQueue;
|
PtrVelocityList mMovementQueue;
|
||||||
PtrVelocityList mMovementResults;
|
PtrPositionList mMovementResults;
|
||||||
|
|
||||||
float mTimeAccum;
|
float mTimeAccum;
|
||||||
|
|
||||||
|
|
|
@ -1494,24 +1494,22 @@ namespace MWWorld
|
||||||
|
|
||||||
void World::doPhysics(float duration)
|
void World::doPhysics(float duration)
|
||||||
{
|
{
|
||||||
mPhysics->stepSimulation(duration);
|
mPhysics->stepSimulation();
|
||||||
processDoors(duration);
|
processDoors(duration);
|
||||||
|
|
||||||
mProjectileManager->update(duration);
|
mProjectileManager->update(duration);
|
||||||
|
|
||||||
const MWPhysics::PtrVelocityList &results = mPhysics->applyQueuedMovement(duration);
|
const auto results = mPhysics->applyQueuedMovement(duration);
|
||||||
MWPhysics::PtrVelocityList::const_iterator player(results.end());
|
|
||||||
for(MWPhysics::PtrVelocityList::const_iterator iter(results.begin());iter != results.end();++iter)
|
for(const auto& result : results)
|
||||||
{
|
{
|
||||||
if(iter->first == getPlayerPtr())
|
// Handle player last, in case a cell transition occurs
|
||||||
{
|
if(result.first != getPlayerPtr())
|
||||||
// Handle player last, in case a cell transition occurs
|
moveObjectImp(result.first, result.second.x(), result.second.y(), result.second.z(), false);
|
||||||
player = iter;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
moveObjectImp(iter->first, iter->second.x(), iter->second.y(), iter->second.z(), false);
|
|
||||||
}
|
}
|
||||||
if(player != results.end())
|
|
||||||
|
const auto player = results.find(getPlayerPtr());
|
||||||
|
if (player != results.end())
|
||||||
moveObjectImp(player->first, player->second.x(), player->second.y(), player->second.z(), false);
|
moveObjectImp(player->first, player->second.x(), player->second.y(), player->second.z(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue