mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-20 02:53:53 +00:00
Remove Actor* from ActorFrameData
This commit is contained in:
parent
9e911cc8b5
commit
f68273c3c0
4 changed files with 80 additions and 79 deletions
|
@ -118,8 +118,6 @@ namespace MWPhysics
|
||||||
void MovementSolver::move(ActorFrameData& actor, float time, const btCollisionWorld* collisionWorld,
|
void MovementSolver::move(ActorFrameData& actor, float time, const btCollisionWorld* collisionWorld,
|
||||||
WorldFrameData& worldData)
|
WorldFrameData& worldData)
|
||||||
{
|
{
|
||||||
auto* physicActor = actor.mActorRaw;
|
|
||||||
|
|
||||||
// Reset per-frame data
|
// Reset per-frame data
|
||||||
actor.mWalkingOnWater = false;
|
actor.mWalkingOnWater = false;
|
||||||
// Anything to collide with?
|
// Anything to collide with?
|
||||||
|
@ -131,20 +129,16 @@ namespace MWPhysics
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const btCollisionObject *colobj = physicActor->getCollisionObject();
|
|
||||||
|
|
||||||
// Adjust for collision mesh offset relative to actor's "location"
|
// Adjust for collision mesh offset relative to actor's "location"
|
||||||
// (doTrace doesn't take local/interior collision shape translation into account, so we have to do it on our own)
|
// (doTrace doesn't take local/interior collision shape translation into account, so we have to do it on our own)
|
||||||
// for compatibility with vanilla assets, we have to derive this from the vertical half extent instead of from internal hull translation
|
// for compatibility with vanilla assets, we have to derive this from the vertical half extent instead of from internal hull translation
|
||||||
// if not for this hack, the "correct" collision hull position would be physicActor->getScaledMeshTranslation()
|
// if not for this hack, the "correct" collision hull position would be physicActor->getScaledMeshTranslation()
|
||||||
osg::Vec3f halfExtents = physicActor->getHalfExtents();
|
actor.mPosition.z() += actor.mHalfExtentsZ; // vanilla-accurate
|
||||||
actor.mPosition.z() += halfExtents.z(); // vanilla-accurate
|
|
||||||
|
|
||||||
float swimlevel = actor.mSwimLevel + halfExtents.z();
|
float swimlevel = actor.mSwimLevel + actor.mHalfExtentsZ;
|
||||||
|
|
||||||
ActorTracer tracer;
|
ActorTracer tracer;
|
||||||
|
|
||||||
osg::Vec3f inertia = physicActor->getInertialForce();
|
|
||||||
osg::Vec3f velocity;
|
osg::Vec3f velocity;
|
||||||
|
|
||||||
// Dead and paralyzed actors underwater will float to the surface,
|
// Dead and paralyzed actors underwater will float to the surface,
|
||||||
|
@ -162,10 +156,10 @@ namespace MWPhysics
|
||||||
velocity = (osg::Quat(actor.mRotation.y(), osg::Vec3f(0, 0, -1))) * actor.mMovement;
|
velocity = (osg::Quat(actor.mRotation.y(), osg::Vec3f(0, 0, -1))) * actor.mMovement;
|
||||||
|
|
||||||
if ((velocity.z() > 0.f && actor.mIsOnGround && !actor.mIsOnSlope)
|
if ((velocity.z() > 0.f && actor.mIsOnGround && !actor.mIsOnSlope)
|
||||||
|| (velocity.z() > 0.f && velocity.z() + inertia.z() <= -velocity.z() && actor.mIsOnSlope))
|
|| (velocity.z() > 0.f && velocity.z() + actor.mInertia.z() <= -velocity.z() && actor.mIsOnSlope))
|
||||||
inertia = velocity;
|
actor.mInertia = velocity;
|
||||||
else if (!actor.mIsOnGround || actor.mIsOnSlope)
|
else if (!actor.mIsOnGround || actor.mIsOnSlope)
|
||||||
velocity = velocity + inertia;
|
velocity = velocity + actor.mInertia;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we have the effective movement vector, apply wind forces to it
|
// Now that we have the effective movement vector, apply wind forces to it
|
||||||
|
@ -177,7 +171,7 @@ namespace MWPhysics
|
||||||
velocity *= 1.f-(fStromWalkMult * (angleDegrees/180.f));
|
velocity *= 1.f-(fStromWalkMult * (angleDegrees/180.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
Stepper stepper(collisionWorld, colobj);
|
Stepper stepper(collisionWorld, actor.mCollisionObject);
|
||||||
osg::Vec3f origVelocity = velocity;
|
osg::Vec3f origVelocity = velocity;
|
||||||
osg::Vec3f newPosition = actor.mPosition;
|
osg::Vec3f newPosition = actor.mPosition;
|
||||||
/*
|
/*
|
||||||
|
@ -209,7 +203,7 @@ namespace MWPhysics
|
||||||
if((newPosition - nextpos).length2() > 0.0001)
|
if((newPosition - nextpos).length2() > 0.0001)
|
||||||
{
|
{
|
||||||
// trace to where character would go if there were no obstructions
|
// trace to where character would go if there were no obstructions
|
||||||
tracer.doTrace(colobj, newPosition, nextpos, collisionWorld);
|
tracer.doTrace(actor.mCollisionObject, newPosition, nextpos, collisionWorld);
|
||||||
|
|
||||||
// check for obstructions
|
// check for obstructions
|
||||||
if(tracer.mFraction >= 1.0f)
|
if(tracer.mFraction >= 1.0f)
|
||||||
|
@ -233,7 +227,7 @@ namespace MWPhysics
|
||||||
bool seenGround = !actor.mFlying && !underwater && ((actor.mIsOnGround && !actor.mIsOnSlope) || isWalkableSlope(tracer.mPlaneNormal));
|
bool seenGround = !actor.mFlying && !underwater && ((actor.mIsOnGround && !actor.mIsOnSlope) || isWalkableSlope(tracer.mPlaneNormal));
|
||||||
|
|
||||||
// We hit something. Check if we can step up.
|
// We hit something. Check if we can step up.
|
||||||
float hitHeight = tracer.mHitPoint.z() - tracer.mEndPos.z() + halfExtents.z();
|
float hitHeight = tracer.mHitPoint.z() - tracer.mEndPos.z() + actor.mHalfExtentsZ;
|
||||||
osg::Vec3f oldPosition = newPosition;
|
osg::Vec3f oldPosition = newPosition;
|
||||||
bool usedStepLogic = false;
|
bool usedStepLogic = false;
|
||||||
if (hitHeight < sStepSizeUp && !isActor(tracer.mHitObject))
|
if (hitHeight < sStepSizeUp && !isActor(tracer.mHitObject))
|
||||||
|
@ -244,9 +238,7 @@ namespace MWPhysics
|
||||||
}
|
}
|
||||||
if (usedStepLogic)
|
if (usedStepLogic)
|
||||||
{
|
{
|
||||||
// don't let pure water creatures move out of water after stepMove
|
if (actor.mIsAquatic && newPosition.z() + actor.mHalfExtentsZ > actor.mWaterlevel)
|
||||||
const auto ptr = physicActor->getPtr();
|
|
||||||
if (ptr.getClass().isPureWaterCreature(ptr) && newPosition.z() + halfExtents.z() > actor.mWaterlevel)
|
|
||||||
newPosition = oldPosition;
|
newPosition = oldPosition;
|
||||||
else if(!actor.mFlying && actor.mPosition.z() >= swimlevel)
|
else if(!actor.mFlying && actor.mPosition.z() >= swimlevel)
|
||||||
forceGroundTest = true;
|
forceGroundTest = true;
|
||||||
|
@ -305,7 +297,7 @@ namespace MWPhysics
|
||||||
// version of surface rejection for acute crevices/seams
|
// version of surface rejection for acute crevices/seams
|
||||||
auto averageNormal = bestNormal + planeNormal;
|
auto averageNormal = bestNormal + planeNormal;
|
||||||
averageNormal.normalize();
|
averageNormal.normalize();
|
||||||
tracer.doTrace(colobj, newPosition, newPosition + averageNormal*(sCollisionMargin*2.0), collisionWorld);
|
tracer.doTrace(actor.mCollisionObject, newPosition, newPosition + averageNormal*(sCollisionMargin*2.0), collisionWorld);
|
||||||
newPosition = (newPosition + tracer.mEndPos)/2.0;
|
newPosition = (newPosition + tracer.mEndPos)/2.0;
|
||||||
|
|
||||||
usedSeamLogic = true;
|
usedSeamLogic = true;
|
||||||
|
@ -321,7 +313,7 @@ namespace MWPhysics
|
||||||
// but this is along the collision normal
|
// but this is along the collision normal
|
||||||
if(!usedSeamLogic && (iterations > 0 || remainingTime < 0.01f))
|
if(!usedSeamLogic && (iterations > 0 || remainingTime < 0.01f))
|
||||||
{
|
{
|
||||||
tracer.doTrace(colobj, newPosition, newPosition + planeNormal*(sCollisionMargin*2.0), collisionWorld);
|
tracer.doTrace(actor.mCollisionObject, newPosition, newPosition + planeNormal*(sCollisionMargin*2.0), collisionWorld);
|
||||||
newPosition = (newPosition + tracer.mEndPos)/2.0;
|
newPosition = (newPosition + tracer.mEndPos)/2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,12 +333,12 @@ namespace MWPhysics
|
||||||
|
|
||||||
bool isOnGround = false;
|
bool isOnGround = false;
|
||||||
bool isOnSlope = false;
|
bool isOnSlope = false;
|
||||||
if (forceGroundTest || (inertia.z() <= 0.f && newPosition.z() >= swimlevel))
|
if (forceGroundTest || (actor.mInertia.z() <= 0.f && newPosition.z() >= swimlevel))
|
||||||
{
|
{
|
||||||
osg::Vec3f from = newPosition;
|
osg::Vec3f from = newPosition;
|
||||||
auto dropDistance = 2*sGroundOffset + (actor.mIsOnGround ? sStepSizeDown : 0);
|
auto dropDistance = 2*sGroundOffset + (actor.mIsOnGround ? sStepSizeDown : 0);
|
||||||
osg::Vec3f to = newPosition - osg::Vec3f(0,0,dropDistance);
|
osg::Vec3f to = newPosition - osg::Vec3f(0,0,dropDistance);
|
||||||
tracer.doTrace(colobj, from, to, collisionWorld);
|
tracer.doTrace(actor.mCollisionObject, from, to, collisionWorld);
|
||||||
if(tracer.mFraction < 1.0f)
|
if(tracer.mFraction < 1.0f)
|
||||||
{
|
{
|
||||||
if (!isActor(tracer.mHitObject))
|
if (!isActor(tracer.mHitObject))
|
||||||
|
@ -368,7 +360,7 @@ namespace MWPhysics
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newPosition.z() = tracer.mEndPos.z();
|
newPosition.z() = tracer.mEndPos.z();
|
||||||
tracer.doTrace(colobj, newPosition, newPosition + osg::Vec3f(0, 0, 2*sGroundOffset), collisionWorld);
|
tracer.doTrace(actor.mCollisionObject, newPosition, newPosition + osg::Vec3f(0, 0, 2*sGroundOffset), collisionWorld);
|
||||||
newPosition = (newPosition+tracer.mEndPos)/2.0;
|
newPosition = (newPosition+tracer.mEndPos)/2.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -383,7 +375,7 @@ namespace MWPhysics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// forcibly treat stuck actors as if they're on flat ground because buggy collisions when inside of things can/will break ground detection
|
// forcibly treat stuck actors as if they're on flat ground because buggy collisions when inside of things can/will break ground detection
|
||||||
if(physicActor->getStuckFrames() > 0)
|
if(actor.mStuckFrames > 0)
|
||||||
{
|
{
|
||||||
isOnGround = true;
|
isOnGround = true;
|
||||||
isOnSlope = false;
|
isOnSlope = false;
|
||||||
|
@ -391,24 +383,23 @@ namespace MWPhysics
|
||||||
}
|
}
|
||||||
|
|
||||||
if((isOnGround && !isOnSlope) || newPosition.z() < swimlevel || actor.mFlying)
|
if((isOnGround && !isOnSlope) || newPosition.z() < swimlevel || actor.mFlying)
|
||||||
physicActor->setInertialForce(osg::Vec3f(0.f, 0.f, 0.f));
|
actor.mInertia = osg::Vec3f(0.f, 0.f, 0.f);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
inertia.z() -= time * Constants::GravityConst * Constants::UnitsPerMeter;
|
actor.mInertia.z() -= time * Constants::GravityConst * Constants::UnitsPerMeter;
|
||||||
if (inertia.z() < 0)
|
if (actor.mInertia.z() < 0)
|
||||||
inertia.z() *= actor.mSlowFall;
|
actor.mInertia.z() *= actor.mSlowFall;
|
||||||
if (actor.mSlowFall < 1.f) {
|
if (actor.mSlowFall < 1.f) {
|
||||||
inertia.x() *= actor.mSlowFall;
|
actor.mInertia.x() *= actor.mSlowFall;
|
||||||
inertia.y() *= actor.mSlowFall;
|
actor.mInertia.y() *= actor.mSlowFall;
|
||||||
}
|
}
|
||||||
physicActor->setInertialForce(inertia);
|
|
||||||
}
|
}
|
||||||
actor.mIsOnGround = isOnGround;
|
actor.mIsOnGround = isOnGround;
|
||||||
actor.mIsOnSlope = isOnSlope;
|
actor.mIsOnSlope = isOnSlope;
|
||||||
|
|
||||||
actor.mPosition = newPosition;
|
actor.mPosition = newPosition;
|
||||||
// remove what was added earlier in compensating for doTrace not taking interior transformation into account
|
// remove what was added earlier in compensating for doTrace not taking interior transformation into account
|
||||||
actor.mPosition.z() -= halfExtents.z(); // vanilla-accurate
|
actor.mPosition.z() -= actor.mHalfExtentsZ; // vanilla-accurate
|
||||||
}
|
}
|
||||||
|
|
||||||
btVector3 addMarginToDelta(btVector3 delta)
|
btVector3 addMarginToDelta(btVector3 delta)
|
||||||
|
@ -420,49 +411,47 @@ namespace MWPhysics
|
||||||
|
|
||||||
void MovementSolver::unstuck(ActorFrameData& actor, const btCollisionWorld* collisionWorld)
|
void MovementSolver::unstuck(ActorFrameData& actor, const btCollisionWorld* collisionWorld)
|
||||||
{
|
{
|
||||||
auto* physicActor = actor.mActorRaw;
|
|
||||||
if(actor.mSkipCollisionDetection) // noclipping/tcl
|
if(actor.mSkipCollisionDetection) // noclipping/tcl
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto* collisionObject = physicActor->getCollisionObject();
|
|
||||||
auto tempPosition = actor.mPosition;
|
auto tempPosition = actor.mPosition;
|
||||||
|
|
||||||
if(physicActor->getStuckFrames() >= 10)
|
if(actor.mStuckFrames >= 10)
|
||||||
{
|
{
|
||||||
if((physicActor->getLastStuckPosition() - actor.mPosition).length2() < 100)
|
if((actor.mLastStuckPosition - actor.mPosition).length2() < 100)
|
||||||
return;
|
return;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
physicActor->setStuckFrames(0);
|
actor.mStuckFrames = 0;
|
||||||
physicActor->setLastStuckPosition({0, 0, 0});
|
actor.mLastStuckPosition = {0, 0, 0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// use vanilla-accurate collision hull position hack (do same hitbox offset hack as movement solver)
|
// use vanilla-accurate collision hull position hack (do same hitbox offset hack as movement solver)
|
||||||
// if vanilla compatibility didn't matter, the "correct" collision hull position would be physicActor->getScaledMeshTranslation()
|
// if vanilla compatibility didn't matter, the "correct" collision hull position would be physicActor->getScaledMeshTranslation()
|
||||||
const auto verticalHalfExtent = osg::Vec3f(0.0, 0.0, physicActor->getHalfExtents().z());
|
const auto verticalHalfExtent = osg::Vec3f(0.0, 0.0, actor.mHalfExtentsZ);
|
||||||
|
|
||||||
// use a 3d approximation of the movement vector to better judge player intent
|
// use a 3d approximation of the movement vector to better judge player intent
|
||||||
auto velocity = (osg::Quat(actor.mRotation.x(), osg::Vec3f(-1, 0, 0)) * osg::Quat(actor.mRotation.y(), osg::Vec3f(0, 0, -1))) * actor.mMovement;
|
auto velocity = (osg::Quat(actor.mRotation.x(), osg::Vec3f(-1, 0, 0)) * osg::Quat(actor.mRotation.y(), osg::Vec3f(0, 0, -1))) * actor.mMovement;
|
||||||
// try to pop outside of the world before doing anything else if we're inside of it
|
// try to pop outside of the world before doing anything else if we're inside of it
|
||||||
if (!actor.mIsOnGround || actor.mIsOnSlope)
|
if (!actor.mIsOnGround || actor.mIsOnSlope)
|
||||||
velocity += physicActor->getInertialForce();
|
velocity += actor.mInertia;
|
||||||
|
|
||||||
// because of the internal collision box offset hack, and the fact that we're moving the collision box manually,
|
// because of the internal collision box offset hack, and the fact that we're moving the collision box manually,
|
||||||
// we need to replicate part of the collision box's transform process from scratch
|
// we need to replicate part of the collision box's transform process from scratch
|
||||||
osg::Vec3f refPosition = tempPosition + verticalHalfExtent;
|
osg::Vec3f refPosition = tempPosition + verticalHalfExtent;
|
||||||
osg::Vec3f goodPosition = refPosition;
|
osg::Vec3f goodPosition = refPosition;
|
||||||
const btTransform oldTransform = collisionObject->getWorldTransform();
|
const btTransform oldTransform = actor.mCollisionObject->getWorldTransform();
|
||||||
btTransform newTransform = oldTransform;
|
btTransform newTransform = oldTransform;
|
||||||
|
|
||||||
auto gatherContacts = [&](btVector3 newOffset) -> ContactCollectionCallback
|
auto gatherContacts = [&](btVector3 newOffset) -> ContactCollectionCallback
|
||||||
{
|
{
|
||||||
goodPosition = refPosition + Misc::Convert::toOsg(addMarginToDelta(newOffset));
|
goodPosition = refPosition + Misc::Convert::toOsg(addMarginToDelta(newOffset));
|
||||||
newTransform.setOrigin(Misc::Convert::toBullet(goodPosition));
|
newTransform.setOrigin(Misc::Convert::toBullet(goodPosition));
|
||||||
collisionObject->setWorldTransform(newTransform);
|
actor.mCollisionObject->setWorldTransform(newTransform);
|
||||||
|
|
||||||
ContactCollectionCallback callback{collisionObject, velocity};
|
ContactCollectionCallback callback{actor.mCollisionObject, velocity};
|
||||||
ContactTestWrapper::contactTest(const_cast<btCollisionWorld*>(collisionWorld), collisionObject, callback);
|
ContactTestWrapper::contactTest(const_cast<btCollisionWorld*>(collisionWorld), actor.mCollisionObject, callback);
|
||||||
return callback;
|
return callback;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -470,8 +459,8 @@ namespace MWPhysics
|
||||||
auto contactCallback = gatherContacts({0.0, 0.0, 0.0});
|
auto contactCallback = gatherContacts({0.0, 0.0, 0.0});
|
||||||
if(contactCallback.mDistance < -sAllowedPenetration)
|
if(contactCallback.mDistance < -sAllowedPenetration)
|
||||||
{
|
{
|
||||||
physicActor->setStuckFrames(physicActor->getStuckFrames() + 1);
|
++actor.mStuckFrames;
|
||||||
physicActor->setLastStuckPosition(actor.mPosition);
|
actor.mLastStuckPosition = actor.mPosition;
|
||||||
// we are; try moving it out of the world
|
// we are; try moving it out of the world
|
||||||
auto positionDelta = contactCallback.mContactSum;
|
auto positionDelta = contactCallback.mContactSum;
|
||||||
// limit rejection delta to the largest known individual rejections
|
// limit rejection delta to the largest known individual rejections
|
||||||
|
@ -506,11 +495,11 @@ namespace MWPhysics
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
physicActor->setStuckFrames(0);
|
actor.mStuckFrames = 0;
|
||||||
physicActor->setLastStuckPosition({0, 0, 0});
|
actor.mLastStuckPosition = {0, 0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
collisionObject->setWorldTransform(oldTransform);
|
actor.mCollisionObject->setWorldTransform(oldTransform);
|
||||||
actor.mPosition = tempPosition;
|
actor.mPosition = tempPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,9 +66,9 @@ namespace
|
||||||
actorData.mFallHeight += heightDiff;
|
actorData.mFallHeight += heightDiff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateMechanics(MWPhysics::ActorFrameData& actorData)
|
void updateMechanics(MWPhysics::Actor& actor, MWPhysics::ActorFrameData& actorData)
|
||||||
{
|
{
|
||||||
auto ptr = actorData.mActorRaw->getPtr();
|
auto ptr = actor.getPtr();
|
||||||
|
|
||||||
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
if (actorData.mNeedLand)
|
if (actorData.mNeedLand)
|
||||||
|
@ -77,21 +77,24 @@ namespace
|
||||||
stats.addToFallHeight(-actorData.mFallHeight);
|
stats.addToFallHeight(-actorData.mFallHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec3f interpolateMovements(MWPhysics::ActorFrameData& actorData, float timeAccum, float physicsDt)
|
osg::Vec3f interpolateMovements(MWPhysics::Actor& actor, MWPhysics::ActorFrameData& actorData, float timeAccum, float physicsDt)
|
||||||
{
|
{
|
||||||
const float interpolationFactor = std::clamp(timeAccum / physicsDt, 0.0f, 1.0f);
|
const float interpolationFactor = std::clamp(timeAccum / physicsDt, 0.0f, 1.0f);
|
||||||
return actorData.mPosition * interpolationFactor + actorData.mActorRaw->getPreviousPosition() * (1.f - interpolationFactor);
|
return actorData.mPosition * interpolationFactor + actor.getPreviousPosition() * (1.f - interpolationFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateActor(MWPhysics::ActorFrameData& actorData, bool simulationPerformed, float timeAccum, float dt)
|
void updateActor(MWPhysics::Actor& actor, MWPhysics::ActorFrameData& actorData, bool simulationPerformed, float timeAccum, float dt)
|
||||||
{
|
{
|
||||||
actorData.mActorRaw->setSimulationPosition(interpolateMovements(actorData, timeAccum, dt));
|
actor.setSimulationPosition(interpolateMovements(actor, actorData, timeAccum, dt));
|
||||||
|
actor.setLastStuckPosition(actorData.mLastStuckPosition);
|
||||||
|
actor.setStuckFrames(actorData.mStuckFrames);
|
||||||
if (simulationPerformed)
|
if (simulationPerformed)
|
||||||
{
|
{
|
||||||
actorData.mActorRaw->setStandingOnPtr(actorData.mStandingOn);
|
actor.setStandingOnPtr(actorData.mStandingOn);
|
||||||
actorData.mActorRaw->setOnGround(actorData.mIsOnGround);
|
actor.setOnGround(actorData.mIsOnGround);
|
||||||
actorData.mActorRaw->setOnSlope(actorData.mIsOnSlope);
|
actor.setOnSlope(actorData.mIsOnSlope);
|
||||||
actorData.mActorRaw->setWalkingOnWater(actorData.mWalkingOnWater);
|
actor.setWalkingOnWater(actorData.mWalkingOnWater);
|
||||||
|
actor.setInertialForce(actorData.mInertia);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,16 +236,10 @@ namespace MWPhysics
|
||||||
{
|
{
|
||||||
for (auto& data : mActorsFrameData)
|
for (auto& data : mActorsFrameData)
|
||||||
{
|
{
|
||||||
const auto actorActive = [&data](const auto& newFrameData) -> bool
|
if (auto actor = data.mActor.lock())
|
||||||
{
|
{
|
||||||
const auto actor = data.mActor.lock();
|
updateMechanics(*actor, data);
|
||||||
return actor && actor->getPtr() == newFrameData.mActorRaw->getPtr();
|
updateActor(*actor, data, mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
||||||
};
|
|
||||||
// Only return actors that are still part of the scene
|
|
||||||
if (std::any_of(actorsData.begin(), actorsData.end(), actorActive))
|
|
||||||
{
|
|
||||||
updateMechanics(data);
|
|
||||||
updateActor(data, mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(mAdvanceSimulation)
|
if(mAdvanceSimulation)
|
||||||
|
@ -255,7 +252,10 @@ namespace MWPhysics
|
||||||
|
|
||||||
// init
|
// init
|
||||||
for (auto& data : actorsData)
|
for (auto& data : actorsData)
|
||||||
data.updatePosition(mCollisionWorld);
|
{
|
||||||
|
assert(data.mActor.lock());
|
||||||
|
data.updatePosition(*data.mActor.lock(), mCollisionWorld);
|
||||||
|
}
|
||||||
mPrevStepCount = numSteps;
|
mPrevStepCount = numSteps;
|
||||||
mRemainingSteps = numSteps;
|
mRemainingSteps = numSteps;
|
||||||
mTimeAccum = timeAccum;
|
mTimeAccum = timeAccum;
|
||||||
|
@ -536,9 +536,11 @@ namespace MWPhysics
|
||||||
|
|
||||||
for (auto& actorData : mActorsFrameData)
|
for (auto& actorData : mActorsFrameData)
|
||||||
{
|
{
|
||||||
|
auto actor = actorData.mActor.lock();
|
||||||
|
assert(actor);
|
||||||
handleFall(actorData, mAdvanceSimulation);
|
handleFall(actorData, mAdvanceSimulation);
|
||||||
updateMechanics(actorData);
|
updateMechanics(*actor, actorData);
|
||||||
updateActor(actorData, mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
updateActor(*actor, actorData, mAdvanceSimulation, mTimeAccum, mPhysicsDt);
|
||||||
}
|
}
|
||||||
refreshLOSCache();
|
refreshLOSCache();
|
||||||
}
|
}
|
||||||
|
|
|
@ -987,7 +987,7 @@ namespace MWPhysics
|
||||||
ActorFrameData::ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn,
|
ActorFrameData::ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn,
|
||||||
bool waterCollision, float slowFall, float waterlevel)
|
bool waterCollision, float slowFall, float waterlevel)
|
||||||
: mActor(actor)
|
: mActor(actor)
|
||||||
, mActorRaw(actor.get())
|
, mCollisionObject(actor->getCollisionObject())
|
||||||
, mStandingOn(standingOn)
|
, mStandingOn(standingOn)
|
||||||
, mWasOnGround(actor->getOnGround())
|
, mWasOnGround(actor->getOnGround())
|
||||||
, mIsOnGround(actor->getOnGround())
|
, mIsOnGround(actor->getOnGround())
|
||||||
|
@ -1000,6 +1000,7 @@ namespace MWPhysics
|
||||||
, mSlowFall(slowFall)
|
, mSlowFall(slowFall)
|
||||||
, mOldHeight(0)
|
, mOldHeight(0)
|
||||||
, mFallHeight(0)
|
, mFallHeight(0)
|
||||||
|
, mHalfExtentsZ(actor->getHalfExtents().z())
|
||||||
, mMovement(actor->velocity())
|
, mMovement(actor->velocity())
|
||||||
, mPosition()
|
, mPosition()
|
||||||
, mRotation()
|
, mRotation()
|
||||||
|
@ -1007,6 +1008,7 @@ namespace MWPhysics
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
const auto ptr = actor->getPtr();
|
const auto ptr = actor->getPtr();
|
||||||
mFlying = world->isFlying(ptr);
|
mFlying = world->isFlying(ptr);
|
||||||
|
mIsAquatic = ptr.getClass().isPureWaterCreature(ptr);
|
||||||
const auto& stats = ptr.getClass().getCreatureStats(ptr);
|
const auto& stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
const bool godmode = ptr == world->getPlayerConstPtr() && world->getGodModeState();
|
const bool godmode = ptr == world->getPlayerConstPtr() && world->getGodModeState();
|
||||||
mInert = stats.isDead() || (!godmode && stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getModifier() > 0);
|
mInert = stats.isDead() || (!godmode && stats.getMagicEffects().get(ESM::MagicEffect::Paralyze).getModifier() > 0);
|
||||||
|
@ -1014,18 +1016,21 @@ namespace MWPhysics
|
||||||
mSwimLevel = mWaterlevel - (actor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
|
mSwimLevel = mWaterlevel - (actor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActorFrameData::updatePosition(btCollisionWorld* world)
|
void ActorFrameData::updatePosition(Actor& actor, btCollisionWorld* world)
|
||||||
{
|
{
|
||||||
mActorRaw->applyOffsetChange();
|
actor.applyOffsetChange();
|
||||||
mPosition = mActorRaw->getPosition();
|
mPosition = actor.getPosition();
|
||||||
if (mWaterCollision && mPosition.z() < mWaterlevel && canMoveToWaterSurface(mActorRaw, mWaterlevel, world))
|
if (mWaterCollision && mPosition.z() < mWaterlevel && canMoveToWaterSurface(&actor, mWaterlevel, world))
|
||||||
{
|
{
|
||||||
mPosition.z() = mWaterlevel;
|
mPosition.z() = mWaterlevel;
|
||||||
MWBase::Environment::get().getWorld()->moveObject(mActorRaw->getPtr(), mPosition, false);
|
MWBase::Environment::get().getWorld()->moveObject(actor.getPtr(), mPosition, false);
|
||||||
}
|
}
|
||||||
mOldHeight = mPosition.z();
|
mOldHeight = mPosition.z();
|
||||||
const auto rotation = mActorRaw->getPtr().getRefData().getPosition().asRotationVec3();
|
const auto rotation = actor.getPtr().getRefData().getPosition().asRotationVec3();
|
||||||
mRotation = osg::Vec2f(rotation.x(), rotation.z());
|
mRotation = osg::Vec2f(rotation.x(), rotation.z());
|
||||||
|
mInertia = actor.getInertialForce();
|
||||||
|
mStuckFrames = actor.getStuckFrames();
|
||||||
|
mLastStuckPosition = actor.getLastStuckPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
WorldFrameData::WorldFrameData()
|
WorldFrameData::WorldFrameData()
|
||||||
|
|
|
@ -79,9 +79,9 @@ namespace MWPhysics
|
||||||
struct ActorFrameData
|
struct ActorFrameData
|
||||||
{
|
{
|
||||||
ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, float slowFall, float waterlevel);
|
ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, float slowFall, float waterlevel);
|
||||||
void updatePosition(btCollisionWorld* world);
|
void updatePosition(Actor& actor, btCollisionWorld* world);
|
||||||
std::weak_ptr<Actor> mActor;
|
std::weak_ptr<Actor> mActor;
|
||||||
Actor* mActorRaw;
|
btCollisionObject* mCollisionObject;
|
||||||
MWWorld::Ptr mStandingOn;
|
MWWorld::Ptr mStandingOn;
|
||||||
bool mFlying;
|
bool mFlying;
|
||||||
bool mWasOnGround;
|
bool mWasOnGround;
|
||||||
|
@ -89,17 +89,22 @@ namespace MWPhysics
|
||||||
bool mIsOnSlope;
|
bool mIsOnSlope;
|
||||||
bool mInert;
|
bool mInert;
|
||||||
bool mNeedLand;
|
bool mNeedLand;
|
||||||
|
bool mIsAquatic;
|
||||||
bool mWaterCollision;
|
bool mWaterCollision;
|
||||||
bool mWalkingOnWater;
|
bool mWalkingOnWater;
|
||||||
bool mSkipCollisionDetection;
|
bool mSkipCollisionDetection;
|
||||||
|
unsigned int mStuckFrames;
|
||||||
float mWaterlevel;
|
float mWaterlevel;
|
||||||
float mSwimLevel;
|
float mSwimLevel;
|
||||||
float mSlowFall;
|
float mSlowFall;
|
||||||
float mOldHeight;
|
float mOldHeight;
|
||||||
float mFallHeight;
|
float mFallHeight;
|
||||||
|
float mHalfExtentsZ;
|
||||||
osg::Vec3f mMovement;
|
osg::Vec3f mMovement;
|
||||||
osg::Vec3f mPosition;
|
osg::Vec3f mPosition;
|
||||||
osg::Vec2f mRotation;
|
osg::Vec2f mRotation;
|
||||||
|
osg::Vec3f mInertia;
|
||||||
|
osg::Vec3f mLastStuckPosition;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WorldFrameData
|
struct WorldFrameData
|
||||||
|
|
Loading…
Reference in a new issue