Apply movement by queueing it to do later

actorid
Chris Robinson 12 years ago
parent 96bab88da6
commit 9d56e2d86d

@ -250,8 +250,9 @@ namespace MWBase
virtual void positionToIndex (float x, float y, int &cellX, int &cellY) const = 0;
///< Convert position to cell numbers
virtual void doPhysics (const MWWorld::PtrMovementList &actors, float duration) = 0;
///< Run physics simulation and modify \a world accordingly.
virtual void queueMovement(const MWWorld::Ptr &ptr, const Ogre::Vector3 &velocity) = 0;
///< Queues movement for \a ptr (in local space), to be applied in the next call to
/// doPhysics.
virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2) = 0;
///< cast a Ray and return true if there is an object in the ray path.

@ -300,17 +300,8 @@ namespace MWMechanics
if(!paused)
{
mMovement.reserve(mActors.size());
for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter)
{
Movement movement;
iter->second->update(duration, movement);
mMovement.push_back(std::make_pair(iter->first, movement));
}
MWBase::Environment::get().getWorld()->doPhysics(mMovement, duration);
mMovement.clear();
iter->second->update(duration);
}
}

@ -28,8 +28,6 @@ namespace MWMechanics
typedef std::map<MWWorld::Ptr,CharacterController*> PtrControllerMap;
PtrControllerMap mActors;
MWWorld::PtrMovementList mMovement;
std::map<std::string, int> mDeathCount;
float mDuration;

@ -663,9 +663,11 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
return forcestateupdate;
}
void CharacterController::update(float duration, Movement &movement)
void CharacterController::update(float duration)
{
MWBase::World *world = MWBase::Environment::get().getWorld();
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
Ogre::Vector3 movement(0.0f);
if(!cls.isActor())
{
@ -684,8 +686,6 @@ void CharacterController::update(float duration, Movement &movement)
}
else if(!cls.getCreatureStats(mPtr).isDead())
{
MWBase::World *world = MWBase::Environment::get().getWorld();
bool onground = world->isOnGround(mPtr);
bool inwater = world->isSwimming(mPtr);
bool isrunning = cls.getStance(mPtr, MWWorld::Class::Run);
@ -796,45 +796,41 @@ void CharacterController::update(float duration, Movement &movement)
}
}
vec *= duration;
movement.mPosition[0] += vec.x;
movement.mPosition[1] += vec.y;
movement.mPosition[2] += vec.z;
rot *= duration;
movement.mRotation[0] += rot.x;
movement.mRotation[1] += rot.y;
movement.mRotation[2] += rot.z;
if(cls.isNpc())
forcestateupdate = updateNpcState(onground, inwater, isrunning, sneak);
refreshCurrentAnims(idlestate, movestate, forcestateupdate);
rot *= duration * Ogre::Math::RadiansToDegrees(1.0f);
world->rotateObject(mPtr, rot.x, rot.y, rot.z, true);
world->queueMovement(mPtr, vec);
movement = vec;
}
else if(cls.getCreatureStats(mPtr).isDead())
{
MWBase::Environment::get().getWorld()->enableActorCollision(mPtr, false);
world->queueMovement(mPtr, Ogre::Vector3(0.0f));
}
if(mAnimation && !mSkipAnim)
{
Ogre::Vector3 moved = mAnimation->runAnimation(duration);
Ogre::Vector3 moved = mAnimation->runAnimation(duration) / duration;
// Ensure we're moving in generally the right direction
if(mMovementSpeed > 0.f)
{
if((movement.mPosition[0] < 0.0f && movement.mPosition[0] < moved.x*2.0f) ||
(movement.mPosition[0] > 0.0f && movement.mPosition[0] > moved.x*2.0f))
moved.x = movement.mPosition[0];
if((movement.mPosition[1] < 0.0f && movement.mPosition[1] < moved.y*2.0f) ||
(movement.mPosition[1] > 0.0f && movement.mPosition[1] > moved.y*2.0f))
moved.y = movement.mPosition[1];
if((movement.mPosition[2] < 0.0f && movement.mPosition[2] < moved.z*2.0f) ||
(movement.mPosition[2] > 0.0f && movement.mPosition[2] > moved.z*2.0f))
moved.z = movement.mPosition[2];
if((movement.x < 0.0f && movement.x < moved.x*2.0f) ||
(movement.x > 0.0f && movement.x > moved.x*2.0f))
moved.x = movement.x;
if((movement.y < 0.0f && movement.y < moved.y*2.0f) ||
(movement.y > 0.0f && movement.y > moved.y*2.0f))
moved.y = movement.y;
if((movement.z < 0.0f && movement.z < moved.z*2.0f) ||
(movement.z > 0.0f && movement.z > moved.z*2.0f))
moved.z = movement.z;
}
movement.mPosition[0] = moved.x;
movement.mPosition[1] = moved.y;
movement.mPosition[2] = moved.z;
if(moved.squaredLength() > 1.0f)
world->queueMovement(mPtr, moved);
}
mSkipAnim = false;
}

@ -164,7 +164,7 @@ public:
void updatePtr(const MWWorld::Ptr &ptr);
void update(float duration, Movement &movement);
void update(float duration);
void playGroup(const std::string &groupname, int mode, int count);
void skipAnim();

@ -65,10 +65,7 @@ void Objects::update(float duration, bool paused)
if(!paused)
{
for(PtrControllerMap::iterator iter(mObjects.begin());iter != mObjects.end();++iter)
{
Movement movement;
iter->second->update(duration, movement);
}
iter->second->update(duration);
}
}

@ -124,7 +124,7 @@ namespace MWWorld
return position + (Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z)*
Ogre::Quaternion(Ogre::Radian(-refpos.rot[1]), Ogre::Vector3::UNIT_Y)*
Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) *
movement;
movement * time;
}
btCollisionObject *colobj = physicActor->getCollisionBody();
@ -140,7 +140,7 @@ namespace MWWorld
velocity = (Ogre::Quaternion(Ogre::Radian( -refpos.rot[2]), Ogre::Vector3::UNIT_Z)*
Ogre::Quaternion(Ogre::Radian( -refpos.rot[1]), Ogre::Vector3::UNIT_Y)*
Ogre::Quaternion(Ogre::Radian( refpos.rot[0]), Ogre::Vector3::UNIT_X)) *
movement / time;
movement;
}
else
{
@ -150,7 +150,7 @@ namespace MWWorld
if(tracer.mFraction < 1.0f && getSlope(tracer.mPlaneNormal) <= sMaxSlope)
onground = true;
}
velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z)*movement / time;
velocity = Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z) * movement;
velocity.z += physicActor->getVerticalForce();
}

@ -1083,7 +1083,12 @@ namespace MWWorld
--cellY;
}
void World::doPhysics(const PtrMovementList &actors, float duration)
void World::queueMovement(const Ptr &ptr, const Vector3 &velocity)
{
mPhysics->queueObjectMovement(ptr, velocity);
}
void World::doPhysics(float duration)
{
/* No duration? Shouldn't be any movement, then. */
if(duration <= 0.0f)
@ -1091,8 +1096,9 @@ namespace MWWorld
processDoors(duration);
PtrMovementList::const_iterator player(actors.end());
for(PtrMovementList::const_iterator iter(actors.begin());iter != actors.end();iter++)
const PtrVelocityList &results = mPhysics->applyQueuedMovement(duration);
PtrVelocityList::const_iterator player(results.end());
for(PtrVelocityList::const_iterator iter(results.begin());iter != results.end();iter++)
{
if(iter->first.getRefData().getHandle() == "player")
{
@ -1100,23 +1106,12 @@ namespace MWWorld
player = iter;
continue;
}
rotateObjectImp(iter->first, Ogre::Vector3(iter->second.mRotation), true);
Ogre::Vector3 vec = mPhysics->move(iter->first, Ogre::Vector3(iter->second.mPosition), duration,
!isSwimming(iter->first) && !isFlying(iter->first));
moveObjectImp(iter->first, vec.x, vec.y, vec.z);
}
if(player != actors.end())
{
rotateObjectImp(player->first, Ogre::Vector3(player->second.mRotation), true);
Ogre::Vector3 vec = mPhysics->move(player->first, Ogre::Vector3(player->second.mPosition), duration,
!isSwimming(player->first) && !isFlying(player->first));
moveObjectImp(player->first, vec.x, vec.y, vec.z);
moveObjectImp(iter->first, iter->second.x, iter->second.y, iter->second.z);
}
if(player != results.end())
moveObjectImp(player->first, player->second.x, player->second.y, player->second.z);
mPhysEngine->stepSimulation (duration);
mPhysEngine->stepSimulation(duration);
}
bool World::castRay (float x1, float y1, float z1, float x2, float y2, float z2)
@ -1261,6 +1256,8 @@ namespace MWWorld
mWorldScene->update (duration, paused);
doPhysics (duration);
performUpdateSceneQueries ();
updateWindowManager ();

@ -106,6 +106,9 @@ namespace MWWorld
void processDoors(float duration);
///< Run physics simulation and modify \a world accordingly.
void doPhysics(float duration);
///< Run physics simulation and modify \a world accordingly.
void ensureNeededRecords();
int mPlayIntro;
@ -276,8 +279,9 @@ namespace MWWorld
virtual void positionToIndex (float x, float y, int &cellX, int &cellY) const;
///< Convert position to cell numbers
virtual void doPhysics(const PtrMovementList &actors, float duration);
///< Run physics simulation and modify \a world accordingly.
virtual void queueMovement(const Ptr &ptr, const Ogre::Vector3 &velocity);
///< Queues movement for \a ptr (in local space), to be applied in the next call to
/// doPhysics.
virtual bool castRay (float x1, float y1, float z1, float x2, float y2, float z2);
///< cast a Ray and return true if there is an object in the ray path.

Loading…
Cancel
Save