Browse Source

Keep track of animation being dirtied while model was invisible, and force update in that case during UpdateGeometry(). Potentially a fix for #875.

Lasse Öörni 10 years ago
parent
commit
0fa04d4c3f
2 changed files with 22 additions and 4 deletions
  1. 20 4
      Source/Urho3D/Graphics/AnimatedModel.cpp
  2. 2 0
      Source/Urho3D/Graphics/AnimatedModel.h

+ 20 - 4
Source/Urho3D/Graphics/AnimatedModel.cpp

@@ -71,7 +71,8 @@ AnimatedModel::AnimatedModel(Context* context) :
     boneBoundingBoxDirty_(true),
     boneBoundingBoxDirty_(true),
     isMaster_(true),
     isMaster_(true),
     loading_(false),
     loading_(false),
-    assignBonesPending_(false)
+    assignBonesPending_(false),
+    forceAnimationUpdate_(false)
 {
 {
 }
 }
 
 
@@ -209,9 +210,17 @@ void AnimatedModel::Update(const FrameInfo& frame)
     // If headless, retain the current animation distance (should be 0)
     // If headless, retain the current animation distance (should be 0)
     if (frame.camera_ && abs((int)frame.frameNumber_ - (int)viewFrameNumber_) > 1)
     if (frame.camera_ && abs((int)frame.frameNumber_ - (int)viewFrameNumber_) > 1)
     {
     {
-        // First check for no update at all when invisible
+        // First check for no update at all when invisible. In that case reset LOD timer to ensure update
+        // next time the model is in view
         if (!updateInvisible_)
         if (!updateInvisible_)
+        {
+            if (animationDirty_)
+            {
+                animationLodTimer_ = -1.0f;
+                forceAnimationUpdate_ = true;
+            }
             return;
             return;
+        }
         float distance = frame.camera_->GetDistance(node_->GetWorldPosition());
         float distance = frame.camera_->GetDistance(node_->GetWorldPosition());
         // If distance is greater than draw distance, no need to update at all
         // If distance is greater than draw distance, no need to update at all
         if (drawDistance_ > 0.0f && distance > drawDistance_)
         if (drawDistance_ > 0.0f && distance > drawDistance_)
@@ -266,6 +275,13 @@ void AnimatedModel::UpdateBatches(const FrameInfo& frame)
 
 
 void AnimatedModel::UpdateGeometry(const FrameInfo& frame)
 void AnimatedModel::UpdateGeometry(const FrameInfo& frame)
 {
 {
+    // Late update in case the model came into view and animation was dirtied in the meanwhile
+    if (forceAnimationUpdate_)
+    {
+        UpdateAnimation(frame);
+        forceAnimationUpdate_ = false;
+    }
+
     if (morphsDirty_)
     if (morphsDirty_)
         UpdateMorphs();
         UpdateMorphs();
 
 
@@ -275,7 +291,7 @@ void AnimatedModel::UpdateGeometry(const FrameInfo& frame)
 
 
 UpdateGeometryType AnimatedModel::GetUpdateGeometryType()
 UpdateGeometryType AnimatedModel::GetUpdateGeometryType()
 {
 {
-    if (morphsDirty_)
+    if (morphsDirty_ || forceAnimationUpdate_)
         return UPDATE_MAIN_THREAD;
         return UPDATE_MAIN_THREAD;
     else if (skinningDirty_)
     else if (skinningDirty_)
         return UPDATE_WORKER_THREAD;
         return UPDATE_WORKER_THREAD;
@@ -1124,7 +1140,7 @@ void AnimatedModel::UpdateAnimation(const FrameInfo& frame)
     // If using animation LOD, accumulate time and see if it is time to update
     // If using animation LOD, accumulate time and see if it is time to update
     if (animationLodBias_ > 0.0f && animationLodDistance_ > 0.0f)
     if (animationLodBias_ > 0.0f && animationLodDistance_ > 0.0f)
     {
     {
-        // Check for first time update
+        // Perform the first update always regardless of LOD timer
         if (animationLodTimer_ >= 0.0f)
         if (animationLodTimer_ >= 0.0f)
         {
         {
             animationLodTimer_ += animationLodBias_ * frame.timeStep_ * ANIMATION_LOD_BASESCALE;
             animationLodTimer_ += animationLodBias_ * frame.timeStep_ * ANIMATION_LOD_BASESCALE;

+ 2 - 0
Source/Urho3D/Graphics/AnimatedModel.h

@@ -250,6 +250,8 @@ private:
     bool loading_;
     bool loading_;
     /// Bone nodes assignment pending flag.
     /// Bone nodes assignment pending flag.
     bool assignBonesPending_;
     bool assignBonesPending_;
+    /// Force animation update after becoming visible flag.
+    bool forceAnimationUpdate_;
 };
 };
 
 
 }
 }