Browse Source

Fixed physics update bug that caused physics framerate dependency and instability.

Lasse Öörni 13 years ago
parent
commit
3e812ec1e0

+ 0 - 1
Bin/Data/Scripts/TestScene.as

@@ -411,7 +411,6 @@ void HandleSpawnBox(StringHash eventType, VariantMap& eventData)
     RigidBody@ body = newNode.CreateComponent("RigidBody");
     body.mass = 1;
     body.linearVelocity = rotation * Vector3(0.0, 1.0, 10.0);
-    body.linearDamping = 0.1;
     body.friction = 1.0;
 
     BoxShape@ shape = newNode.CreateComponent("BoxShape");

+ 1 - 1
Engine/Core/ProcessUtils.cpp

@@ -86,7 +86,7 @@ void GetCPUData(struct cpu_id_t* data)
 void InitFPU()
 {
     // Make sure FPU is in round-to-nearest, single precision mode
-    // This is needed for ODE to behave predictably in float mode
+    // This ensures Direct3D and OpenGL behave similarly, and all threads behave similarly
     #ifdef _MSC_VER
     _controlfp(_RC_NEAR | _PC_24, _MCW_RC | _MCW_PC);
     #else

+ 5 - 2
Engine/Physics/PhysicsWorld.cpp

@@ -153,12 +153,15 @@ void PhysicsWorld::Update(float timeStep)
 {
     PROFILE(UpdatePhysics);
     
+    // Allow max. 0.1s update at a time
+    if (timeStep > 0.1f)
+        timeStep = 0.1f;
+    
     float internalTimeStep = 1.0f / fps_;
     
     if (interpolation_)
     {
-        float minFps = 1.0f;
-        int maxSubSteps = (int)((float)fps_ / minFps);
+        int maxSubSteps = (int)(0.1f * fps_);
         world_->stepSimulation(timeStep, maxSubSteps, internalTimeStep);
     }
     else

+ 18 - 10
Engine/Physics/RigidBody.cpp

@@ -107,6 +107,7 @@ void RigidBody::getWorldTransform(btTransform &worldTrans) const
 
 void RigidBody::setWorldTransform(const btTransform &worldTrans)
 {
+    /// \todo If rigid body is parented, should set the transforms in hierarchy order (parent first)
     if (node_)
     {
         inSetTransform_ = true;
@@ -567,18 +568,25 @@ void RigidBody::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
 
 void RigidBody::OnMarkedDirty(Node* node)
 {
-    // Physics operations are not safe from worker threads
-    Scene* scene = node->GetScene();
-    if (scene && scene->IsThreadedUpdate())
+    /// \todo If the node contains a SmoothedTransform component, do not react to dirtying, but rather update the position elsewhere
+    if (!inSetTransform_)
     {
-        scene->DelayedMarkedDirty(this);
-        return;
+        // Physics operations are not safe from worker threads
+        Scene* scene = node->GetScene();
+        if (scene && scene->IsThreadedUpdate())
+        {
+            scene->DelayedMarkedDirty(this);
+            return;
+        }
+        
+        Vector3 newWorldPos = node_->GetWorldPosition();
+        Quaternion newWorldRot = node_->GetWorldRotation();
+        
+        if (newWorldPos != GetPosition())
+            SetPosition(newWorldPos);
+        if (newWorldRot != GetRotation())
+            SetRotation(newWorldRot);
     }
-    
-    /// \todo If the node contains a SmoothedTransform component, do not react to dirtying, but rather update the position elsewhere
-    
-    SetPosition(node_->GetWorldPosition());
-    SetRotation(node_->GetWorldRotation());
 }
 
 void RigidBody::OnNodeSet(Node* node)