Stop updating InverseViewProjection every frame 93/34393/8
authorKimmo Hoikka <kimmo.hoikka@samsung.com>
Mon, 26 Jan 2015 11:51:13 +0000 (11:51 +0000)
committerKimmo Hoikka <kimmo.hoikka@samsung.com>
Tue, 27 Jan 2015 10:11:27 +0000 (02:11 -0800)
Change-Id: Ic36faf58bd5d9b4308f69b6e36bd25b6c6ecf9ac

dali/internal/update/node-attachments/scene-graph-camera-attachment.cpp
dali/internal/update/node-attachments/scene-graph-camera-attachment.h

index f78ce4a..97b5fb3 100644 (file)
@@ -27,8 +27,8 @@
 
 namespace // unnamed namespace
 {
-const unsigned int UPDATE_COUNT        = 2u; // Update projection or view matrix this many frames after a change
-const unsigned int COPY_PREVIOUS_PROJECTION = 1u; // Copy projection matrix from previous frame
+const unsigned int UPDATE_COUNT        = 2u;  // Update projection or view matrix this many frames after a change
+const unsigned int COPY_PREVIOUS_MATRIX = 1u; // Copy view or projection matrix from previous frame
 }
 
 namespace Dali
@@ -313,40 +313,25 @@ void CameraAttachment::Update( BufferIndex updateBufferIndex, const Node& owning
     // with the Identity.
     mUpdateProjectionFlag = UPDATE_COUNT;
   }
-  if( 0u != mUpdateViewFlag )
-  {
-    --mUpdateViewFlag;
-    switch ( mType )
-    {
-      // camera orientation taken from node - i.e. look in abitrary, unconstrained direction
-      case Dali::Camera::FREE_LOOK:
-      {
-        Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
-        viewMatrix.SetInverseTransformComponents(
-            Vector3::ONE,
-            owningNode.GetWorldRotation(updateBufferIndex),
-            owningNode.GetWorldPosition(updateBufferIndex) );
-
-        mViewMatrix.SetDirty(updateBufferIndex);
-        break;
-      }
 
-      // camera orientation constrained to look at a target
-      case Dali::Camera::LOOK_AT_TARGET:
-      {
-        Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
-        LookAt( viewMatrix,
-                owningNode.GetWorldPosition(updateBufferIndex),
-                mTargetPosition,
-                owningNode.GetWorldRotation(updateBufferIndex).Rotate(Vector3::YAXIS) );
-
-        mViewMatrix.SetDirty(updateBufferIndex);
-        break;
-      }
-    }
-  }
+  // if either matrix changed, we need to recalculate the inverse matrix for hit testing to work
+  unsigned int viewUpdateCount = UpdateViewMatrix( updateBufferIndex, owningNode );
+  unsigned int projectionUpdateCount = UpdateProjection( updateBufferIndex );
 
-  UpdateProjection( updateBufferIndex );
+  // if model or view matrix changed we need to either recalculate the inverse VP or copy previous
+  if( viewUpdateCount > COPY_PREVIOUS_MATRIX || projectionUpdateCount > COPY_PREVIOUS_MATRIX )
+  {
+    // either has actually changed so recalculate
+    Matrix::Multiply( mInverseViewProjection[ updateBufferIndex ], mViewMatrix[ updateBufferIndex ], mProjectionMatrix[ updateBufferIndex ] );
+    // ignore the error, if the view projection is incorrect (non inversible) then you will have tough times anyways
+    static_cast< void >( mInverseViewProjection[ updateBufferIndex ].Invert() );
+  }
+  else if( viewUpdateCount == COPY_PREVIOUS_MATRIX || projectionUpdateCount == COPY_PREVIOUS_MATRIX )
+  {
+    // neither has actually changed, but we might copied previous frames value so need to
+    // copy the previous inverse as well
+    mInverseViewProjection[updateBufferIndex] = mInverseViewProjection[updateBufferIndex ? 0 : 1];
+  }
 }
 
 bool CameraAttachment::ViewMatrixUpdated()
@@ -354,12 +339,52 @@ bool CameraAttachment::ViewMatrixUpdated()
   return 0u != mUpdateViewFlag;
 }
 
-void CameraAttachment::UpdateProjection( BufferIndex updateBufferIndex )
+unsigned int CameraAttachment::UpdateViewMatrix( BufferIndex updateBufferIndex, const Node& owningNode )
+{
+  unsigned int retval( mUpdateViewFlag );
+  if( 0u != mUpdateViewFlag )
+  {
+    if( COPY_PREVIOUS_MATRIX == mUpdateViewFlag )
+    {
+      // The projection matrix was updated in the previous frame; copy it
+      mViewMatrix.CopyPrevious( updateBufferIndex );
+    }
+    else // UPDATE_COUNT == mUpdateViewFlag
+    {
+      switch( mType )
+      {
+        // camera orientation taken from node - i.e. look in abitrary, unconstrained direction
+        case Dali::Camera::FREE_LOOK:
+          {
+          Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex );
+          viewMatrix.SetInverseTransformComponents( Vector3::ONE, owningNode.GetWorldRotation( updateBufferIndex ),
+                                                    owningNode.GetWorldPosition( updateBufferIndex ) );
+          mViewMatrix.SetDirty( updateBufferIndex );
+          break;
+        }
+          // camera orientation constrained to look at a target
+        case Dali::Camera::LOOK_AT_TARGET:
+          {
+          Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex );
+          LookAt( viewMatrix, owningNode.GetWorldPosition( updateBufferIndex ), mTargetPosition,
+                  owningNode.GetWorldRotation( updateBufferIndex ).Rotate( Vector3::YAXIS ) );
+          mViewMatrix.SetDirty( updateBufferIndex );
+          break;
+        }
+      }
+    }
+    --mUpdateViewFlag;
+  }
+  return retval;
+}
+
+unsigned int CameraAttachment::UpdateProjection( BufferIndex updateBufferIndex )
 {
+  unsigned int retval( mUpdateProjectionFlag );
   // Early-exit if no update required
   if ( 0u != mUpdateProjectionFlag )
   {
-    if ( COPY_PREVIOUS_PROJECTION == mUpdateProjectionFlag )
+    if ( COPY_PREVIOUS_MATRIX == mUpdateProjectionFlag )
     {
       // The projection matrix was updated in the previous frame; copy it
       mProjectionMatrix.CopyPrevious( updateBufferIndex );
@@ -396,19 +421,7 @@ void CameraAttachment::UpdateProjection( BufferIndex updateBufferIndex )
     }
     --mUpdateProjectionFlag;
   }
-
-  // if model or view matrix changed we need to recalculate the inverse VP
-  if( !mViewMatrix.IsClean() || !mProjectionMatrix.IsClean() )
-  {
-    UpdateInverseViewProjection( updateBufferIndex );
-  }
-}
-
-void CameraAttachment::UpdateInverseViewProjection( BufferIndex updateBufferIndex )
-{
-  Matrix::Multiply( mInverseViewProjection[ updateBufferIndex ], mViewMatrix[ updateBufferIndex ], mProjectionMatrix[ updateBufferIndex ] );
-  // ignore the error, if the view projection is incorrect (non inversible) then you will have tough times anyways
-  static_cast< void >( mInverseViewProjection[ updateBufferIndex ].Invert() );
+  return retval;
 }
 
 } // namespace SceneGraph
index ce6966a..c544c0c 100644 (file)
@@ -224,18 +224,22 @@ private:
   CameraAttachment& operator=(const CameraAttachment& rhs);
 
   /**
-   * Recalculates the view & projection matrices.
+   * Recalculates the view matrix.
    * @param[in] bufferIndex The current update buffer index.
+   * @param[in] owningNode to use for calculations.
+   * @return count how many frames ago the matrix was changed.
    */
-  void UpdateProjection( BufferIndex updateBufferIndex );
+  unsigned int UpdateViewMatrix( BufferIndex updateBufferIndex, const Node& owningNode );
 
   /**
-   * Recalculates the inverse modelview matrix, which is used for hit testing
-   * @param[in] updateBufferIndex The current update buffer index.
+   * Recalculates the projection matrix.
+   * @param[in] bufferIndex The current update buffer index.
+   * @return count how many frames ago the matrix was changed.
    */
-  void UpdateInverseViewProjection( BufferIndex updateBufferIndex );
+  unsigned int UpdateProjection( BufferIndex updateBufferIndex );
 
 private:
+
   unsigned int                  mUpdateViewFlag;       ///< This is non-zero if the view matrix requires an update
   unsigned int                  mUpdateProjectionFlag; ///< This is non-zero if the projection matrix requires an update