X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fupdate%2Frender-tasks%2Fscene-graph-camera.cpp;h=c3dc3c5fd5909c286e7bb4b349c93747d347f100;hb=d353bae63798f48237dc24c078c2e8cb2aa0bc62;hp=56e6b9e5d209f4687661d3bfecf25db959998aa2;hpb=bdc9e04578363ff23d527ed8d3944aea9e303c09;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/update/render-tasks/scene-graph-camera.cpp b/dali/internal/update/render-tasks/scene-graph-camera.cpp index 56e6b9e..c3dc3c5 100644 --- a/dali/internal/update/render-tasks/scene-graph-camera.cpp +++ b/dali/internal/update/render-tasks/scene-graph-camera.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,8 +29,12 @@ 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_MATRIX = 1u; // Copy view or projection matrix from previous frame +const uint32_t UPDATE_COUNT = 2u; // Update projection or view matrix this many frames after a change +const uint32_t COPY_PREVIOUS_MATRIX = 1u; // Copy view or projection matrix from previous frame + +//For reflection and clipping plane +const float REFLECTION_NORMALIZED_DEVICE_COORDINATE_PARAMETER_A = 2.0f; +const float REFLECTION_NORMALIZED_DEVICE_COORDINATE_PARAMETER_D = 1.0f; } namespace Dali @@ -45,6 +49,12 @@ namespace SceneGraph namespace { +template< typename T > +T Sign( T value ) +{ + return T( T(0) < value ) - T( value < T(0) ); +} + void LookAt(Matrix& result, const Vector3& eye, const Vector3& target, const Vector3& up) { Vector3 vZ = target - eye; @@ -59,7 +69,6 @@ void LookAt(Matrix& result, const Vector3& eye, const Vector3& target, const Vec result.SetInverseTransformComponents(vX, vY, vZ, eye); } - void Frustum(Matrix& result, float left, float right, float bottom, float top, float near, float far, bool invertYAxis) { float deltaZ = far - near; @@ -91,13 +100,12 @@ void Frustum(Matrix& result, float left, float right, float bottom, float top, f m[12] = m[13] = m[15] = 0.0f; } -void Perspective(Matrix& result, float fovy, float aspect, float near, float far, bool invertYAxis, const Vector2& stereoBias ) +void Perspective(Matrix& result, float fovy, float aspect, float near, float far, bool invertYAxis ) { float frustumH = tanf( fovy * 0.5f ) * near; float frustumW = frustumH * aspect; - Vector2 bias = stereoBias * 0.5f; - Frustum(result, -(frustumW + bias.x), frustumW - bias.x, -(frustumH + bias.y), frustumH - bias.y, near, far, invertYAxis); + Frustum(result, -frustumW, frustumW, -frustumH, frustumH, near, far, invertYAxis); } void Orthographic(Matrix& result, float left, float right, float bottom, float top, float near, float far, bool invertYAxis) @@ -139,7 +147,7 @@ void Orthographic(Matrix& result, float left, float right, float bottom, float t const Dali::Camera::Type Camera::DEFAULT_TYPE( Dali::Camera::FREE_LOOK ); const Dali::Camera::ProjectionMode Camera::DEFAULT_MODE( Dali::Camera::PERSPECTIVE_PROJECTION ); const bool Camera::DEFAULT_INVERT_Y_AXIS( false ); -const float Camera::DEFAULT_FIELD_OF_VIEW( 45.0f*(M_PI/180.0f) ); +const float Camera::DEFAULT_FIELD_OF_VIEW( 45.0f*(Math::PI/180.0f) ); const float Camera::DEFAULT_ASPECT_RATIO( 4.0f/3.0f ); const float Camera::DEFAULT_LEFT_CLIPPING_PLANE(-240.0f); const float Camera::DEFAULT_RIGHT_CLIPPING_PLANE(240.0f); @@ -147,13 +155,13 @@ const float Camera::DEFAULT_TOP_CLIPPING_PLANE(-400.0f); const float Camera::DEFAULT_BOTTOM_CLIPPING_PLANE(400.0f); const float Camera::DEFAULT_NEAR_CLIPPING_PLANE( 800.0f ); // default height of the screen const float Camera::DEFAULT_FAR_CLIPPING_PLANE( DEFAULT_NEAR_CLIPPING_PLANE + 2.f * DEFAULT_NEAR_CLIPPING_PLANE ); -const Vector2 Camera::DEFAULT_STEREO_BIAS( 0.0f, 0.0f ); const Vector3 Camera::DEFAULT_TARGET_POSITION( 0.0f, 0.0f, 0.0f ); Camera::Camera() : mUpdateViewFlag( UPDATE_COUNT ), mUpdateProjectionFlag( UPDATE_COUNT ), + mProjectionRotation( 0 ), mNode( NULL ), mType( DEFAULT_TYPE ), mProjectionMode( DEFAULT_MODE ), @@ -166,11 +174,11 @@ Camera::Camera() mBottomClippingPlane( DEFAULT_BOTTOM_CLIPPING_PLANE ), mNearClippingPlane( DEFAULT_NEAR_CLIPPING_PLANE ), mFarClippingPlane( DEFAULT_FAR_CLIPPING_PLANE ), - mStereoBias( DEFAULT_STEREO_BIAS ), mTargetPosition( DEFAULT_TARGET_POSITION ), mViewMatrix(), mProjectionMatrix(), - mInverseViewProjection( Matrix::IDENTITY ) + mInverseViewProjection( Matrix::IDENTITY ), + mFinalProjection( Matrix::IDENTITY ) { } @@ -217,12 +225,6 @@ void Camera::SetAspectRatio( float aspectRatio ) mUpdateProjectionFlag = UPDATE_COUNT; } -void Camera::SetStereoBias( const Vector2& stereoBias ) -{ - mStereoBias = stereoBias; - mUpdateProjectionFlag = UPDATE_COUNT; -} - void Camera::SetLeftClippingPlane( float leftClippingPlane ) { mLeftClippingPlane = leftClippingPlane; @@ -265,6 +267,73 @@ void Camera::SetTargetPosition( const Vector3& targetPosition ) mUpdateViewFlag = UPDATE_COUNT; } +void VectorReflectedByPlane(Vector4 &out, Vector4 &in, Vector4 &plane) +{ + float d = float(2.0) * plane.Dot(in); + out.x = static_cast(in.x - plane.x*d); + out.y = static_cast(in.y - plane.y*d); + out.z = static_cast(in.z - plane.z*d); + out.w = static_cast(in.w - plane.w*d); +} + +void Camera::AdjustNearPlaneForPerspective( Matrix& perspective, const Vector4& clipPlane ) +{ + Vector4 q; + float* v = perspective.AsFloat(); + + q.x = (Sign(clipPlane.x) + v[8]) / v[0]; + q.y = (Sign(clipPlane.y) + v[9]) / v[5]; + q.z = -1.0f; + q.w = (1.0f + v[10]) / v[14]; + + // Calculate the scaled plane vector + Vector4 c = clipPlane * (REFLECTION_NORMALIZED_DEVICE_COORDINATE_PARAMETER_A / q.Dot( clipPlane)); + + // Replace the third row of the projection v + v[2] = c.x; + v[6] = c.y; + v[10] = c.z + REFLECTION_NORMALIZED_DEVICE_COORDINATE_PARAMETER_D; + v[14] = c.w; +} + +void Camera::SetReflectByPlane( const Vector4& plane ) +{ + float* v = mReflectionMtx.AsFloat(); + float _2ab = -2.0f * plane.x * plane.y; + float _2ac = -2.0f * plane.x * plane.z; + float _2bc = -2.0f * plane.y * plane.z; + + v[0] = 1.0f - 2.0f * plane.x * plane.x; + v[1] = _2ab; + v[2] = _2ac; + v[3] = 0.0f; + + v[4] = _2ab; + v[5] = 1.0f - 2.0f * plane.y * plane.y; + v[6] = _2bc; + v[7] = 0.0f; + + v[8] = _2ac; + v[9] = _2bc; + v[10] = 1.0f - 2.0f * plane.z * plane.z; + v[11] = 0.0f; + + v[12] = - 2 * plane.x * plane.w; + v[13] = - 2 * plane.y * plane.w; + v[14] = - 2 * plane.z * plane.w; + v[15] = 1.0f; + + mUseReflection = true; + mReflectionPlane = plane; + mUpdateViewFlag = UPDATE_COUNT; +} + +void Camera::RotateProjection( int rotationAngle ) +{ + mProjectionRotation = rotationAngle; + mUpdateViewFlag = UPDATE_COUNT; +} + const Matrix& Camera::GetProjectionMatrix( BufferIndex bufferIndex ) const { return mProjectionMatrix[ bufferIndex ]; @@ -280,6 +349,11 @@ const Matrix& Camera::GetInverseViewProjectionMatrix( BufferIndex bufferIndex ) return mInverseViewProjection[ bufferIndex ]; } +const Matrix& Camera::GetFinalProjectionMatrix( BufferIndex bufferIndex ) const +{ + return mFinalProjection[ bufferIndex ]; +} + const PropertyInputImpl* Camera::GetProjectionMatrix() const { return &mProjectionMatrix; @@ -297,7 +371,7 @@ void Camera::Update( BufferIndex updateBufferIndex ) { mUpdateViewFlag = UPDATE_COUNT; } - if( mNode->GetDirtyFlags() & VisibleFlag ) + if( mNode->GetDirtyFlags() & NodePropertyFlags::VISIBLE ) { // If the visibility changes, the projection matrix needs to be re-calculated. // It may happen the first time an actor is rendered it's rendered only once and becomes invisible, @@ -307,8 +381,8 @@ void Camera::Update( BufferIndex updateBufferIndex ) } // if either matrix changed, we need to recalculate the inverse matrix for hit testing to work - unsigned int viewUpdateCount = UpdateViewMatrix( updateBufferIndex ); - unsigned int projectionUpdateCount = UpdateProjection( updateBufferIndex ); + uint32_t viewUpdateCount = UpdateViewMatrix( updateBufferIndex ); + uint32_t projectionUpdateCount = 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 ) @@ -334,9 +408,9 @@ bool Camera::ViewMatrixUpdated() return 0u != mUpdateViewFlag; } -unsigned int Camera::UpdateViewMatrix( BufferIndex updateBufferIndex ) +uint32_t Camera::UpdateViewMatrix( BufferIndex updateBufferIndex ) { - unsigned int retval( mUpdateViewFlag ); + uint32_t retval( mUpdateViewFlag ); if( 0u != mUpdateViewFlag ) { if( COPY_PREVIOUS_MATRIX == mUpdateViewFlag ) @@ -353,11 +427,27 @@ unsigned int Camera::UpdateViewMatrix( BufferIndex updateBufferIndex ) { Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex ); viewMatrix = mNode->GetWorldMatrix( updateBufferIndex ); + + if (mUseReflection) + { + const Matrix& owningNodeMatrix( mNode->GetWorldMatrix( updateBufferIndex ) ); + Vector3 position{}, scale{}; + Quaternion orientation{}; + owningNodeMatrix.GetTransformComponents( position, orientation, scale ); + mReflectionEye = position; + mUseReflectionClip = true; + + Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex ); + Matrix oldViewMatrix( viewMatrix ); + Matrix::Multiply(viewMatrix, oldViewMatrix, mReflectionMtx); + } + viewMatrix.Invert(); mViewMatrix.SetDirty( updateBufferIndex ); break; } - // camera orientation constrained to look at a target + + // camera orientation constrained to look at a target case Dali::Camera::LOOK_AT_TARGET: { const Matrix& owningNodeMatrix( mNode->GetWorldMatrix( updateBufferIndex ) ); @@ -365,7 +455,42 @@ unsigned int Camera::UpdateViewMatrix( BufferIndex updateBufferIndex ) Quaternion orientation; owningNodeMatrix.GetTransformComponents( position, orientation, scale ); Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex ); - LookAt( viewMatrix, position, mTargetPosition, orientation.Rotate( Vector3::YAXIS ) ); + + if (mUseReflection) + { + Vector3 up = orientation.Rotate( Vector3::YAXIS ); + Vector4 position4 = Vector4(position); + Vector4 target4 = Vector4(mTargetPosition); + Vector4 up4 = Vector4(up); + Vector4 positionNew; + Vector4 targetNew; + Vector4 upNew; + Vector3 positionNew3; + Vector3 targetNewVector3; + Vector3 upNew3; + + // eye + VectorReflectedByPlane(positionNew, position4, mReflectionPlane); + VectorReflectedByPlane(targetNew, target4, mReflectionPlane); + VectorReflectedByPlane(upNew, up4, mReflectionPlane); + + positionNew3 = Vector3(positionNew); + targetNewVector3 = Vector3(targetNew); + upNew3 = Vector3(upNew); + LookAt(viewMatrix, positionNew3, targetNewVector3, upNew3 ); + + Matrix oldViewMatrix( viewMatrix ); + Matrix tmp; + tmp.SetIdentityAndScale(Vector3(-1.0, 1.0,1.0)); + Matrix::Multiply(viewMatrix, oldViewMatrix, tmp); + + mReflectionEye = positionNew; + mUseReflectionClip = true; + } + else + { + LookAt( viewMatrix, position, mTargetPosition, orientation.Rotate( Vector3::YAXIS ) ); + } mViewMatrix.SetDirty( updateBufferIndex ); break; } @@ -424,7 +549,7 @@ void Camera::UpdateFrustum( BufferIndex updateBufferIndex, bool normalize ) if ( normalize ) { - for ( unsigned int i = 0; i < 6; ++i ) + for ( uint32_t i = 0; i < 6; ++i ) { // Normalize planes to ensure correct bounding distance checking Plane& plane = planes.mPlanes[ i ]; @@ -437,7 +562,7 @@ void Camera::UpdateFrustum( BufferIndex updateBufferIndex, bool normalize ) } else { - for ( unsigned int i = 0; i < 6; ++i ) + for ( uint32_t i = 0; i < 6; ++i ) { planes.mSign[i] = Vector3( Sign(planes.mPlanes[ i ].mNormal.x), Sign(planes.mPlanes[ i ].mNormal.y), Sign(planes.mPlanes[ i ].mNormal.z) ); } @@ -473,9 +598,9 @@ bool Camera::CheckAABBInFrustum( BufferIndex bufferIndex, const Vector3& origin, return true; } -unsigned int Camera::UpdateProjection( BufferIndex updateBufferIndex ) +uint32_t Camera::UpdateProjection( BufferIndex updateBufferIndex ) { - unsigned int retval( mUpdateProjectionFlag ); + uint32_t retval( mUpdateProjectionFlag ); // Early-exit if no update required if ( 0u != mUpdateProjectionFlag ) { @@ -496,8 +621,33 @@ unsigned int Camera::UpdateProjection( BufferIndex updateBufferIndex ) mAspectRatio, mNearClippingPlane, mFarClippingPlane, - mInvertYAxis, - mStereoBias ); + mInvertYAxis ); + + //need to apply custom clipping plane + if (mUseReflectionClip) + { + Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex ); + Matrix viewInv = viewMatrix; + viewInv.Invert(); + viewInv.Transpose(); + + Dali::Vector4 adjReflectPlane = mReflectionPlane; + float d = mReflectionPlane.Dot(mReflectionEye); + if (d < 0) + { + adjReflectPlane.w = -adjReflectPlane.w; + } + + Vector4 customClipping = viewInv * adjReflectPlane; + AdjustNearPlaneForPerspective(projectionMatrix, customClipping); + + // Invert Z + Matrix matZ; + matZ.SetIdentity(); + float* vZ = matZ.AsFloat(); + vZ[10] = -vZ[10]; + Matrix::Multiply(projectionMatrix, projectionMatrix , matZ); + } break; } case Dali::Camera::ORTHOGRAPHIC_PROJECTION: @@ -513,6 +663,38 @@ unsigned int Camera::UpdateProjection( BufferIndex updateBufferIndex ) } mProjectionMatrix.SetDirty( updateBufferIndex ); + + Matrix &finalProjection = mFinalProjection[ updateBufferIndex ]; + finalProjection.SetIdentity(); + + Quaternion rotationAngle; + switch( mProjectionRotation ) + { + case 90: + { + rotationAngle = Quaternion( Dali::ANGLE_90, Vector3::ZAXIS ); + break; + } + case 180: + { + rotationAngle = Quaternion( Dali::ANGLE_180, Vector3::ZAXIS ); + break; + } + case 270: + { + rotationAngle = Quaternion( Dali::ANGLE_270, Vector3::ZAXIS ); + break; + } + default: + rotationAngle = Quaternion( Dali::ANGLE_0, Vector3::ZAXIS ); + break; + } + + Matrix rotation; + rotation.SetIdentity(); + rotation.SetTransformComponents( Vector3( 1.0f, 1.0f, 1.0f ), rotationAngle, Vector3( 0.0f, 0.0f, 0.0f ) ); + + Matrix::Multiply( finalProjection, mProjectionMatrix.Get( updateBufferIndex ), rotation ); } --mUpdateProjectionFlag; }