Răsfoiți Sursa

Added a way to pause the physics simulation

BearishSun 9 ani în urmă
părinte
comite
15dc008c90

+ 8 - 0
Build/VS2015/ExampleProject.vcxproj.user

@@ -24,4 +24,12 @@
     <LocalDebuggerWorkingDirectory>..\..\bin\x64\$(Configuration)\</LocalDebuggerWorkingDirectory>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='OptimizedDebug|x64'">
+    <LocalDebuggerWorkingDirectory>..\..\bin\x64\$(Configuration)\</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='OptimizedDebug|Win32'">
+    <LocalDebuggerWorkingDirectory>..\..\bin\x86\$(Configuration)\</LocalDebuggerWorkingDirectory>
+    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
+  </PropertyGroup>
 </Project>

+ 3 - 0
Source/BansheeCore/Include/BsPhysics.h

@@ -409,6 +409,9 @@ namespace BansheeEngine
 		/** Enables or disabled a specific physics option. */
 		virtual void setFlag(PhysicsFlags flag, bool enabled) { if (enabled) mFlags |= flag; else mFlags &= ~flag; }
 
+		/** Pauses or resumes the physics simulation. */
+		virtual void setPaused(bool paused) = 0;
+
 		/** Gets the global gravity value for all objects in the scene. */
 		virtual Vector3 getGravity() const = 0;
 

+ 6 - 2
Source/BansheePhysX/Include/BsPhysX.h

@@ -183,6 +183,9 @@ namespace BansheeEngine
 		/** @copydoc Physics::setFlag */
 		void setFlag(PhysicsFlags flags, bool enabled) override;
 
+		/** @copydoc Physics::setPaused */
+		void setPaused(bool paused) override;
+
 		/** @copydoc Physics::getGravity */
 		Vector3 getGravity() const override;
 
@@ -283,10 +286,11 @@ namespace BansheeEngine
 		inline bool overlapAny(const physx::PxGeometry& geometry, const physx::PxTransform& tfrm, UINT64 layer) const;
 
 		float mSimulationStep = 1.0f/60.0f;
-		float mLastSimulationTime = 0.0f;
+		float mSimulationTime = 0.0f;
+		float mFrameTime = 0.0f;
 		float mTesselationLength = 3.0f;
 		UINT32 mNextRegionIdx = 1;
-		bool mFirstUpdate = true;
+		bool mPaused = false;
 
 		Vector<TriggerEvent> mTriggerEvents;
 		Vector<ContactEvent> mContactEvents;

+ 16 - 14
Source/BansheePhysX/Source/BsPhysX.cpp

@@ -501,6 +501,7 @@ namespace BansheeEngine
 		mCharManager = PxCreateControllerManager(*mScene);
 
 		mSimulationStep = input.timeStep;
+		mSimulationTime = -mSimulationStep * 1.01f; // Ensures simulation runs on the first frame
 		mDefaultMaterial = mPhysics->createMaterial(0.0f, 0.0f, 0.0f);
 	}
 
@@ -518,24 +519,21 @@ namespace BansheeEngine
 
 	void PhysX::update()
 	{
+		if (mPaused)
+			return;
+
 		mUpdateInProgress = true;
 
-		if(mFirstUpdate)
-		{
-			mLastSimulationTime = gTime().getTime() - mSimulationStep * 1.01f;
-			mFirstUpdate = false;
-		}
+		float nextFrameTime = mSimulationTime + mSimulationStep;
+		mFrameTime += gTime().getFrameDelta();
 
-		float nextFrameTime = mLastSimulationTime + mSimulationStep;
-		float curFrameTime = gTime().getTime();
-		if(curFrameTime < nextFrameTime)
+		if(mFrameTime < nextFrameTime)
 		{
-			// TODO - Interpolate rigidbodies but perform no actual simulation
-
+			// Note: Potentially interpolate (would mean a one frame delay needs to be introduced)
 			return;
 		}
 
-		float simulationAmount = std::max(curFrameTime - mLastSimulationTime, mSimulationStep); // At least one step
+		float simulationAmount = std::max(mFrameTime - mSimulationTime, mSimulationStep); // At least one step
 		INT32 numIterations = Math::floorToInt(simulationAmount / mSimulationStep);
 
 		// If too many iterations are required, increase time step. This should only happen in extreme situations (or when
@@ -555,7 +553,7 @@ namespace BansheeEngine
 
 			mScene->simulate(step, nullptr, scratchBuffer, SCRATCH_BUFFER_SIZE);
 			simulationAmount -= step;
-			mLastSimulationTime += step;
+			mSimulationTime += step;
 
 			UINT32 errorState;
 			if(!mScene->fetchResults(true, &errorState))
@@ -596,8 +594,7 @@ namespace BansheeEngine
 			rigidbody->_setTransform(fromPxVector(transform.p), fromPxQuaternion(transform.q));
 		}
 
-		// TODO - Consider extrapolating for the remaining "simulationAmount" value
-
+		// Note: Consider extrapolating for the remaining "simulationAmount" value
 		mUpdateInProgress = false;
 
 		triggerEvents();
@@ -1150,6 +1147,11 @@ namespace BansheeEngine
 		mCharManager->setTessellation(mFlags.isSet(PhysicsFlag::CCT_Tesselation), mTesselationLength);
 	}
 
+	void PhysX::setPaused(bool paused)
+	{
+		mPaused = paused;
+	}
+
 	Vector3 PhysX::getGravity() const
 	{
 		return fromPxVector(mScene->getGravity());

+ 7 - 0
Source/SBansheeEngine/Source/BsPlayInEditorManager.cpp

@@ -6,6 +6,7 @@
 #include "BsSceneManager.h"
 #include "BsSceneObject.h"
 #include "BsApplication.h"
+#include "BsPhysics.h"
 
 namespace BansheeEngine
 {
@@ -43,6 +44,8 @@ namespace BansheeEngine
 			mFrameStepActive = false;
 			mPausableTime = 0.0f;
 
+			gPhysics().setPaused(true);
+
 			mSavedScene->_instantiate();
 			gSceneManager()._setRootNode(mSavedScene);
 			mSavedScene = nullptr;
@@ -55,11 +58,15 @@ namespace BansheeEngine
 				saveSceneInMemory();
 				ScriptGameObjectManager::instance().wakeRuntimeComponents();
 			}
+
+			gPhysics().setPaused(false);
 		}
 			break;
 		case PlayInEditorState::Paused:
 		{
 			mFrameStepActive = false;
+			gPhysics().setPaused(true);
+
 			if (oldState == PlayInEditorState::Stopped)
 			{
 				saveSceneInMemory();