1
0
Fork 0
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:
fredzio 2021-07-22 19:29:20 +02:00
parent 9e911cc8b5
commit f68273c3c0
4 changed files with 80 additions and 79 deletions

View file

@ -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;
} }
} }

View file

@ -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();
} }

View file

@ -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()

View file

@ -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