diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 4b4ffd0d3..38d8a0998 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -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. diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 10d609384..b8d0a8745 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -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); } } diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index a289a9174..69878a000 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -28,8 +28,6 @@ namespace MWMechanics typedef std::map PtrControllerMap; PtrControllerMap mActors; - MWWorld::PtrMovementList mMovement; - std::map mDeathCount; float mDuration; diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 1b220e65f..04e4185ba 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -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; } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 34d778fea..b631f9980 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -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(); diff --git a/apps/openmw/mwmechanics/objects.cpp b/apps/openmw/mwmechanics/objects.cpp index e0c0c756b..694987855 100644 --- a/apps/openmw/mwmechanics/objects.cpp +++ b/apps/openmw/mwmechanics/objects.cpp @@ -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); } } diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index 0ae3e6fb2..94eba704c 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -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(); } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index bd234c0b6..af3f35464 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -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 (); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index b2f6418a3..2f9629f57 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -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.