From 04fc6ed5bbe00bc226c8f20523ead194c5892a03 Mon Sep 17 00:00:00 2001 From: Kimmo Hoikka Date: Mon, 26 Jan 2015 11:51:13 +0000 Subject: [PATCH] Stop updating InverseViewProjection every frame Change-Id: Ic36faf58bd5d9b4308f69b6e36bd25b6c6ecf9ac --- .../scene-graph-camera-attachment.cpp | 111 ++++++++++++--------- .../scene-graph-camera-attachment.h | 14 ++- 2 files changed, 71 insertions(+), 54 deletions(-) diff --git a/dali/internal/update/node-attachments/scene-graph-camera-attachment.cpp b/dali/internal/update/node-attachments/scene-graph-camera-attachment.cpp index f78ce4a..97b5fb3 100644 --- a/dali/internal/update/node-attachments/scene-graph-camera-attachment.cpp +++ b/dali/internal/update/node-attachments/scene-graph-camera-attachment.cpp @@ -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 diff --git a/dali/internal/update/node-attachments/scene-graph-camera-attachment.h b/dali/internal/update/node-attachments/scene-graph-camera-attachment.h index ce6966a..c544c0c 100644 --- a/dali/internal/update/node-attachments/scene-graph-camera-attachment.h +++ b/dali/internal/update/node-attachments/scene-graph-camera-attachment.h @@ -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 -- 2.7.4