/*
- * 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.
// 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
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
// 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)
/*
- * 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.
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);
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;
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
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;
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];
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;
}
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;
}
}
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;
}