mirror of
				https://github.com/TES3MP/openmw-tes3mp.git
				synced 2025-10-31 17:26:42 +00:00 
			
		
		
		
	pMove in a seperate loop with fixed timestep to prevent frame-dependent movement
This commit is contained in:
		
							parent
							
								
									4655ec94f0
								
							
						
					
					
						commit
						86b6184f43
					
				
					 5 changed files with 102 additions and 74 deletions
				
			
		|  | @ -21,27 +21,24 @@ namespace MWWorld | |||
|     PhysicsSystem::PhysicsSystem(OEngine::Render::OgreRenderer &_rend) : | ||||
|         mRender(_rend), mEngine(0), mFreeFly (true) | ||||
|     { | ||||
| 		 | ||||
| 
 | ||||
|         playerphysics = new playerMove; | ||||
|         // Create physics. shapeLoader is deleted by the physic engine
 | ||||
|         NifBullet::ManualBulletShapeLoader* shapeLoader = new NifBullet::ManualBulletShapeLoader(); | ||||
|         mEngine = new OEngine::Physic::PhysicEngine(shapeLoader); | ||||
|         playerphysics->mEngine = mEngine; | ||||
|        | ||||
|          | ||||
| 		 | ||||
|     } | ||||
| 
 | ||||
|     PhysicsSystem::~PhysicsSystem() | ||||
|     { | ||||
|         delete mEngine; | ||||
|      | ||||
| 
 | ||||
|     } | ||||
|     OEngine::Physic::PhysicEngine* PhysicsSystem::getEngine() | ||||
|     { | ||||
|         return mEngine; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
| 	std::pair<std::string, float> PhysicsSystem::getFacedHandle (MWWorld::World& world) | ||||
| 	{ | ||||
| 		std::string handle = ""; | ||||
|  | @ -74,7 +71,7 @@ namespace MWWorld | |||
|         if(hasWater){ | ||||
|             playerphysics->waterHeight = waterHeight; | ||||
|         } | ||||
|          | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     btVector3 PhysicsSystem::getRayPoint(float extent) | ||||
|  | @ -86,26 +83,23 @@ namespace MWWorld | |||
|         btVector3 result(centerRay.getPoint(500*extent).x,-centerRay.getPoint(500*extent).z,centerRay.getPoint(500*extent).y); | ||||
|         return result; | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     bool PhysicsSystem::castRay(const Vector3& from, const Vector3& to) | ||||
|     { | ||||
|         btVector3 _from, _to; | ||||
|         _from = btVector3(from.x, from.y, from.z); | ||||
|         _to = btVector3(to.x, to.y, to.z); | ||||
|          | ||||
| 
 | ||||
|         std::pair<std::string, float> result = mEngine->rayTest(_from, _to); | ||||
|          | ||||
| 
 | ||||
|         return !(result.first == ""); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     std::vector< std::pair<std::string, Ogre::Vector3> > PhysicsSystem::doPhysics (float duration, | ||||
|         const std::vector<std::pair<std::string, Ogre::Vector3> >& actors) | ||||
|     void PhysicsSystem::doPhysics(float dt, const std::vector<std::pair<std::string, Ogre::Vector3> >& actors) | ||||
|     { | ||||
|         //set the DebugRenderingMode. To disable it,set it to 0
 | ||||
|         //eng->setDebugRenderingMode(1);
 | ||||
| 		 | ||||
| 		 | ||||
| 
 | ||||
|         //set the walkdirection to 0 (no movement) for every actor)
 | ||||
|         for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) | ||||
|         { | ||||
|  | @ -117,8 +111,7 @@ namespace MWWorld | |||
|         pm_ref.rightmove = 0; | ||||
|         pm_ref.forwardmove = 0; | ||||
|         pm_ref.upmove = 0; | ||||
| 		 | ||||
| 		 | ||||
| 
 | ||||
| 		//playerphysics->ps.move_type = PM_NOCLIP;
 | ||||
|         for (std::vector<std::pair<std::string, Ogre::Vector3> >::const_iterator iter (actors.begin()); | ||||
|             iter!=actors.end(); ++iter) | ||||
|  | @ -133,29 +126,24 @@ namespace MWWorld | |||
|             Ogre::Node* yawNode = sceneNode->getChildIterator().getNext(); | ||||
|             Ogre::Node* pitchNode = yawNode->getChildIterator().getNext(); | ||||
| 			Ogre::Quaternion yawQuat = yawNode->getOrientation(); | ||||
|                 Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); | ||||
|             Ogre::Quaternion pitchQuat = pitchNode->getOrientation(); | ||||
| 
 | ||||
|                 // unused
 | ||||
| 				//Ogre::Quaternion both = yawQuat * pitchQuat;
 | ||||
| 				 | ||||
| 				playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); | ||||
| 				playerphysics->ps.viewangles.z = 0; | ||||
|             // unused
 | ||||
|             //Ogre::Quaternion both = yawQuat * pitchQuat;
 | ||||
| 
 | ||||
|             playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees(); | ||||
|             playerphysics->ps.viewangles.z = 0; | ||||
| 			playerphysics->ps.viewangles.y = yawQuat.getYaw().valueDegrees() *-1 + 90; | ||||
| 
 | ||||
| 				 | ||||
| 				 | ||||
| 			 | ||||
|             if(mFreeFly) | ||||
|             { | ||||
|                  | ||||
|                 Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); | ||||
| 
 | ||||
| 				pm_ref.rightmove = -dir1.x; | ||||
| 				pm_ref.forwardmove = dir1.z; | ||||
| 				pm_ref.upmove = dir1.y; | ||||
| 
 | ||||
| 				 | ||||
| 				 | ||||
| 
 | ||||
| 				//std::cout << "Current angle" << yawQuat.getYaw().valueDegrees() - 90<< "\n";
 | ||||
| 				//playerphysics->ps.viewangles.x = pitchQuat.getPitch().valueDegrees();
 | ||||
| 				//std::cout << "Pitch: " << yawQuat.getPitch() << "Yaw:" << yawQuat.getYaw() << "Roll: " << yawQuat.getRoll() << "\n";
 | ||||
|  | @ -163,46 +151,50 @@ namespace MWWorld | |||
|             } | ||||
|             else | ||||
|             { | ||||
| 				 | ||||
| 
 | ||||
|                 Ogre::Quaternion quat = yawNode->getOrientation(); | ||||
|                 Ogre::Vector3 dir1(iter->second.x,iter->second.z,-iter->second.y); | ||||
| 				 | ||||
| 
 | ||||
| 				pm_ref.rightmove = -dir1.x; | ||||
| 				pm_ref.forwardmove = dir1.z; | ||||
| 				pm_ref.upmove = dir1.y; | ||||
| 				 | ||||
| 				 | ||||
| 				 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|                 dir = 0.025*(quat*dir1); | ||||
|             } | ||||
| 			 | ||||
| 
 | ||||
| 
 | ||||
|             //set the walk direction
 | ||||
|             act->setWalkDirection(btVector3(dir.x,-dir.z,dir.y)); | ||||
|         } | ||||
|         mEngine->stepSimulation(duration); | ||||
| 		Pmove(playerphysics); | ||||
|         mEngine->stepSimulation(dt); | ||||
|     } | ||||
| 
 | ||||
|     std::vector< std::pair<std::string, Ogre::Vector3> > PhysicsSystem::doPhysicsFixed ( | ||||
|         const std::vector<std::pair<std::string, Ogre::Vector3> >& actors) | ||||
|     { | ||||
|         Pmove(playerphysics); | ||||
| 
 | ||||
| 		 | ||||
|         std::vector< std::pair<std::string, Ogre::Vector3> > response; | ||||
|         for(std::map<std::string,OEngine::Physic::PhysicActor*>::iterator it = mEngine->PhysicActorMap.begin(); it != mEngine->PhysicActorMap.end();it++) | ||||
|         { | ||||
|             btVector3 newPos = it->second->getPosition(); | ||||
| 			 | ||||
|             Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z()); | ||||
| 			if(it->first == "player"){ | ||||
| 				 | ||||
| 				coord = playerphysics->ps.origin; | ||||
| 				//std::cout << "ZCoord: " << coord.z << "\n";
 | ||||
| 				//std::cout << "Coord" << coord << "\n";
 | ||||
| 				//coord = Ogre::Vector3(coord.x, coord.z, coord.y);   //x, z, -y
 | ||||
| 				 | ||||
| 			} | ||||
| 
 | ||||
| 			 | ||||
|             Ogre::Vector3 coord(newPos.x(), newPos.y(), newPos.z()); | ||||
|             if(it->first == "player"){ | ||||
| 
 | ||||
|                 coord = playerphysics->ps.origin; | ||||
|                 //std::cout << "ZCoord: " << coord.z << "\n";
 | ||||
|                 //std::cout << "Coord" << coord << "\n";
 | ||||
|                 //coord = Ogre::Vector3(coord.x, coord.z, coord.y);   //x, z, -y
 | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             response.push_back(std::pair<std::string, Ogre::Vector3>(it->first, coord)); | ||||
|         } | ||||
| 		 | ||||
| 
 | ||||
|         return response; | ||||
|     } | ||||
| 
 | ||||
|  | @ -260,7 +252,14 @@ namespace MWWorld | |||
|         { | ||||
|             // TODO very dirty hack to avoid crash during setup -> needs cleaning up to allow
 | ||||
|             // start positions others than 0, 0, 0
 | ||||
|             act->setPosition(btVector3(position.x,position.y,position.z)); | ||||
|             if (handle == "player") | ||||
|             { | ||||
|                 playerphysics->ps.origin = position; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 act->setPosition(btVector3(position.x,position.y,position.z)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -316,7 +315,7 @@ namespace MWWorld | |||
|     } | ||||
| 
 | ||||
|      void PhysicsSystem::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string model){ | ||||
| 		  | ||||
| 
 | ||||
|            Ogre::SceneNode* node = ptr.getRefData().getBaseNode(); | ||||
| 
 | ||||
|            // unused
 | ||||
|  |  | |||
|  | @ -16,8 +16,11 @@ namespace MWWorld | |||
|             PhysicsSystem (OEngine::Render::OgreRenderer &_rend); | ||||
|             ~PhysicsSystem (); | ||||
| 
 | ||||
|             std::vector< std::pair<std::string, Ogre::Vector3> > doPhysics (float duration, | ||||
|                 const std::vector<std::pair<std::string, Ogre::Vector3> >& actors); | ||||
|             void doPhysics(float duration, const std::vector<std::pair<std::string, Ogre::Vector3> >& actors); | ||||
|             ///< do physics with dt - Usage: first call doPhysics with frame dt, then call doPhysicsFixed as often as time steps have passed
 | ||||
| 
 | ||||
|             std::vector< std::pair<std::string, Ogre::Vector3> > doPhysicsFixed (const std::vector<std::pair<std::string, Ogre::Vector3> >& actors); | ||||
|             ///< do physics with fixed timestep - Usage: first call doPhysics with frame dt, then call doPhysicsFixed as often as time steps have passed
 | ||||
| 
 | ||||
|             void addObject (const std::string& handle, const std::string& mesh, | ||||
|                 const Ogre::Quaternion& rotation, float scale, const Ogre::Vector3& position); | ||||
|  | @ -55,7 +58,7 @@ namespace MWWorld | |||
|             void insertActorPhysics(const MWWorld::Ptr&, std::string model); | ||||
| 
 | ||||
|             OEngine::Physic::PhysicEngine* getEngine(); | ||||
|              | ||||
| 
 | ||||
|             void setCurrentWater(bool hasWater, int waterHeight); | ||||
| 
 | ||||
|         private: | ||||
|  | @ -64,7 +67,6 @@ namespace MWWorld | |||
|             bool mFreeFly; | ||||
|             playerMove* playerphysics; | ||||
| 
 | ||||
| 
 | ||||
|             PhysicsSystem (const PhysicsSystem&); | ||||
|             PhysicsSystem& operator= (const PhysicsSystem&); | ||||
|     }; | ||||
|  |  | |||
|  | @ -215,6 +215,7 @@ namespace MWWorld | |||
| 
 | ||||
|         setFallbackValues(fallbackMap); | ||||
| 
 | ||||
|         lastTick = mTimer.getMilliseconds(); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -559,8 +560,9 @@ namespace MWWorld | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void World::moveObjectImp (Ptr ptr, float x, float y, float z) | ||||
|     bool World::moveObjectImp (Ptr ptr, float x, float y, float z) | ||||
|     { | ||||
|         bool ret = false; | ||||
|         ptr.getRefData().getPosition().pos[0] = x; | ||||
|         ptr.getRefData().getPosition().pos[1] = y; | ||||
|         ptr.getRefData().getPosition().pos[2] = z; | ||||
|  | @ -582,6 +584,7 @@ namespace MWWorld | |||
|                     if (currentCell->cell->data.gridX!=cellX || currentCell->cell->data.gridY!=cellY) | ||||
|                     { | ||||
|                         mWorldScene->changeCell (cellX, cellY, mPlayer->getPlayer().getRefData().getPosition(), false); | ||||
|                         ret = true; | ||||
|                     } | ||||
| 
 | ||||
|                 } | ||||
|  | @ -591,6 +594,8 @@ namespace MWWorld | |||
|         /// \todo cell change for non-player ref
 | ||||
| 
 | ||||
|         mRendering->moveObject (ptr, Ogre::Vector3 (x, y, z)); | ||||
| 
 | ||||
|         return ret; | ||||
|     } | ||||
| 
 | ||||
|     void World::moveObject (Ptr ptr, float x, float y, float z) | ||||
|  | @ -632,29 +637,45 @@ namespace MWWorld | |||
|     void World::doPhysics (const std::vector<std::pair<std::string, Ogre::Vector3> >& actors, | ||||
|         float duration) | ||||
|     { | ||||
|         std::vector< std::pair<std::string, Ogre::Vector3> > vectors = mPhysics->doPhysics (duration, actors); | ||||
|         mPhysics->doPhysics(duration, actors); | ||||
| 
 | ||||
|         std::vector< std::pair<std::string, Ogre::Vector3> >::iterator player = vectors.end(); | ||||
|         const int tick = 16; // 16 ms ^= 60 Hz
 | ||||
| 
 | ||||
|         for (std::vector< std::pair<std::string, Ogre::Vector3> >::iterator it = vectors.begin(); | ||||
|             it!= vectors.end(); ++it) | ||||
|         // Game clock part of the loop, contains everything that has to be executed in a fixed timestep
 | ||||
|         long long dt = mTimer.getMilliseconds() - lastTick; | ||||
|         if (dt >= 100) dt = 100; 	//  throw away wall clock time if necessary to keep the framerate above the minimum of 10 fps
 | ||||
|         while (dt >= tick) | ||||
|         { | ||||
|             if (it->first=="player") | ||||
|             dt -= tick; | ||||
|             lastTick += tick; | ||||
| 
 | ||||
|             std::vector< std::pair<std::string, Ogre::Vector3> > vectors = mPhysics->doPhysicsFixed (actors); | ||||
| 
 | ||||
|             std::vector< std::pair<std::string, Ogre::Vector3> >::iterator player = vectors.end(); | ||||
| 
 | ||||
|             for (std::vector< std::pair<std::string, Ogre::Vector3> >::iterator it = vectors.begin(); | ||||
|                 it!= vectors.end(); ++it) | ||||
|             { | ||||
|                 player = it; | ||||
|                 if (it->first=="player") | ||||
|                 { | ||||
|                     player = it; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     MWWorld::Ptr ptr = getPtrViaHandle (it->first); | ||||
|                     moveObjectImp (ptr, it->second.x, it->second.y, it->second.z); | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
| 
 | ||||
|             // Make sure player is moved last (otherwise the cell might change in the middle of an update
 | ||||
|             // loop)
 | ||||
|             if (player!=vectors.end()) | ||||
|             { | ||||
|                 MWWorld::Ptr ptr = getPtrViaHandle (it->first); | ||||
|                 moveObjectImp (ptr, it->second.x, it->second.y, it->second.z); | ||||
|                 if (moveObjectImp (getPtrViaHandle (player->first), | ||||
|                     player->second.x, player->second.y, player->second.z) == true) | ||||
|                     return; // abort the current loop if the cell has changed
 | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Make sure player is moved last (otherwise the cell might change in the middle of an update
 | ||||
|         // loop)
 | ||||
|         if (player!=vectors.end()) | ||||
|             moveObjectImp (getPtrViaHandle (player->first), | ||||
|                 player->second.x, player->second.y, player->second.z); | ||||
|     } | ||||
| 
 | ||||
|     bool World::toggleCollisionMode() | ||||
|  |  | |||
|  | @ -22,6 +22,8 @@ | |||
| #include <openengine/bullet/physic.hpp> | ||||
| #include <openengine/ogre/fader.hpp> | ||||
| 
 | ||||
| #include <OgreTimer.h> | ||||
| 
 | ||||
| namespace Ogre | ||||
| { | ||||
|     class Vector3; | ||||
|  | @ -100,9 +102,13 @@ namespace MWWorld | |||
|             int mNumFacing; | ||||
|             std::map<std::string,std::string> mFallback; | ||||
| 
 | ||||
|             unsigned long lastTick; | ||||
|             Ogre::Timer mTimer; | ||||
| 
 | ||||
|             int getDaysPerMonth (int month) const; | ||||
| 
 | ||||
|             void moveObjectImp (Ptr ptr, float x, float y, float z); | ||||
|             bool moveObjectImp (Ptr ptr, float x, float y, float z); | ||||
|             ///< @return true if the active cell (cell player is in) changed
 | ||||
| 
 | ||||
|         public: | ||||
| 
 | ||||
|  |  | |||
|  | @ -393,7 +393,7 @@ namespace Physic | |||
| 
 | ||||
|     void PhysicEngine::stepSimulation(double deltaT) | ||||
|     { | ||||
|         dynamicsWorld->stepSimulation(deltaT,10); | ||||
|         dynamicsWorld->stepSimulation(deltaT,10, 1/60.0); | ||||
|         if(isDebugCreated) | ||||
|         { | ||||
|             mDebugDrawer->step(); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue