Selaa lähdekoodia

Implemented a global fixed timestep update for Core, physics modules now update in sync with core using the core fps setting, added ability to have a custom fixed timestep loop

Ivan Safrin 11 vuotta sitten
vanhempi
sitoutus
966420be46

+ 3 - 0
Bindings/Contents/LUA/API/defaults.lua

@@ -130,6 +130,9 @@ end
 function Update(e)
 function Update(e)
 end
 end
 
 
+function fixedUpdate()
+end
+
 KEY_UNKNOWN= 0
 KEY_UNKNOWN= 0
 KEY_FIRST= 0
 KEY_FIRST= 0
 KEY_BACKSPACE= 8
 KEY_BACKSPACE= 8

+ 1 - 1
Core/Contents/Include/PolyCocoaCore.h

@@ -118,7 +118,7 @@ namespace Polycode {
 		
 		
 		void enableMouse(bool newval);
 		void enableMouse(bool newval);
 		unsigned int getTicks();		
 		unsigned int getTicks();		
-		bool Update();
+		bool systemUpdate();
 		
 		
 		void Render();
 		void Render();
 								
 								

+ 12 - 4
Core/Contents/Include/PolyCore.h

@@ -92,9 +92,11 @@ namespace Polycode {
 		Core(int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate, int monitorIndex);
 		Core(int xRes, int yRes, bool fullScreen, bool vSync, int aaLevel, int anisotropyLevel, int frameRate, int monitorIndex);
 		virtual ~Core();
 		virtual ~Core();
 		
 		
-		virtual bool Update() = 0;
-
+        bool Update();
 		virtual void Render() = 0;
 		virtual void Render() = 0;
+        
+        bool fixedUpdate();
+        virtual bool systemUpdate() = 0;
 		
 		
 		bool updateAndRender();
 		bool updateAndRender();
 		
 		
@@ -267,7 +269,7 @@ namespace Polycode {
 		*/
 		*/
 		virtual String openFolderPicker() = 0;
 		virtual String openFolderPicker() = 0;
 
 
-		void setFramerate(int frameRate);
+		void setFramerate(int frameRate, int maxFixedCycles = 8);
 		
 		
 		/**
 		/**
 		* Opens a system file picker for the specified extensions.
 		* Opens a system file picker for the specified extensions.
@@ -321,6 +323,8 @@ namespace Polycode {
 		long getTimeSleptMs() const {
 		long getTimeSleptMs() const {
 			return timeSleptMs;
 			return timeSleptMs;
 		}
 		}
+        
+        Number getFixedTimestep();
 		
 		
 		/**
 		/**
 		* Returns the total ticks elapsed since launch.
 		* Returns the total ticks elapsed since launch.
@@ -393,7 +397,6 @@ namespace Polycode {
 		void loseFocus();
 		void loseFocus();
 		void gainFocus();
 		void gainFocus();
 		
 		
-		
 		String userHomeDirectory;
 		String userHomeDirectory;
 		String defaultWorkingDirectory;
 		String defaultWorkingDirectory;
 		
 		
@@ -416,6 +419,11 @@ namespace Polycode {
 		unsigned int lastFrameTicks;
 		unsigned int lastFrameTicks;
 		unsigned int lastFPSTicks;
 		unsigned int lastFPSTicks;
 		unsigned int elapsed;
 		unsigned int elapsed;
+        
+        double fixedElapsed;
+        double fixedTimestep;
+        double timeLeftOver;
+        double maxFixedElapsed;
 		
 		
 		bool mouseEnabled;
 		bool mouseEnabled;
 		bool mouseCaptured;
 		bool mouseCaptured;

+ 1 - 0
Core/Contents/Include/PolyCoreServices.h

@@ -65,6 +65,7 @@ namespace Polycode {
 			Renderer *getRenderer();
 			Renderer *getRenderer();
 			
 			
 			void Update(int elapsed);
 			void Update(int elapsed);
+            void fixedUpdate();
 			void Render();
 			void Render();
 			
 			
 			void setCore(Core *core);
 			void setCore(Core *core);

+ 4 - 2
Core/Contents/Include/PolyEntity.h

@@ -93,7 +93,8 @@ namespace Polycode {
 			* Main update method. Override this to do your updates before the render cycle.
 			* Main update method. Override this to do your updates before the render cycle.
 			*/			
 			*/			
 			virtual void Update(){};			
 			virtual void Update(){};			
-
+			virtual void fixedUpdate(){};
+        
 			void transformAndRender();		
 			void transformAndRender();		
 
 
 			void renderChildren();					
 			void renderChildren();					
@@ -737,7 +738,8 @@ namespace Polycode {
              */
              */
 			bool getInverseY();
 			bool getInverseY();
 			
 			
-			void doUpdates();				
+			void doUpdates();
+			void doFixedUpdates();
 			virtual Matrix4 buildPositionMatrix();
 			virtual Matrix4 buildPositionMatrix();
 			void setRenderer(Renderer *renderer);
 			void setRenderer(Renderer *renderer);
 			
 			

+ 2 - 1
Core/Contents/Include/PolyScene.h

@@ -119,7 +119,8 @@ namespace Polycode {
 		void setFogProperties(int fogMode, Color color, Number density, Number startDepth, Number endDepth);
 		void setFogProperties(int fogMode, Color color, Number density, Number startDepth, Number endDepth);
         
         
         void setSceneType(int newType);
         void setSceneType(int newType);
-	
+
+		virtual void fixedUpdate();
 		virtual void Update();
 		virtual void Update();
 		void setVirtual(bool val);
 		void setVirtual(bool val);
 		bool isVirtual();
 		bool isVirtual();

+ 1 - 0
Core/Contents/Include/PolySceneManager.h

@@ -51,6 +51,7 @@ namespace Polycode {
         
         
         // Polycode internal
         // Polycode internal
 		void Update();
 		void Update();
+		void fixedUpdate();
 		void Render();
 		void Render();
 		void renderVirtual();
 		void renderVirtual();
 		void registerRenderTexture(SceneRenderTexture *renderTexture);
 		void registerRenderTexture(SceneRenderTexture *renderTexture);

+ 1 - 3
Core/Contents/Source/PolyCocoaCore.mm

@@ -625,7 +625,7 @@ void CocoaCore::Render() {
 	unlockMutex(CoreServices::getRenderMutex());
 	unlockMutex(CoreServices::getRenderMutex());
 }
 }
 
 
-bool CocoaCore::Update() {
+bool CocoaCore::systemUpdate() {
 	if(!running)
 	if(!running)
 		return false;
 		return false;
 	doSleep();
 	doSleep();
@@ -640,8 +640,6 @@ bool CocoaCore::Update() {
 	return running;
 	return running;
 }
 }
 
 
-
-
 static void hatValueToXY(CFIndex value, CFIndex range, int * outX, int * outY) {
 static void hatValueToXY(CFIndex value, CFIndex range, int * outX, int * outY) {
 	if (value == range) {
 	if (value == range) {
 		*outX = *outY = 0;
 		*outX = *outY = 0;

+ 33 - 4
Core/Contents/Source/PolyCore.cpp

@@ -60,6 +60,7 @@ namespace Polycode {
 		input = new CoreInput();
 		input = new CoreInput();
 		services->setCore(this);
 		services->setCore(this);
 		fps = 0;
 		fps = 0;
+        timeLeftOver = 0.0;
 		running = true;
 		running = true;
 		frames = 0;
 		frames = 0;
 		lastFrameTicks=0;
 		lastFrameTicks=0;
@@ -80,7 +81,7 @@ namespace Polycode {
 		if(frameRate == 0)
 		if(frameRate == 0)
 			frameRate = 60;
 			frameRate = 60;
 		
 		
-		refreshInterval = 1000 / frameRate;		
+		setFramerate(frameRate);
 		threadedEventMutex = NULL;
 		threadedEventMutex = NULL;
 	}
 	}
     
     
@@ -96,8 +97,10 @@ namespace Polycode {
         return height;
         return height;
     }
     }
 	
 	
-	void Core::setFramerate(int frameRate) {
+	void Core::setFramerate(int frameRate, int maxFixedCycles) {
 		refreshInterval = 1000 / frameRate;
 		refreshInterval = 1000 / frameRate;
+        fixedTimestep = 1.0 / ((double) frameRate);
+        maxFixedElapsed = fixedTimestep * maxFixedCycles;
 	}
 	}
 	
 	
 	void Core::enableMouse(bool newval) {
 	void Core::enableMouse(bool newval) {
@@ -197,15 +200,41 @@ namespace Polycode {
 		Render();
 		Render();
 		return ret;
 		return ret;
 	}
 	}
+    
+    bool Core::fixedUpdate() {
+        if(fixedElapsed < fixedTimestep) {
+            return false;
+        }
+        services->fixedUpdate();
+        fixedElapsed -= fixedTimestep;
+        return true;
+    }
+    
+    Number Core::getFixedTimestep() {
+        return fixedTimestep;
+    }
+    
+    bool Core::Update() {
+        bool ret = systemUpdate();
+        while(fixedUpdate()) {}
+        return ret;
+    }
 							
 							
 	void Core::updateCore() {
 	void Core::updateCore() {
 		frames++;
 		frames++;
 		frameTicks = getTicks();
 		frameTicks = getTicks();
 		elapsed = frameTicks - lastFrameTicks;
 		elapsed = frameTicks - lastFrameTicks;
-		
+		      
 		if(elapsed > 1000)
 		if(elapsed > 1000)
 			elapsed = 1000;
 			elapsed = 1000;
-			
+		
+        timeLeftOver = fixedElapsed;
+        fixedElapsed = (((Number)elapsed)/1000.0f) + timeLeftOver;
+        
+        if(fixedElapsed > maxFixedElapsed) {
+            fixedElapsed = maxFixedElapsed;
+        }
+        
 		services->Update(elapsed);
 		services->Update(elapsed);
 		
 		
 		if(frameTicks-lastFPSTicks >= 1000) {
 		if(frameTicks-lastFPSTicks >= 1000) {

+ 4 - 0
Core/Contents/Source/PolyCoreServices.cpp

@@ -184,6 +184,10 @@ void CoreServices::Render() {
 	renderer->clearLights();
 	renderer->clearLights();
 }
 }
 
 
+void CoreServices::fixedUpdate() {
+    sceneManager->fixedUpdate();
+}
+
 void CoreServices::Update(int elapsed) {
 void CoreServices::Update(int elapsed) {
 	
 	
 	for(int i=0; i < updateModules.size(); i++) {
 	for(int i=0; i < updateModules.size(); i++) {

+ 9 - 0
Core/Contents/Source/PolyEntity.cpp

@@ -408,6 +408,15 @@ void Entity::doUpdates() {
 	}
 	}
 }
 }
 
 
+void Entity::doFixedUpdates() {
+	if (enabled) {
+		fixedUpdate();
+		for(int i=0; i < children.size(); i++) {
+			children[i]->doFixedUpdates();
+		}
+	}
+}
+
 void Entity::updateEntityMatrix() {
 void Entity::updateEntityMatrix() {
 
 
 	if(matrixDirty) {
 	if(matrixDirty) {

+ 5 - 0
Core/Contents/Source/PolyScene.cpp

@@ -138,6 +138,11 @@ void Scene::Update() {
 	rootEntity.doUpdates();
 	rootEntity.doUpdates();
 }
 }
 
 
+void Scene::fixedUpdate() {
+    rootEntity.updateEntityMatrix();
+	rootEntity.doFixedUpdates();
+}
+
 Scene::~Scene() {
 Scene::~Scene() {
 	core->getInput()->removeAllHandlersForListener(this);
 	core->getInput()->removeAllHandlersForListener(this);
 	CoreServices::getInstance()->getSceneManager()->removeScene(this);	
 	CoreServices::getInstance()->getSceneManager()->removeScene(this);	

+ 8 - 0
Core/Contents/Source/PolySceneManager.cpp

@@ -102,6 +102,14 @@ void SceneManager::Render() {
 	}
 	}
 }
 }
 
 
+void SceneManager::fixedUpdate() {
+	for(int i=0;i<scenes.size();i++) {
+		if(scenes[i]->isEnabled()) {
+			scenes[i]->fixedUpdate();
+		}
+	}
+}
+
 void SceneManager::Update() {
 void SceneManager::Update() {
 	for(int i=0;i<scenes.size();i++) {
 	for(int i=0;i<scenes.size();i++) {
 		if(scenes[i]->isEnabled()) {
 		if(scenes[i]->isEnabled()) {

+ 4 - 6
Modules/Contents/2DPhysics/Include/PolyPhysicsScreen.h

@@ -159,7 +159,7 @@ public:
 	/**
 	/**
 	* Creates a new physics screen.
 	* Creates a new physics screen.
 	*/ 
 	*/ 
-	PhysicsScene2D(Number worldScale, Number freq, int velIterations=10, int posIterations=10);
+	PhysicsScene2D(Number worldScale, int velIterations=10, int posIterations=10);
 	
 	
 	/**
 	/**
 	* Default constructor.
 	* Default constructor.
@@ -168,7 +168,7 @@ public:
 	
 	
 	~PhysicsScene2D();
 	~PhysicsScene2D();
 	
 	
-	void Update();
+	void fixedUpdate();
 	
 	
 	/**
 	/**
 	* Adds a Entity as a physics enabled child. Once an entity is added as a physics child, its transforms are set by the physics engine and you are not able to position it manually. Use addCollisionChild/trackCollisionChild to track collisions of entities that you can position manually.
 	* Adds a Entity as a physics enabled child. Once an entity is added as a physics child, its transforms are set by the physics engine and you are not able to position it manually. Use addCollisionChild/trackCollisionChild to track collisions of entities that you can position manually.
@@ -404,18 +404,16 @@ public:
     
     
 protected:
 protected:
 
 
-	Number cyclesLeftOver;
 	
 	
     Number worldScale;
     Number worldScale;
     
     
     std::vector <PhysicsScene2DEntity*> physicsChildren;
     std::vector <PhysicsScene2DEntity*> physicsChildren;
 	std::vector<PhysicsScene2DEvent*> eventsToDispatch;
 	std::vector<PhysicsScene2DEvent*> eventsToDispatch;
 			
 			
-	void init(Number worldScale, Number physicsTimeStep, int velIterations, int posIterations, Vector2 physicsGravity);
+	void init(Number worldScale, int velIterations, int posIterations, Vector2 physicsGravity);
 
 
 	std::vector<b2Contact*> contacts;
 	std::vector<b2Contact*> contacts;
-    b2World *world;    
-	Number timeStep;
+    b2World *world;
 	int32 velocityIterations, positionIterations;
 	int32 velocityIterations, positionIterations;
 };
 };
 
 

+ 22 - 22
Modules/Contents/2DPhysics/Source/PolyPhysicsScreen.cpp

@@ -196,19 +196,17 @@ bool PhysicsScene2D::testEntityCollision(Entity *ent1, Entity *ent2) {
 }
 }
 
 
 PhysicsScene2D::PhysicsScene2D() : Scene(Scene::SCENE_2D) {
 PhysicsScene2D::PhysicsScene2D() : Scene(Scene::SCENE_2D) {
-	init(10.0f, 1.0f/60.0f,10,10,Vector2(0.0f, -10.0f));
+	init(10.0f,10,10,Vector2(0.0f, -10.0f));
 }
 }
 
 
-PhysicsScene2D::PhysicsScene2D(Number worldScale, Number freq, int velIterations, int posIterations): Scene(Scene::SCENE_2D) {
-	init(worldScale, 1.0f/freq,velIterations, posIterations, Vector2(0.0f, -10.0f));	
+PhysicsScene2D::PhysicsScene2D(Number worldScale, int velIterations, int posIterations): Scene(Scene::SCENE_2D) {
+	init(worldScale, velIterations, posIterations, Vector2(0.0f, -10.0f));
 }
 }
 
 
-void PhysicsScene2D::init(Number worldScale, Number physicsTimeStep, int velIterations, int posIterations, Vector2 physicsGravity) {
+void PhysicsScene2D::init(Number worldScale, int velIterations, int posIterations, Vector2 physicsGravity) {
 	
 	
-	cyclesLeftOver = 0.0;
 	this->worldScale = worldScale;
 	this->worldScale = worldScale;
 	
 	
-	timeStep = physicsTimeStep;
 	velocityIterations = velIterations;
 	velocityIterations = velIterations;
     positionIterations = posIterations;
     positionIterations = posIterations;
 	
 	
@@ -547,22 +545,24 @@ void PhysicsScene2D::handleEvent(Event *event) {
 	Scene::handleEvent(event);
 	Scene::handleEvent(event);
 }
 }
 
 
-void PhysicsScene2D::Update() {
+void PhysicsScene2D::fixedUpdate() {
     
     
-	Number elapsed = CoreServices::getInstance()->getCore()->getElapsed() + cyclesLeftOver;
-	
-	while(elapsed > timeStep) {
-		elapsed -= timeStep;
-		for(int i=0; i<physicsChildren.size();i++) {
-			physicsChildren[i]->Update();
-		}
-		world->Step(timeStep, velocityIterations,positionIterations);
+    for(int i=0; i<physicsChildren.size();i++) {
+        if(physicsChildren[i]->collisionOnly) {
+            physicsChildren[i]->Update();
+        }
+    }
+    world->Step(core->getFixedTimestep(), velocityIterations,positionIterations);
+    
+    for(int i=0; i<physicsChildren.size();i++) {
+        if(!physicsChildren[i]->collisionOnly) {
+            physicsChildren[i]->Update();
+        }
+    }
 		
 		
-		for(int i=0; i < eventsToDispatch.size(); i++) {
-			dispatchEvent(eventsToDispatch[i], eventsToDispatch[i]->getEventCode());
-		}
-		eventsToDispatch.clear();
-	}
-	cyclesLeftOver = elapsed;
-	Scene::Update();
+    for(int i=0; i < eventsToDispatch.size(); i++) {
+        dispatchEvent(eventsToDispatch[i], eventsToDispatch[i]->getEventCode());
+    }
+    eventsToDispatch.clear();
+	Scene::fixedUpdate();
 }
 }

+ 0 - 1
Modules/Contents/2DPhysics/Source/PolyPhysicsScreenEntity.cpp

@@ -301,7 +301,6 @@ void PhysicsScene2DEntity::Update() {
 		Number angle = body->GetAngle();	
 		Number angle = body->GetAngle();	
 		entity->setRoll(angle*(180.0f/PI));	
 		entity->setRoll(angle*(180.0f/PI));	
 		entity->setPosition(position.x*worldScale, position.y*worldScale, 0.0);
 		entity->setPosition(position.x*worldScale, position.y*worldScale, 0.0);
-		entity->rebuildTransformMatrix();		
 	}	
 	}	
 }
 }
 
 

+ 1 - 1
Modules/Contents/3DPhysics/Include/PolyCollisionScene.h

@@ -92,7 +92,7 @@ struct CollisionResult {
 		
 		
 			void initCollisionScene(Vector3 size);
 			void initCollisionScene(Vector3 size);
 		
 		
-			virtual void Update();
+			virtual void fixedUpdate();
 			
 			
 			virtual void removeEntity(Entity *entity);
 			virtual void removeEntity(Entity *entity);
 						
 						

+ 1 - 1
Modules/Contents/3DPhysics/Include/PolyPhysicsScene.h

@@ -90,7 +90,7 @@ namespace Polycode {
 		PhysicsScene(int maxSubSteps = 0, Vector3 size = Vector3(200), bool virtualScene = false);
 		PhysicsScene(int maxSubSteps = 0, Vector3 size = Vector3(200), bool virtualScene = false);
 		virtual ~PhysicsScene();	
 		virtual ~PhysicsScene();	
 		
 		
-		void Update();		
+		void fixedUpdate();
 		
 		
 		void removeEntity(Entity *entity);
 		void removeEntity(Entity *entity);
 		
 		

+ 2 - 2
Modules/Contents/3DPhysics/Source/PolyCollisionScene.cpp

@@ -44,7 +44,7 @@ void CollisionScene::initCollisionScene(Vector3 size) {
 	world = new btCollisionWorld(dispatcher,axisSweep,collisionConfiguration);	
 	world = new btCollisionWorld(dispatcher,axisSweep,collisionConfiguration);	
 }
 }
 
 
-void CollisionScene::Update() {
+void CollisionScene::fixedUpdate() {
 	
 	
 	for(int i=0; i < collisionChildren.size(); i++) {
 	for(int i=0; i < collisionChildren.size(); i++) {
 		if(collisionChildren[i]->enabled)
 		if(collisionChildren[i]->enabled)
@@ -57,7 +57,7 @@ void CollisionScene::Update() {
 		if(collisionChildren[i]->enabled)		
 		if(collisionChildren[i]->enabled)		
 			collisionChildren[i]->lastPosition = collisionChildren[i]->getEntity()->getPosition();
 			collisionChildren[i]->lastPosition = collisionChildren[i]->getEntity()->getPosition();
 	}
 	}
-	Scene::Update();	
+	Scene::fixedUpdate();
 }
 }
 
 
 void CollisionScene::enableCollision(Entity *entity, bool val) {
 void CollisionScene::enableCollision(Entity *entity, bool val) {

+ 12 - 14
Modules/Contents/3DPhysics/Source/PolyPhysicsScene.cpp

@@ -142,23 +142,21 @@ void PhysicsScene::processWorldCollisions() {
 
 
 }
 }
 
 
-void PhysicsScene::Update() {
+void PhysicsScene::fixedUpdate() {
 	if(!pausePhysics) {
 	if(!pausePhysics) {
-	for(int i=0; i < physicsChildren.size(); i++) {
-		if(physicsChildren[i]->enabled) {
-			physicsChildren[i]->Update();
+        for(int i=0; i < physicsChildren.size(); i++) {
+            if(physicsChildren[i]->enabled) {
+                physicsChildren[i]->Update();
+            }
+        }
+                
+        if(maxSubSteps > 0) {
+            physicsWorld->stepSimulation(core->getFixedTimestep(), maxSubSteps);
+        } else {
+            physicsWorld->stepSimulation(core->getFixedTimestep());
         }
         }
 	}
 	}
-	
-	
-	Number elapsed = CoreServices::getInstance()->getCore()->getElapsed();
-	if(maxSubSteps > 0) {
-		physicsWorld->stepSimulation(elapsed, maxSubSteps);	
-	} else {
-		physicsWorld->stepSimulation(elapsed);		
-	}
-	}
-	CollisionScene::Update();
+	CollisionScene::fixedUpdate();
 	
 	
 }
 }
 
 

+ 7 - 2
Player/Contents/Source/PolycodePlayer.cpp

@@ -882,7 +882,7 @@ void PolycodePlayer::handleEvent(Event *event) {
 
 
 
 
 bool PolycodePlayer::Update() {
 bool PolycodePlayer::Update() {
-	bool retVal = core->Update();
+	bool retVal = core->systemUpdate();
 	if(L) {
 	if(L) {
 		lua_getfield (L, LUA_GLOBALSINDEX, "__customError");
 		lua_getfield (L, LUA_GLOBALSINDEX, "__customError");
 		errH = lua_gettop(L);	
 		errH = lua_gettop(L);	
@@ -893,7 +893,6 @@ bool PolycodePlayer::Update() {
 			lua_pcall(L, 0,0,errH);		
 			lua_pcall(L, 0,0,errH);		
 		}	
 		}	
 		if(!crashed) {
 		if(!crashed) {
-		
 			lua_getfield(L, LUA_GLOBALSINDEX, "__process_safe_delete");
 			lua_getfield(L, LUA_GLOBALSINDEX, "__process_safe_delete");
 			lua_pcall(L, 0,0,errH);	
 			lua_pcall(L, 0,0,errH);	
 		
 		
@@ -901,6 +900,12 @@ bool PolycodePlayer::Update() {
 			lua_pushnumber(L, core->getElapsed());
 			lua_pushnumber(L, core->getElapsed());
 			lua_pcall(L, 1,0,errH);
 			lua_pcall(L, 1,0,errH);
 		}
 		}
+        
+        while(core->fixedUpdate()) {
+			lua_getfield(L, LUA_GLOBALSINDEX, "fixedUpdate");
+			lua_pcall(L, 0,0,errH);
+        }
+        
 		lua_settop(L, 0);
 		lua_settop(L, 0);
 	}
 	}
 	core->Render();
 	core->Render();