Browse Source

Force the RigidBody's interpolation transform only inside FixedUpdate() to prevent strange behavior with parented rigidbodies.

Lasse Öörni 10 years ago
parent
commit
d3d1538e5b

+ 4 - 0
Source/Urho3D/Physics/PhysicsWorld.cpp

@@ -129,6 +129,7 @@ PhysicsWorld::PhysicsWorld(Context* context) :
     interpolation_(true),
     internalEdge_(true),
     applyingTransforms_(false),
+    simulating_(false),
     debugRenderer_(0),
     debugMode_(btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits)
 {
@@ -249,6 +250,7 @@ void PhysicsWorld::Update(float timeStep)
         maxSubSteps = Min(maxSubSteps, maxSubSteps_);
 
     delayedWorldTransforms_.Clear();
+    simulating_ = true;
 
     if (interpolation_)
         world_->stepSimulation(timeStep, maxSubSteps, internalTimeStep);
@@ -263,6 +265,8 @@ void PhysicsWorld::Update(float timeStep)
         }
     }
 
+    simulating_ = false;
+
     // Apply delayed (parented) world transforms now
     while (!delayedWorldTransforms_.Empty())
     {

+ 7 - 2
Source/Urho3D/Physics/PhysicsWorld.h

@@ -244,6 +244,9 @@ public:
     /// Return whether node dirtying should be disregarded.
     bool IsApplyingTransforms() const { return applyingTransforms_; }
 
+    /// Return whether is currently inside the Bullet substep loop.
+    bool IsSimulating() const { return simulating_; }
+
 protected:
     /// Handle scene being assigned.
     virtual void OnSceneSet(Scene* scene);
@@ -308,12 +311,14 @@ private:
     bool internalEdge_;
     /// Applying transforms flag.
     bool applyingTransforms_;
+    /// Simulating flag.
+    bool simulating_;
+    /// Debug draw depth test mode.
+    bool debugDepthTest_;
     /// Debug renderer.
     DebugRenderer* debugRenderer_;
     /// Debug draw flags.
     int debugMode_;
-    /// Debug draw depth test mode.
-    bool debugDepthTest_;
 };
 
 /// Register Physics library objects.

+ 25 - 12
Source/Urho3D/Physics/RigidBody.cpp

@@ -240,9 +240,14 @@ void RigidBody::SetPosition(const Vector3& position)
         worldTrans.setOrigin(ToBtVector3(position + ToQuaternion(worldTrans.getRotation()) * centerOfMass_));
 
         // When forcing the physics position, set also interpolated position so that there is no jitter
-        btTransform interpTrans = body_->getInterpolationWorldTransform();
-        interpTrans.setOrigin(worldTrans.getOrigin());
-        body_->setInterpolationWorldTransform(interpTrans);
+        // When not inside the simulation loop, this may lead to erratic movement of parented rigidbodies
+        // so skip in that case
+        if (physicsWorld_->IsSimulating())
+        {
+            btTransform interpTrans = body_->getInterpolationWorldTransform();
+            interpTrans.setOrigin(worldTrans.getOrigin());
+            body_->setInterpolationWorldTransform(interpTrans);
+        }
 
         Activate();
         MarkNetworkUpdate();
@@ -259,11 +264,15 @@ void RigidBody::SetRotation(const Quaternion& rotation)
         if (!centerOfMass_.Equals(Vector3::ZERO))
             worldTrans.setOrigin(ToBtVector3(oldPosition + rotation * centerOfMass_));
 
-        btTransform interpTrans = body_->getInterpolationWorldTransform();
-        interpTrans.setRotation(worldTrans.getRotation());
-        if (!centerOfMass_.Equals(Vector3::ZERO))
-            interpTrans.setOrigin(worldTrans.getOrigin());
-        body_->setInterpolationWorldTransform(interpTrans);
+        if (physicsWorld_->IsSimulating())
+        {
+            btTransform interpTrans = body_->getInterpolationWorldTransform();
+            interpTrans.setRotation(worldTrans.getRotation());
+            if (!centerOfMass_.Equals(Vector3::ZERO))
+                interpTrans.setOrigin(worldTrans.getOrigin());
+            body_->setInterpolationWorldTransform(interpTrans);
+        }
+        
         body_->updateInertiaTensor();
 
         Activate();
@@ -279,10 +288,14 @@ void RigidBody::SetTransform(const Vector3& position, const Quaternion& rotation
         worldTrans.setRotation(ToBtQuaternion(rotation));
         worldTrans.setOrigin(ToBtVector3(position + rotation * centerOfMass_));
 
-        btTransform interpTrans = body_->getInterpolationWorldTransform();
-        interpTrans.setOrigin(worldTrans.getOrigin());
-        interpTrans.setRotation(worldTrans.getRotation());
-        body_->setInterpolationWorldTransform(interpTrans);
+        if (physicsWorld_->IsSimulating())
+        {
+            btTransform interpTrans = body_->getInterpolationWorldTransform();
+            interpTrans.setOrigin(worldTrans.getOrigin());
+            interpTrans.setRotation(worldTrans.getRotation());
+            body_->setInterpolationWorldTransform(interpTrans);
+        }
+
         body_->updateInertiaTensor();
 
         Activate();