Optimize some matrix multiply for projection matrix + Orthographic reflection 66/287766/8
authorEunki Hong <eunkiki.hong@samsung.com>
Sat, 4 Feb 2023 04:08:53 +0000 (13:08 +0900)
committerEunki, Hong <eunkiki.hong@samsung.com>
Fri, 10 Feb 2023 08:30:45 +0000 (17:30 +0900)
Let we use MatrixUtils::MultiplyProjectionMatrix for some internal API.

And also, make Orthographic camera can use reflection plane.

TODO : We should make MultiplyProjectionMatrix funtion as NEON.

Change-Id: Ifeff525ed96dc5ebdf280f794973ecbb8f4eb7ab
Signed-off-by: Eunki Hong <eunkiki.hong@samsung.com>
automated-tests/src/dali/utc-Dali-CameraActor.cpp
dali/internal/common/matrix-utils.cpp
dali/internal/common/matrix-utils.h
dali/internal/event/actors/actor-coords.cpp
dali/internal/event/actors/camera-actor-impl.cpp
dali/internal/event/common/projection.cpp
dali/internal/render/renderers/render-renderer.cpp
dali/internal/update/render-tasks/scene-graph-camera.cpp
dali/internal/update/render-tasks/scene-graph-camera.h

index 9f3e6e7..6c8af27 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -2324,6 +2324,37 @@ int UtcDaliCameraActorReflectionByPlane(void)
   matrixAfter.GetTransformComponents(position, rotation, scale);
   DALI_TEST_EQUALS(reflected, rotation, 0.01f, TEST_LOCATION);
 
+  // Test Orthographic camera
+  freeLookCameraActor.SetProjectionMode(Dali::Camera::ProjectionMode::ORTHOGRAPHIC_PROJECTION);
+
+  // Make sure the recalculation will take place
+  freeLookCameraActor.SetProperty(Dali::DevelCameraActor::Property::REFLECTION_PLANE, Vector4(0.0f, 1.0f, 0.0f, 0.0f));
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // Nothing should change despite of different camera type
+  matrixAfter.GetTransformComponents(position, rotation, scale);
+  DALI_TEST_EQUALS(reflected, rotation, 0.01f, TEST_LOCATION);
+
+  // Test Orthographic camera + Look at target
+  freeLookCameraActor.SetType(Camera::LOOK_AT_TARGET);
+  freeLookCameraActor.SetTargetPosition(targetPosition);
+
+  // Make sure the recalculation will take place
+  freeLookCameraActor.SetProperty(Dali::DevelCameraActor::Property::REFLECTION_PLANE, Vector4(0.0f, 1.0f, 0.0f, 0.0f));
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // Nothing should change despite of different camera type
+  matrixAfter.GetTransformComponents(position, rotation, scale);
+  DALI_TEST_EQUALS(reflected, rotation, 0.01f, TEST_LOCATION);
+
   END_TEST;
 }
 
index ce2eb1f..e5c7566 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -256,7 +256,7 @@ void MultiplyProjectionMatrix(Dali::Matrix& result, const Dali::Matrix& lhs, con
   // Current NEON code is copy of Multiply.
 
   MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
-  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY, 32); // 32 = 8*4
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY, 40); // 40 = 10*4
 
   float*       temp   = result.AsFloat();
   const float* rhsPtr = projection.AsFloat();
@@ -264,11 +264,13 @@ void MultiplyProjectionMatrix(Dali::Matrix& result, const Dali::Matrix& lhs, con
 
 #ifndef __ARM_NEON__
 
-  // We only use rhsPtr's 0, 1, 4, 5, 10, 11, 14, 15 index.
+  // We only use rhsPtr's 0, 1, 2, 4, 5, 6, 10, 11, 14, 15 index.
   const float rhs0  = rhsPtr[0];
   const float rhs1  = rhsPtr[1];
+  const float rhs2  = rhsPtr[2];
   const float rhs4  = rhsPtr[4];
   const float rhs5  = rhsPtr[5];
+  const float rhs6  = rhsPtr[6];
   const float rhs10 = rhsPtr[10];
   const float rhs11 = rhsPtr[11];
   const float rhs14 = rhsPtr[14];
@@ -289,7 +291,7 @@ void MultiplyProjectionMatrix(Dali::Matrix& result, const Dali::Matrix& lhs, con
 
     temp[loc0] = (value0 * rhs0) + (value1 * rhs4);
     temp[loc1] = (value0 * rhs1) + (value1 * rhs5);
-    temp[loc2] = (value2 * rhs10) + (value3 * rhs14);
+    temp[loc2] = (value0 * rhs2) + (value1 * rhs6) + (value2 * rhs10) + (value3 * rhs14);
     temp[loc3] = (value2 * rhs11) + (value3 * rhs15);
   }
 
index f65687c..9852f97 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_MATRIX_UTILS_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -59,7 +59,8 @@ void Multiply(Dali::Matrix& result, const Dali::Matrix& lhs, const Dali::Quatern
  * Perspective matrix only has 0, 5, 10, 11, 14 (14 is const value, 1.0f).
  * Orthographic matrix only has 0, 5, 10, 14, 15 (15 is const value, 1.0f).
  * If window rotated, we use 1, 4 index instead of 0, 5.
- * So we only need 8 values to multiplication.
+ * If reflect plane used, we use 2, 6 index.
+ * So we only need 10 values to multiplication.
  *
  * Use this method in time critical path as it does not require temporaries.
  *
index 9f1fefe..9fa1983 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -83,7 +83,7 @@ bool ConvertScreenToLocal(
 
   // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
   Matrix invertedMvp(false /*don't init*/);
-  MatrixUtils::Multiply(invertedMvp, modelView, projectionMatrix);
+  MatrixUtils::MultiplyProjectionMatrix(invertedMvp, modelView, projectionMatrix);
   bool success = invertedMvp.Invert();
 
   // Convert to GL coordinates
@@ -540,17 +540,17 @@ Matrix CalculateActorWorldTransform(const Actor& actor)
         parentMatrix.GetTransformComponents(parentPosition, parentOrientation, parentScale);
 
         // Compute intermediate Local information
-        centerPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
+        centerPosition                    = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, localScale, localOrientation);
         Vector3 intermediateLocalPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
-        Matrix intermediateLocalMatrix;
+        Matrix  intermediateLocalMatrix;
         intermediateLocalMatrix.SetTransformComponents(localScale, localOrientation, intermediateLocalPosition);
 
         // Compute intermediate world information
         Matrix intermediateWorldMatrix;
         MatrixUtils::Multiply(intermediateWorldMatrix, intermediateLocalMatrix, parentMatrix);
 
-        Vector3       intermediateWorldPosition, intermediateWorldScale;
-        Quaternion    intermediateWorldOrientation;
+        Vector3    intermediateWorldPosition, intermediateWorldScale;
+        Quaternion intermediateWorldOrientation;
         intermediateWorldMatrix.GetTransformComponents(intermediateWorldPosition, intermediateWorldOrientation, intermediateWorldScale);
 
         // Compute final world information
@@ -576,7 +576,7 @@ Matrix CalculateActorWorldTransform(const Actor& actor)
         // parent origin position in world space and relative position of center from parent origin.
         // If this node doesn't inherit its parent position, simply use the relative position as a final world position.
         Vector3 localCenterPosition = CalculateCenterPosition(anchorPoint, positionUsesAnchorPoint, size, finalWorldScale, finalWorldOrientation);
-        finalWorldPosition = actorPosition * finalWorldScale;
+        finalWorldPosition          = actorPosition * finalWorldScale;
         finalWorldPosition *= finalWorldOrientation;
         finalWorldPosition += localCenterPosition;
         if((inheritanceModeList[i] & INHERIT_POSITION) != 0)
index 1c6bb33..f714d74 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -107,7 +107,7 @@ void BuildOrthoPickingRay(const Matrix&   viewMatrix,
 
   // Transforms the touch point from the screen reference system to the world reference system.
   Matrix invViewProjection(false); // Don't initialize.
-  MatrixUtils::Multiply(invViewProjection, viewMatrix, projectionMatrix);
+  MatrixUtils::MultiplyProjectionMatrix(invViewProjection, viewMatrix, projectionMatrix);
   if(!invViewProjection.Invert())
   {
     DALI_ASSERT_DEBUG(false);
index e6cae8d..d662f2f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -73,7 +73,7 @@ bool UnprojectFull(const Vector4& windowPos,
                    Vector4&       objectPos)
 {
   Matrix invertedMvp(false); // Don't initialize.
-  MatrixUtils::Multiply(invertedMvp, modelView, projection);
+  MatrixUtils::MultiplyProjectionMatrix(invertedMvp, modelView, projection);
 
   if(invertedMvp.Invert())
   {
@@ -124,7 +124,7 @@ bool ProjectFull(const Vector4& position,
   bool ok = false;
 
   Matrix Mvp(false); // Don't initialize.
-  MatrixUtils::Multiply(Mvp, modelView, projection);
+  MatrixUtils::MultiplyProjectionMatrix(Mvp, modelView, projection);
 
   Vector4 p = Mvp * position;
 
index 3bea0e5..9b8c2c9 100644 (file)
@@ -487,7 +487,7 @@ bool Renderer::Render(Graphics::CommandBuffer&                             comma
     mRenderCallbackInput->size       = size;
     mRenderCallbackInput->projection = projectionMatrix;
 
-    MatrixUtils::Multiply(mRenderCallbackInput->mvp, modelViewMatrix, projectionMatrix);
+    MatrixUtils::MultiplyProjectionMatrix(mRenderCallbackInput->mvp, modelViewMatrix, projectionMatrix);
 
     // submit draw
     commandBuffer.DrawNative(&info);
@@ -739,7 +739,7 @@ void Renderer::WriteUniformBuffer(
     if(mvpUniformInfo && !mvpUniformInfo->name.empty())
     {
       Matrix modelViewProjectionMatrix(false);
-      MatrixUtils::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
+      MatrixUtils::MultiplyProjectionMatrix(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
       WriteDefaultUniform(mvpUniformInfo, *uboView, modelViewProjectionMatrix);
     }
 
index 586d7cc..450c990 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -166,6 +166,154 @@ void Orthographic(Matrix& result, Dali::DevelCameraActor::ProjectionDirection or
   m[15] = 1.0f;
 }
 
+/**
+ * Adjust near plane for reflection
+ * @param[in] perspective Perspective matrix
+ * @param[in] clipPlane Clipping plane
+ * @param[in] far Far plane distance of original projection matrix
+ */
+void AdjustNearPlaneForPerspective(Matrix& perspective, const Vector4& clipPlane, float far)
+{
+  // Make third row of perspective projection matrix as clipPlane.
+  // If me let third row vector as v = (v[2], v[6], v[10], v[14]),
+  // z_n = v * (x, y, z, 1) / z
+
+  // For example, standard case : -1 for near, 1 for far.
+  // v.z * n + v.w = -n
+  // v.z * f + v.w = f
+  // This formular makes v.z = (f + n) / (f - n), v.w = -2fn / (f - n)
+
+  // Now, we should make like this : -1 for clipPlane, 1 for farPlane.
+  // Let we think some point p : c.x * p.x + c.y * p.y + c.z * p.z + c.w = 0.
+  // v.x * p.x + v.y * p.y + v.z * p.z + v.w = -p.z;
+
+  // Since point p doesn't have any special rule, we can think that
+  // (v.x, v.y, v.z + 1, v.w) = scale * (c.x, c.y, c.z, c.w).
+  // -->
+  // v.z = scale * c.z - 1.0,
+  // v.w = scale * c.w.
+
+  // Now we have to determine scale value.
+
+  // Reference of Far plane fomular : https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc07/slides/S3730i1.pdf page 38
+  // Let we pick 'one of any edge' point Q which position on original projection frustum's far plane and...
+  // c.x * Q.x + c.y * Q.y + c.z * Q.z + c.w is maximum.
+
+  // To make Q far far away, Below fomular should be applied. (We can assume that Q.z is bigger than 0)
+  // || (v[0], 0, v[8], 0) * Q / Q.z || = 1 --> || v[0] * Q.x + v[8] * Q.z || = Q.z
+  // || (0, v[5], v[9], 0) * Q / Q.z || = 1 --> || v[5] * Q.y + v[9] * Q.z || = Q.z
+
+  // And the far plane case
+  // v * Q = Q.z
+  // --> (c * scale + (0, 0, -1, 0)) * Q = Q.z
+  // --> c * scale * Q = 2.0 * Q.z
+  // --> scale = 2.0 * Q.z / (c * Q)
+
+  float* v = perspective.AsFloat();
+
+  float maximalCDotQ = Math::MACHINE_EPSILON_0; // We should find CDotQ is positive.
+
+  float inverseV0 = 1.0f / v[0];
+  float inverseV5 = 1.0f / v[5];
+
+  // There are 4 case of solution. Choose one of them and check whether clipPlane * Q is maxium.
+  for(int testCase = 0; testCase != 4; ++testCase)
+  {
+    Vector4 Q(0.0f, 0.0f, far, 1.0f);
+
+    // Check for Q.x
+    // v[0] * Q.x = (+-1.0f - v[8]) * Q.z
+    Q.x = (((testCase & 1) ? 1.0f : -1.0f) - v[8]) * Q.z * inverseV0;
+    // v[5] * Q.y = (+-1.0f - v[9]) * Q.z
+    Q.y = (((testCase & 2) ? 1.0f : -1.0f) - v[9]) * Q.z * inverseV5;
+
+    maximalCDotQ = std::max(maximalCDotQ, clipPlane.Dot(Q));
+  }
+
+  float scale = 2.0f * far / maximalCDotQ;
+
+  Vector4 scaledPlaneVector = clipPlane * scale;
+
+  v[2]  = scaledPlaneVector.x;
+  v[6]  = scaledPlaneVector.y;
+  v[10] = scaledPlaneVector.z - 1.0f;
+  v[14] = scaledPlaneVector.w;
+}
+
+/**
+ * Adjust near plane for reflection
+ * @param[in] orthographic Orthographic matrix
+ * @param[in] clipPlane Clipping plane
+ * @param[in] far Far plane distance of original projection matrix
+ */
+void AdjustNearPlaneForOrthographic(Matrix& orthographic, const Vector4& clipPlane, float far)
+{
+  // Make third row of orthographic projection matrix as clipPlane.
+  // If me let third row vector as v = (v[2], v[6], v[10], v[14]),
+  // z_n = v * (x, y, z, 1)
+
+  // For example, standard case : -1 for near, 1 for far.
+  // v.z * n + v.w = -1
+  // v.z * f + v.w = 1
+  // This formular makes v.z = 2 / (f - n), v.w = -(f + n) / (f - n)
+
+  // Now, we should make like this : -1 for clipPlane, 1 for farPlane.
+  // Let we think some point p : c.x * p.x + c.y * p.y + c.z * p.z + c.w = 0.
+  // v.x * p.x + v.y * p.y + v.z * p.z + v.w = -1;
+
+  // Since point p doesn't have any special rule, we can think that
+  // (v.x, v.y, v.z, v.w + 1) = scale * (c.x, c.y, c.z, c.w).
+  // -->
+  // v.z = scale * c.z,
+  // v.w = scale * c.w - 1.0.
+
+  // Now we have to determine scale value.
+
+  // Reference of Far plane fomular : https://ubm-twvideo01.s3.amazonaws.com/o1/vault/gdc07/slides/S3730i1.pdf page 38
+  // Let we pick 'one of any edge' point Q which position on original projection frustum's far plane and...
+  // c.x * Q.x + c.y * Q.y + c.z * Q.z + c.w is maximum.
+
+  // To make Q far far away, Below fomular should be applied. (We can assume that Q.z is bigger than 0)
+  // || (v[0], 0, 0, v[12]) * Q || = 1 --> || v[0] * Q.x + v[12] || = 1
+  // || (0, v[5], 0, v[13]) * Q || = 1 --> || v[5] * Q.y + v[13] || = 1
+
+  // And the far plane case
+  // v * Q = 1
+  // --> (c * scale + (0, 0, 0, 1)) * Q = 1
+  // --> c * scale * Q = 2.0
+  // --> scale = 2.0 / (c * Q)
+
+  float* v = orthographic.AsFloat();
+
+  float maximalCDotQ = Math::MACHINE_EPSILON_0; // We should find CDotQ is positive.
+
+  float inverseV0 = 1.0f / v[0];
+  float inverseV5 = 1.0f / v[5];
+
+  // There are 4 case of solution. Choose one of them and check whether clipPlane * Q is maxium.
+  for(int testCase = 0; testCase != 4; ++testCase)
+  {
+    Vector4 Q(0.0f, 0.0f, far, 1.0f);
+
+    // Check for Q.x
+    // v[0] * Q.x = (+-1.0f - v[12])
+    Q.x = (((testCase & 1) ? 1.0f : -1.0f) - v[12]) * inverseV0;
+    // v[5] * Q.y = (+-1.0f - v[13])
+    Q.y = (((testCase & 2) ? 1.0f : -1.0f) - v[13]) * inverseV5;
+
+    maximalCDotQ = std::max(maximalCDotQ, clipPlane.Dot(Q));
+  }
+
+  float scale = 2.0f / maximalCDotQ;
+
+  Vector4 scaledPlaneVector = clipPlane * scale;
+
+  v[2]  = scaledPlaneVector.x;
+  v[6]  = scaledPlaneVector.y;
+  v[10] = scaledPlaneVector.z;
+  v[14] = scaledPlaneVector.w - 1.0f;
+}
+
 } // unnamed namespace
 
 const Dali::Camera::Type                          Camera::DEFAULT_TYPE(Dali::Camera::FREE_LOOK);
@@ -283,28 +431,10 @@ void VectorReflectedByPlane(Vector4& out, Vector4& in, Vector4& plane)
   out.w   = static_cast<float>(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)
 {
+  // Note :  we assume that plane.xyz is normal vector.
+
   float* v    = mReflectionMtx.AsFloat();
   float  _2ab = -2.0f * plane.x * plane.y;
   float  _2ac = -2.0f * plane.x * plane.z;
@@ -416,7 +546,7 @@ void Camera::Update(BufferIndex updateBufferIndex)
   if(viewUpdateCount > COPY_PREVIOUS_MATRIX || projectionUpdateCount > COPY_PREVIOUS_MATRIX)
   {
     // either has actually changed so recalculate
-    MatrixUtils::Multiply(mInverseViewProjection[updateBufferIndex], mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
+    MatrixUtils::MultiplyProjectionMatrix(mInverseViewProjection[updateBufferIndex], mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
     UpdateFrustum(updateBufferIndex);
 
     // ignore the error, if the view projection is incorrect (non inversible) then you will have tough times anyways
@@ -514,10 +644,12 @@ uint32_t Camera::UpdateViewMatrix(BufferIndex updateBufferIndex)
             upNew3           = Vector3(upNew);
             LookAt(viewMatrix, positionNew3, targetNewVector3, upNew3);
 
-            Matrix oldViewMatrix(viewMatrix);
-            Matrix tmp;
-            tmp.SetIdentityAndScale(Vector3(-1.0, 1.0, 1.0));
-            MatrixUtils::Multiply(viewMatrix, oldViewMatrix, tmp);
+            // Invert X
+            float* vZ = viewMatrix.AsFloat();
+            vZ[0]     = -vZ[0];
+            vZ[4]     = -vZ[4];
+            vZ[8]     = -vZ[8];
+            vZ[12]    = -vZ[12];
 
             mReflectionEye     = positionNew;
             mUseReflectionClip = true;
@@ -539,8 +671,8 @@ uint32_t Camera::UpdateViewMatrix(BufferIndex updateBufferIndex)
 void Camera::UpdateFrustum(BufferIndex updateBufferIndex, bool normalize)
 {
   // Extract the clip matrix planes
-  Matrix clipMatrix;
-  MatrixUtils::Multiply(clipMatrix, mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
+  Matrix clipMatrix(false); // Don't initialize.
+  MatrixUtils::MultiplyProjectionMatrix(clipMatrix, mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
 
   const float*   cm     = clipMatrix.AsFloat();
   FrustumPlanes& planes = mFrustum[updateBufferIndex];
@@ -685,18 +817,12 @@ uint32_t Camera::UpdateProjection(BufferIndex updateBufferIndex)
             float         d               = mReflectionPlane.Dot(mReflectionEye);
             if(d < 0)
             {
-              adjReflectPlane.w = -adjReflectPlane.w;
+              // Original eyesight was behind of mReflectionPlane. Reverse the plane.
+              adjReflectPlane = -adjReflectPlane;
             }
 
             Vector4 customClipping = viewInv * adjReflectPlane;
-            AdjustNearPlaneForPerspective(projectionMatrix, customClipping);
-
-            // Invert Z
-            Matrix matZ;
-            matZ.SetIdentity();
-            float* vZ = matZ.AsFloat();
-            vZ[10]    = -vZ[10];
-            MatrixUtils::Multiply(projectionMatrix, projectionMatrix, matZ);
+            AdjustNearPlaneForPerspective(projectionMatrix, customClipping, mFarClippingPlane);
           }
           break;
         }
@@ -710,6 +836,26 @@ uint32_t Camera::UpdateProjection(BufferIndex updateBufferIndex)
                        mNearClippingPlane,
                        mFarClippingPlane,
                        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)
+            {
+              // Original eyesight was behind of mReflectionPlane. Reverse the plane.
+              adjReflectPlane = -adjReflectPlane;
+            }
+
+            Vector4 customClipping = viewInv * adjReflectPlane;
+            AdjustNearPlaneForOrthographic(projectionMatrix, customClipping, mFarClippingPlane);
+          }
           break;
         }
       }
@@ -739,11 +885,8 @@ uint32_t Camera::UpdateProjection(BufferIndex updateBufferIndex)
           break;
       }
 
-      Matrix rotation;
-      rotation.SetIdentity();
-      rotation.SetTransformComponents(Vector3(1.0f, 1.0f, 1.0f), rotationAngle, Vector3(0.0f, 0.0f, 0.0f));
-
-      MatrixUtils::Multiply(finalProjection, mProjectionMatrix.Get(updateBufferIndex), rotation);
+      // TODO : Can't we make finalProjection without matrix multiply?
+      MatrixUtils::Multiply(finalProjection, mProjectionMatrix.Get(updateBufferIndex), rotationAngle);
     }
     --mUpdateProjectionFlag;
   }
index 6604fb9..278d765 100644 (file)
@@ -2,7 +2,7 @@
 #define DALI_INTERNAL_SCENE_GRAPH_CAMERA_H
 
 /*
- * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2023 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.
@@ -384,13 +384,6 @@ private:
    */
   void UpdateFrustum(BufferIndex updateBufferIndex, bool normalize = true);
 
-  /**
-   * Adjust near plane for reflection
-   * @param perspective Perspective matrix
-   * @param clipPlane Clipping plane
-   */
-  void AdjustNearPlaneForPerspective(Matrix& perspective, const Vector4& clipPlane);
-
   uint32_t mUpdateViewFlag;       ///< This is non-zero if the view matrix requires an update
   uint32_t mUpdateProjectionFlag; ///< This is non-zero if the projection matrix requires an update
   int      mProjectionRotation;   ///< The rotaion angle of the projection