mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 17:26:38 +00:00 
			
		
		
		
	Move the movement solver code to mwworld's physics system
This commit is contained in:
		
							parent
							
								
									0a4568bd11
								
							
						
					
					
						commit
						2c39760bd5
					
				
					 9 changed files with 184 additions and 229 deletions
				
			
		|  | @ -64,7 +64,7 @@ add_openmw_dir (mwclass | |||
| add_openmw_dir (mwmechanics | ||||
|     mechanicsmanagerimp stat character creaturestats magiceffects movement actors activators | ||||
|     drawstate spells activespells npcstats aipackage aisequence alchemy aiwander aitravel aifollow | ||||
|     aiescort aiactivate movementsolver | ||||
|     aiescort aiactivate | ||||
|     ) | ||||
| 
 | ||||
| add_openmw_dir (mwbase | ||||
|  |  | |||
|  | @ -265,6 +265,7 @@ namespace MWMechanics | |||
|                 Ogre::Vector3 movement = iter->second.update(duration); | ||||
|                 mMovement.push_back(std::make_pair(iter->first, movement)); | ||||
|             } | ||||
|             MWBase::Environment::get().getWorld()->doPhysics(mMovement, duration); | ||||
| 
 | ||||
|             mMovement.clear(); | ||||
|         } | ||||
|  |  | |||
|  | @ -29,8 +29,6 @@ | |||
| 
 | ||||
| #include "../mwworld/class.hpp" | ||||
| 
 | ||||
| #include "movementsolver.hpp" | ||||
| 
 | ||||
| 
 | ||||
| namespace MWMechanics | ||||
| { | ||||
|  | @ -79,7 +77,6 @@ static void getStateInfo(CharacterState state, std::string *group) | |||
| CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop) | ||||
|   : mPtr(ptr), mAnimation(anim), mState(state), mSkipAnim(false) | ||||
| { | ||||
|     mMovementSolver = new MovementSolver(); | ||||
|     if(!mAnimation) | ||||
|         return; | ||||
| 
 | ||||
|  | @ -98,7 +95,6 @@ CharacterController::CharacterController(const CharacterController &rhs) | |||
|   , mCurrentGroup(rhs.mCurrentGroup), mState(rhs.mState) | ||||
|   , mSkipAnim(rhs.mSkipAnim) | ||||
| { | ||||
|     mMovementSolver = new MovementSolver(); | ||||
|     if(!mAnimation) | ||||
|         return; | ||||
|     /* We've been copied. Update the animation with the new controller. */ | ||||
|  | @ -107,7 +103,6 @@ CharacterController::CharacterController(const CharacterController &rhs) | |||
| 
 | ||||
| CharacterController::~CharacterController() | ||||
| { | ||||
|     delete mMovementSolver; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -181,21 +176,14 @@ Ogre::Vector3 CharacterController::update(float duration) | |||
|     } | ||||
|     mSkipAnim = false; | ||||
| 
 | ||||
|     if(duration > 0.0f) | ||||
|     { | ||||
|         const ESM::Position &refpos = mPtr.getRefData().getPosition(); | ||||
|     const ESM::Position &refpos = mPtr.getRefData().getPosition(); | ||||
|     // Rotates first around z, then y, then x
 | ||||
|     movement = (Ogre::Quaternion(Ogre::Radian(-refpos.rot[0]), Ogre::Vector3::UNIT_X)* | ||||
|                 Ogre::Quaternion(Ogre::Radian(-refpos.rot[1]), Ogre::Vector3::UNIT_Y)* | ||||
|                 Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z)) * | ||||
|                 movement; | ||||
| 
 | ||||
|         // Rotates first around z, then y, then x
 | ||||
|         movement = (Ogre::Quaternion(Ogre::Radian(-refpos.rot[0]), Ogre::Vector3::UNIT_X)* | ||||
|                     Ogre::Quaternion(Ogre::Radian(-refpos.rot[1]), Ogre::Vector3::UNIT_Y)* | ||||
|                     Ogre::Quaternion(Ogre::Radian(-refpos.rot[2]), Ogre::Vector3::UNIT_Z)) * | ||||
|                    movement; | ||||
| 
 | ||||
|         Ogre::Vector3 res = mMovementSolver->move(mPtr, movement, duration); | ||||
|         MWBase::Environment::get().getWorld()->moveObject(mPtr, res.x, res.y, res.z); | ||||
|     } | ||||
| 
 | ||||
|     return Ogre::Vector3(0.0f); | ||||
|     return movement; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,8 +13,6 @@ namespace MWRender | |||
| namespace MWMechanics | ||||
| { | ||||
| 
 | ||||
| class MovementSolver; | ||||
| 
 | ||||
| enum CharacterState { | ||||
|     CharState_Idle, | ||||
|     CharState_Idle2, | ||||
|  | @ -51,8 +49,6 @@ class CharacterController | |||
|     CharacterState mState; | ||||
|     bool mSkipAnim; | ||||
| 
 | ||||
|     MovementSolver *mMovementSolver; | ||||
| 
 | ||||
| protected: | ||||
|     /* Called by the animation whenever a new text key is reached. */ | ||||
|     void markerEvent(float time, const std::string &evt); | ||||
|  |  | |||
|  | @ -1,164 +0,0 @@ | |||
| #include "movementsolver.hpp" | ||||
| 
 | ||||
| #include "libs/openengine/bullet/trace.h" | ||||
| #include "libs/openengine/bullet/physic.hpp" | ||||
| 
 | ||||
| #include "../mwworld/ptr.hpp" | ||||
| #include "../mwbase/environment.hpp" | ||||
| #include "../mwbase/world.hpp" | ||||
| 
 | ||||
| #include <cmath> | ||||
| 
 | ||||
| 
 | ||||
| namespace MWMechanics | ||||
| { | ||||
| 
 | ||||
| static const float sMaxSlope = 45.0f; | ||||
| 
 | ||||
| MovementSolver::MovementSolver() | ||||
|   : mEngine(MWBase::Environment::get().getWorld()->getPhysicEngine()) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| MovementSolver::~MovementSolver() | ||||
| { | ||||
|     // nothing to do
 | ||||
| } | ||||
| 
 | ||||
| void MovementSolver::clipVelocity(const Ogre::Vector3& in, const Ogre::Vector3& normal, Ogre::Vector3& out, const float overbounce) | ||||
| { | ||||
|     //Math stuff. Basically just project the velocity vector onto the plane represented by the normal.
 | ||||
|     //More specifically, it projects velocity onto the normal, takes that result, multiplies it by overbounce and then subtracts it from velocity.
 | ||||
|     float backoff; | ||||
| 
 | ||||
|     backoff = in.dotProduct(normal); | ||||
|     if(backoff < 0.0f) | ||||
|         backoff *= overbounce; | ||||
|     else | ||||
|         backoff /= overbounce; | ||||
| 
 | ||||
|     out = in - (normal*backoff); | ||||
| } | ||||
| 
 | ||||
| void MovementSolver::projectVelocity(Ogre::Vector3& velocity, const Ogre::Vector3& direction) | ||||
| { | ||||
|     Ogre::Vector3 normalizedDirection(direction); | ||||
|     normalizedDirection.normalise(); | ||||
| 
 | ||||
|     // no divide by normalizedDirection.length necessary because it's normalized
 | ||||
|     velocity = normalizedDirection * velocity.dotProduct(normalizedDirection); | ||||
| } | ||||
| 
 | ||||
| bool MovementSolver::stepMove(Ogre::Vector3& position, const Ogre::Vector3 &velocity, float remainingTime, float verticalRotation, const Ogre::Vector3 &halfExtents, bool isInterior) | ||||
| { | ||||
|     traceResults trace; // no initialization needed
 | ||||
| 
 | ||||
|     newtrace(&trace, position+Ogre::Vector3(0.0f,0.0f,STEPSIZE), | ||||
|                      position+Ogre::Vector3(0.0f,0.0f,STEPSIZE)+velocity*remainingTime, | ||||
|              halfExtents, verticalRotation, isInterior, mEngine); | ||||
|     if(trace.fraction == 0.0f || (trace.fraction != 1.0f && getSlope(trace.planenormal) > sMaxSlope)) | ||||
|         return false; | ||||
| 
 | ||||
|     newtrace(&trace, trace.endpos, trace.endpos-Ogre::Vector3(0,0,STEPSIZE), halfExtents, verticalRotation, isInterior, mEngine); | ||||
|     if(getSlope(trace.planenormal) < sMaxSlope) | ||||
|     { | ||||
|         // only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall.
 | ||||
|         position = trace.endpos; | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| float MovementSolver::getSlope(const Ogre::Vector3 &normal) | ||||
| { | ||||
|     return normal.angleBetween(Ogre::Vector3(0.0f,0.0f,1.0f)).valueDegrees(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Ogre::Vector3 MovementSolver::move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time) | ||||
| { | ||||
|     Ogre::Vector3 position(ptr.getRefData().getPosition().pos); | ||||
| 
 | ||||
|     /* Anything to collide with? */ | ||||
|     OEngine::Physic::PhysicActor *physicActor = mEngine->getCharacter(ptr.getRefData().getHandle()); | ||||
|     if(!physicActor || !physicActor->getCollisionMode()) | ||||
|         return position + movement; | ||||
| 
 | ||||
|     traceResults trace; //no initialization needed
 | ||||
|     int iterations=0, maxIterations=50; //arbitrary number. To prevent infinite loops. They shouldn't happen but it's good to be prepared.
 | ||||
| 
 | ||||
|     float verticalVelocity = physicActor->getVerticalForce(); | ||||
|     Ogre::Vector3 horizontalVelocity = movement/time; | ||||
|     Ogre::Vector3 velocity(horizontalVelocity.x, horizontalVelocity.y, verticalVelocity); // we need a copy of the velocity before we start clipping it for steps
 | ||||
|     Ogre::Vector3 clippedVelocity(horizontalVelocity.x, horizontalVelocity.y, verticalVelocity); | ||||
| 
 | ||||
|     float remainingTime = time; | ||||
|     bool isInterior = !ptr.getCell()->isExterior(); | ||||
|     float verticalRotation = physicActor->getRotation().getYaw().valueDegrees(); | ||||
|     Ogre::Vector3 halfExtents = physicActor->getHalfExtents(); | ||||
| 
 | ||||
|     Ogre::Vector3 lastNormal(0.0f); | ||||
|     Ogre::Vector3 currentNormal(0.0f); | ||||
|     Ogre::Vector3 up(0.0f, 0.0f, 1.0f); | ||||
|     Ogre::Vector3 newPosition = position; | ||||
| 
 | ||||
|     newtrace(&trace, position, position+Ogre::Vector3(0,0,-10), halfExtents, verticalRotation, isInterior, mEngine); | ||||
|     if(trace.fraction < 1.0f) | ||||
|     { | ||||
|         if(getSlope(trace.planenormal) > sMaxSlope) | ||||
|         { | ||||
|             // if we're on a really steep slope, don't listen to user input
 | ||||
|             clippedVelocity.x = clippedVelocity.y = 0.0f; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             // if we're within 10 units of the ground, force velocity to track the ground
 | ||||
|             clipVelocity(clippedVelocity, trace.planenormal, clippedVelocity, 1.0f); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     do { | ||||
|         // trace to where character would go if there were no obstructions
 | ||||
|         newtrace(&trace, newPosition, newPosition+clippedVelocity*remainingTime, halfExtents, verticalRotation, isInterior, mEngine); | ||||
|         newPosition = trace.endpos; | ||||
|         currentNormal = trace.planenormal; | ||||
|         remainingTime = remainingTime * (1.0f-trace.fraction); | ||||
| 
 | ||||
|         // check for obstructions
 | ||||
|         if(trace.fraction != 1.0f) | ||||
|         { | ||||
|             //std::cout<<"angle: "<<getSlope(trace.planenormal)<<"\n";
 | ||||
|             if(getSlope(currentNormal) > sMaxSlope || currentNormal == lastNormal) | ||||
|             { | ||||
|                 if(stepMove(newPosition, velocity, remainingTime, verticalRotation, halfExtents, mEngine)) | ||||
|                     std::cout<< "stepped" <<std::endl; | ||||
|                 else | ||||
|                 { | ||||
|                     Ogre::Vector3 resultantDirection = currentNormal.crossProduct(up); | ||||
|                     resultantDirection.normalise(); | ||||
|                     clippedVelocity = velocity; | ||||
|                     projectVelocity(clippedVelocity, resultantDirection); | ||||
| 
 | ||||
|                     // just this isn't enough sometimes. It's the same problem that causes steps to be necessary on even uphill terrain.
 | ||||
|                     clippedVelocity += currentNormal*clippedVelocity.length()/50.0f; | ||||
|                     std::cout<< "clipped velocity: "<<clippedVelocity <<std::endl; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|                 clipVelocity(clippedVelocity, currentNormal, clippedVelocity, 1.0f); | ||||
|         } | ||||
| 
 | ||||
|         lastNormal = currentNormal; | ||||
| 
 | ||||
|         iterations++; | ||||
|     } while(iterations < maxIterations && remainingTime != 0.0f); | ||||
| 
 | ||||
|     verticalVelocity = clippedVelocity.z; | ||||
|     verticalVelocity -= time*400; | ||||
|     physicActor->setVerticalForce(verticalVelocity); | ||||
| 
 | ||||
|     return newPosition; | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  | @ -1,41 +0,0 @@ | |||
| #ifndef  GAME_MWMECHANICS_MOVEMENTSOLVER_H | ||||
| #define  GAME_MWMECHANICS_MOVEMENTSOLVER_H | ||||
| 
 | ||||
| #include <OgreVector3.h> | ||||
| 
 | ||||
| namespace MWWorld | ||||
| { | ||||
|     class Ptr; | ||||
| } | ||||
| 
 | ||||
| namespace OEngine | ||||
| { | ||||
|     namespace Physic | ||||
|     { | ||||
|         class PhysicEngine; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| namespace MWMechanics | ||||
| { | ||||
|     class MovementSolver | ||||
|     { | ||||
|         public: | ||||
|             MovementSolver(); | ||||
|             virtual ~MovementSolver(); | ||||
| 
 | ||||
|             Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time); | ||||
| 
 | ||||
|         private: | ||||
|             bool stepMove(Ogre::Vector3& position, const Ogre::Vector3 &velocity, float remainingTime, float verticalRotation, const Ogre::Vector3 &halfExtents, bool isInterior); | ||||
| 
 | ||||
|             void clipVelocity(const Ogre::Vector3& in, const Ogre::Vector3& normal, Ogre::Vector3& out, const float overbounce); | ||||
|             void projectVelocity(Ogre::Vector3& velocity, const Ogre::Vector3& direction); | ||||
| 
 | ||||
|             float getSlope(const Ogre::Vector3 &normal); | ||||
| 
 | ||||
|             OEngine::Physic::PhysicEngine *mEngine; | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| #endif /* GAME_MWMECHANICS_MOVEMENTSOLVER_H */ | ||||
|  | @ -21,6 +21,153 @@ using namespace Ogre; | |||
| namespace MWWorld | ||||
| { | ||||
| 
 | ||||
|     static const float sMaxSlope = 45.0f; | ||||
| 
 | ||||
|     class MovementSolver | ||||
|     { | ||||
|     private: | ||||
|         static bool stepMove(Ogre::Vector3& position, const Ogre::Vector3 &velocity, float remainingTime, | ||||
|                              float verticalRotation, const Ogre::Vector3 &halfExtents, bool isInterior, | ||||
|                              OEngine::Physic::PhysicEngine *engine) | ||||
|         { | ||||
|             traceResults trace; // no initialization needed
 | ||||
| 
 | ||||
|             newtrace(&trace, position+Ogre::Vector3(0.0f,0.0f,STEPSIZE), | ||||
|                              position+Ogre::Vector3(0.0f,0.0f,STEPSIZE)+velocity*remainingTime, | ||||
|                     halfExtents, verticalRotation, isInterior, engine); | ||||
|             if(trace.fraction == 0.0f || (trace.fraction != 1.0f && getSlope(trace.planenormal) > sMaxSlope)) | ||||
|                 return false; | ||||
| 
 | ||||
|             newtrace(&trace, trace.endpos, trace.endpos-Ogre::Vector3(0,0,STEPSIZE), halfExtents, verticalRotation, isInterior, engine); | ||||
|             if(getSlope(trace.planenormal) < sMaxSlope) | ||||
|             { | ||||
|                 // only step down onto semi-horizontal surfaces. don't step down onto the side of a house or a wall.
 | ||||
|                 position = trace.endpos; | ||||
|                 return true; | ||||
|             } | ||||
| 
 | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         static void clipVelocity(const Ogre::Vector3& in, const Ogre::Vector3& normal, Ogre::Vector3& out, | ||||
|                                  const float overbounce) | ||||
|         { | ||||
|             //Math stuff. Basically just project the velocity vector onto the plane represented by the normal.
 | ||||
|             //More specifically, it projects velocity onto the normal, takes that result, multiplies it by overbounce and then subtracts it from velocity.
 | ||||
|             float backoff; | ||||
| 
 | ||||
|             backoff = in.dotProduct(normal); | ||||
|             if(backoff < 0.0f) | ||||
|                 backoff *= overbounce; | ||||
|             else | ||||
|                 backoff /= overbounce; | ||||
| 
 | ||||
|             out = in - (normal*backoff); | ||||
|         } | ||||
| 
 | ||||
|         static void projectVelocity(Ogre::Vector3& velocity, const Ogre::Vector3& direction) | ||||
|         { | ||||
|             Ogre::Vector3 normalizedDirection(direction); | ||||
|             normalizedDirection.normalise(); | ||||
| 
 | ||||
|             // no divide by normalizedDirection.length necessary because it's normalized
 | ||||
|             velocity = normalizedDirection * velocity.dotProduct(normalizedDirection); | ||||
|         } | ||||
| 
 | ||||
|         static float getSlope(const Ogre::Vector3 &normal) | ||||
|         { | ||||
|             return normal.angleBetween(Ogre::Vector3(0.0f,0.0f,1.0f)).valueDegrees(); | ||||
|         } | ||||
| 
 | ||||
|     public: | ||||
|         static Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time, | ||||
|                                   OEngine::Physic::PhysicEngine *engine) | ||||
|         { | ||||
|             Ogre::Vector3 position(ptr.getRefData().getPosition().pos); | ||||
| 
 | ||||
|             /* Anything to collide with? */ | ||||
|             OEngine::Physic::PhysicActor *physicActor = engine->getCharacter(ptr.getRefData().getHandle()); | ||||
|             if(!physicActor || !physicActor->getCollisionMode()) | ||||
|                 return position + movement; | ||||
| 
 | ||||
|             traceResults trace; //no initialization needed
 | ||||
|             int iterations=0, maxIterations=50; //arbitrary number. To prevent infinite loops. They shouldn't happen but it's good to be prepared.
 | ||||
| 
 | ||||
|             float verticalVelocity = physicActor->getVerticalForce(); | ||||
|             Ogre::Vector3 horizontalVelocity = movement/time; | ||||
|             Ogre::Vector3 velocity(horizontalVelocity.x, horizontalVelocity.y, verticalVelocity); // we need a copy of the velocity before we start clipping it for steps
 | ||||
|             Ogre::Vector3 clippedVelocity(horizontalVelocity.x, horizontalVelocity.y, verticalVelocity); | ||||
| 
 | ||||
|             float remainingTime = time; | ||||
|             bool isInterior = !ptr.getCell()->isExterior(); | ||||
|             float verticalRotation = physicActor->getRotation().getYaw().valueDegrees(); | ||||
|             Ogre::Vector3 halfExtents = physicActor->getHalfExtents(); | ||||
| 
 | ||||
|             Ogre::Vector3 lastNormal(0.0f); | ||||
|             Ogre::Vector3 currentNormal(0.0f); | ||||
|             Ogre::Vector3 up(0.0f, 0.0f, 1.0f); | ||||
|             Ogre::Vector3 newPosition = position; | ||||
| 
 | ||||
|             newtrace(&trace, position, position+Ogre::Vector3(0,0,-10), halfExtents, verticalRotation, isInterior, engine); | ||||
|             if(trace.fraction < 1.0f) | ||||
|             { | ||||
|                 if(getSlope(trace.planenormal) > sMaxSlope) | ||||
|                 { | ||||
|                     // if we're on a really steep slope, don't listen to user input
 | ||||
|                     clippedVelocity.x = clippedVelocity.y = 0.0f; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // if we're within 10 units of the ground, force velocity to track the ground
 | ||||
|                     clipVelocity(clippedVelocity, trace.planenormal, clippedVelocity, 1.0f); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             do { | ||||
|                 // trace to where character would go if there were no obstructions
 | ||||
|                 newtrace(&trace, newPosition, newPosition+clippedVelocity*remainingTime, halfExtents, verticalRotation, isInterior, engine); | ||||
|                 newPosition = trace.endpos; | ||||
|                 currentNormal = trace.planenormal; | ||||
|                 remainingTime = remainingTime * (1.0f-trace.fraction); | ||||
| 
 | ||||
|                 // check for obstructions
 | ||||
|                 if(trace.fraction != 1.0f) | ||||
|                 { | ||||
|                     //std::cout<<"angle: "<<getSlope(trace.planenormal)<<"\n";
 | ||||
|                     if(getSlope(currentNormal) > sMaxSlope || currentNormal == lastNormal) | ||||
|                     { | ||||
|                         if(stepMove(newPosition, velocity, remainingTime, verticalRotation, halfExtents, isInterior, engine)) | ||||
|                             std::cout<< "stepped" <<std::endl; | ||||
|                         else | ||||
|                         { | ||||
|                             Ogre::Vector3 resultantDirection = currentNormal.crossProduct(up); | ||||
|                             resultantDirection.normalise(); | ||||
|                             clippedVelocity = velocity; | ||||
|                             projectVelocity(clippedVelocity, resultantDirection); | ||||
| 
 | ||||
|                             // just this isn't enough sometimes. It's the same problem that causes steps to be necessary on even uphill terrain.
 | ||||
|                             clippedVelocity += currentNormal*clippedVelocity.length()/50.0f; | ||||
|                             std::cout<< "clipped velocity: "<<clippedVelocity <<std::endl; | ||||
|                         } | ||||
|                     } | ||||
|                     else | ||||
|                         clipVelocity(clippedVelocity, currentNormal, clippedVelocity, 1.0f); | ||||
|                 } | ||||
| 
 | ||||
|                 lastNormal = currentNormal; | ||||
| 
 | ||||
|                 iterations++; | ||||
|             } while(iterations < maxIterations && remainingTime != 0.0f); | ||||
| 
 | ||||
|             verticalVelocity = clippedVelocity.z; | ||||
|             verticalVelocity -= time*400; | ||||
|             physicActor->setVerticalForce(verticalVelocity); | ||||
| 
 | ||||
|             return newPosition; | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
| 
 | ||||
|     PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend) : | ||||
|         mRender(_rend), mEngine(0), mFreeFly (true) | ||||
|     { | ||||
|  | @ -185,6 +332,11 @@ namespace MWWorld | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Ogre::Vector3 PhysicsSystem::move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time) | ||||
|     { | ||||
|         return MovementSolver::move(ptr, movement, time, mEngine); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void PhysicsSystem::addHeightField (float* heights, | ||||
|                 int x, int y, float yoffset, | ||||
|  |  | |||
|  | @ -35,6 +35,8 @@ namespace MWWorld | |||
| 
 | ||||
|             bool toggleCollisionMode(); | ||||
|              | ||||
|             Ogre::Vector3 move(const MWWorld::Ptr &ptr, const Ogre::Vector3 &movement, float time); | ||||
| 
 | ||||
|             std::pair<float, std::string> getFacedHandle (MWWorld::World& world, float queryDistance); | ||||
|             std::vector < std::pair <float, std::string> > getFacedHandles (float queryDistance); | ||||
|             std::vector < std::pair <float, std::string> > getFacedHandles (float mouseX, float mouseY, float queryDistance); | ||||
|  |  | |||
|  | @ -836,6 +836,27 @@ namespace MWWorld | |||
| 
 | ||||
|     void World::doPhysics(const PtrMovementList &actors, float duration) | ||||
|     { | ||||
|         /* No duration? Shouldn't be any movement, then. */ | ||||
|         if(duration <= 0.0f) | ||||
|             return; | ||||
| 
 | ||||
|         PtrMovementList::const_iterator player(actors.end()); | ||||
|         for(PtrMovementList::const_iterator iter(actors.begin());iter != actors.end();iter++) | ||||
|         { | ||||
|             if(iter->first.getRefData().getHandle() == "player") | ||||
|             { | ||||
|                 /* Handle player last, in case a cell transition occurs */ | ||||
|                 player = iter; | ||||
|                 continue; | ||||
|             } | ||||
|             Ogre::Vector3 vec = mPhysics->move(iter->first, iter->second, duration); | ||||
|             moveObjectImp(iter->first, vec.x, vec.y, vec.z); | ||||
|         } | ||||
|         if(player != actors.end()) | ||||
|         { | ||||
|             Ogre::Vector3 vec = mPhysics->move(player->first, player->second, duration); | ||||
|             moveObjectImp(player->first, vec.x, vec.y, vec.z); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     bool World::toggleCollisionMode() | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue