2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <dali/internal/update/render-tasks/scene-graph-camera.h>
25 #include <dali/integration-api/debug.h>
26 #include <dali/internal/common/matrix-utils.h>
27 #include <dali/internal/common/memory-pool-object-allocator.h>
28 #include <dali/internal/update/nodes/node.h>
29 #include <dali/public-api/common/dali-common.h>
30 #include <dali/public-api/math/math-utils.h>
32 namespace // unnamed namespace
34 const uint32_t UPDATE_COUNT = 2u; // Update projection or view matrix this many frames after a change
35 const uint32_t COPY_PREVIOUS_MATRIX = 1u; // Copy view or projection matrix from previous frame
37 //For reflection and clipping plane
38 const float REFLECTION_NORMALIZED_DEVICE_COORDINATE_PARAMETER_A = 2.0f;
39 const float REFLECTION_NORMALIZED_DEVICE_COORDINATE_PARAMETER_D = 1.0f;
50 //Memory pool used to allocate new camera. Memory used by this pool will be released when shutting down DALi
51 MemoryPoolObjectAllocator<Camera>& GetCameraMemoryPool()
53 static MemoryPoolObjectAllocator<Camera> gCameraMemoryPool;
54 return gCameraMemoryPool;
60 return T(T(0) < value) - T(value < T(0));
63 void LookAt(Matrix& result, const Vector3& eye, const Vector3& target, const Vector3& up)
65 Vector3 vZ = target - eye;
68 Vector3 vX = up.Cross(vZ);
71 Vector3 vY = vZ.Cross(vX);
74 result.SetInverseTransformComponents(vX, vY, vZ, eye);
77 void Frustum(Matrix& result, float left, float right, float bottom, float top, float near, float far, bool invertYAxis)
79 float deltaZ = far - near;
80 if((near <= 0.0f) || (far <= 0.0f) || Equals(right, left) || Equals(bottom, top) || (deltaZ <= 0.0f))
82 DALI_LOG_ERROR("Invalid parameters passed into Frustum!\n");
83 DALI_ASSERT_DEBUG("Invalid parameters passed into Frustum!");
87 float deltaX = right - left;
88 float deltaY = invertYAxis ? bottom - top : top - bottom;
92 float* m = result.AsFloat();
93 m[0] = -2.0f * near / deltaX;
94 m[1] = m[2] = m[3] = 0.0f;
96 m[5] = -2.0f * near / deltaY;
97 m[4] = m[6] = m[7] = 0.0f;
99 m[8] = (right + left) / deltaX;
100 m[9] = (top + bottom) / deltaY;
101 m[10] = (near + far) / deltaZ;
104 m[14] = -2.0f * near * far / deltaZ;
105 m[12] = m[13] = m[15] = 0.0f;
108 void Perspective(Matrix& result, Dali::DevelCameraActor::ProjectionDirection fovDir, float fov, float aspect, float near, float far, bool invertYAxis)
112 if(fovDir == Dali::DevelCameraActor::ProjectionDirection::VERTICAL)
114 frustumH = tanf(fov * 0.5f) * near;
115 frustumW = frustumH * aspect;
119 frustumW = tanf(fov * 0.5f) * near;
120 frustumH = frustumW / aspect;
123 Frustum(result, -frustumW, frustumW, -frustumH, frustumH, near, far, invertYAxis);
126 void Orthographic(Matrix& result, Dali::DevelCameraActor::ProjectionDirection orthographicDir, float orthographicSize, float aspect, float near, float far, bool invertYAxis)
128 if(EqualsZero(orthographicSize) || EqualsZero(aspect) || Equals(far, near))
130 DALI_LOG_ERROR("Cannot create orthographic projection matrix with a zero dimension.\n");
131 DALI_ASSERT_DEBUG("Cannot create orthographic projection matrix with a zero dimension.");
137 if(orthographicDir == Dali::DevelCameraActor::ProjectionDirection::VERTICAL)
139 halfDeltaY = orthographicSize;
140 halfDeltaX = halfDeltaY * aspect;
144 halfDeltaX = orthographicSize;
145 halfDeltaY = halfDeltaX / aspect;
148 float deltaZ = far - near;
150 float* m = result.AsFloat();
152 m[0] = -1.0f / halfDeltaX;
158 m[5] = (invertYAxis ? 1.0f : -1.0f) / halfDeltaY;
164 m[10] = 2.0f / deltaZ;
169 m[14] = -(near + far) / deltaZ;
173 } // unnamed namespace
175 const Dali::Camera::Type Camera::DEFAULT_TYPE(Dali::Camera::FREE_LOOK);
176 const Dali::Camera::ProjectionMode Camera::DEFAULT_MODE(Dali::Camera::PERSPECTIVE_PROJECTION);
177 const Dali::DevelCameraActor::ProjectionDirection Camera::DEFAULT_PROJECTION_DIRECTION(Dali::DevelCameraActor::VERTICAL);
178 const bool Camera::DEFAULT_INVERT_Y_AXIS(false);
179 const float Camera::DEFAULT_FIELD_OF_VIEW(45.0f * (Math::PI / 180.0f));
180 const float Camera::DEFAULT_ORTHOGRAPHIC_SIZE(400.0f); // half of default height of the screen
181 const float Camera::DEFAULT_ASPECT_RATIO(480.0f / 800.0f); // default width / default height of the screen
182 const float Camera::DEFAULT_NEAR_CLIPPING_PLANE(800.0f); // default height of the screen
183 const float Camera::DEFAULT_FAR_CLIPPING_PLANE(DEFAULT_NEAR_CLIPPING_PLANE + 2.f * DEFAULT_NEAR_CLIPPING_PLANE);
184 const Vector3 Camera::DEFAULT_TARGET_POSITION(0.0f, 0.0f, 0.0f);
188 mUpdateViewFlag(UPDATE_COUNT),
189 mUpdateProjectionFlag(UPDATE_COUNT),
190 mProjectionRotation(0),
192 mProjectionMode(DEFAULT_MODE),
193 mProjectionDirection(DEFAULT_PROJECTION_DIRECTION),
194 mInvertYAxis(DEFAULT_INVERT_Y_AXIS),
195 mFieldOfView(DEFAULT_FIELD_OF_VIEW),
196 mOrthographicSize(DEFAULT_ORTHOGRAPHIC_SIZE),
197 mAspectRatio(DEFAULT_ASPECT_RATIO),
198 mNearClippingPlane(DEFAULT_NEAR_CLIPPING_PLANE),
199 mFarClippingPlane(DEFAULT_FAR_CLIPPING_PLANE),
200 mTargetPosition(DEFAULT_TARGET_POSITION),
203 mInverseViewProjection(Matrix::IDENTITY),
204 mFinalProjection(Matrix::IDENTITY)
206 // set a flag the node to say this is a camera
210 Camera* Camera::New()
212 return new(GetCameraMemoryPool().AllocateRawThreadSafe()) Camera();
215 Camera::~Camera() = default;
217 void Camera::operator delete(void* ptr)
219 GetCameraMemoryPool().FreeThreadSafe(static_cast<Camera*>(ptr));
222 void Camera::SetType(Dali::Camera::Type type)
227 void Camera::SetProjectionMode(Dali::Camera::ProjectionMode mode)
229 mProjectionMode = mode;
230 mUpdateProjectionFlag = UPDATE_COUNT;
233 void Camera::SetProjectionDirection(Dali::DevelCameraActor::ProjectionDirection direction)
235 mProjectionDirection = direction;
236 mUpdateProjectionFlag = UPDATE_COUNT;
239 void Camera::SetInvertYAxis(bool invertYAxis)
241 mInvertYAxis = invertYAxis;
242 mUpdateProjectionFlag = UPDATE_COUNT;
245 void Camera::BakeFieldOfView(BufferIndex updateBufferIndex, float fieldOfView)
247 mFieldOfView.Bake(updateBufferIndex, fieldOfView);
248 mUpdateProjectionFlag = UPDATE_COUNT;
251 void Camera::BakeOrthographicSize(BufferIndex updateBufferIndex, float orthographicSize)
253 mOrthographicSize.Bake(updateBufferIndex, orthographicSize);
254 mUpdateProjectionFlag = UPDATE_COUNT;
257 void Camera::BakeAspectRatio(BufferIndex updateBufferIndex, float aspectRatio)
259 mAspectRatio.Bake(updateBufferIndex, aspectRatio);
260 mUpdateProjectionFlag = UPDATE_COUNT;
263 void Camera::SetNearClippingPlane(float nearClippingPlane)
265 mNearClippingPlane = nearClippingPlane;
266 mUpdateProjectionFlag = UPDATE_COUNT;
269 void Camera::SetFarClippingPlane(float farClippingPlane)
271 mFarClippingPlane = farClippingPlane;
272 mUpdateProjectionFlag = UPDATE_COUNT;
275 void Camera::SetTargetPosition(const Vector3& targetPosition)
277 mTargetPosition = targetPosition;
278 mUpdateViewFlag = UPDATE_COUNT;
281 void VectorReflectedByPlane(Vector4& out, Vector4& in, Vector4& plane)
283 float d = float(2.0) * plane.Dot(in);
284 out.x = static_cast<float>(in.x - plane.x * d);
285 out.y = static_cast<float>(in.y - plane.y * d);
286 out.z = static_cast<float>(in.z - plane.z * d);
287 out.w = static_cast<float>(in.w - plane.w * d);
290 void Camera::AdjustNearPlaneForPerspective(Matrix& perspective, const Vector4& clipPlane)
293 float* v = perspective.AsFloat();
295 q.x = (Sign(clipPlane.x) + v[8]) / v[0];
296 q.y = (Sign(clipPlane.y) + v[9]) / v[5];
298 q.w = (1.0f + v[10]) / v[14];
300 // Calculate the scaled plane vector
301 Vector4 c = clipPlane * (REFLECTION_NORMALIZED_DEVICE_COORDINATE_PARAMETER_A / q.Dot(clipPlane));
303 // Replace the third row of the projection v
306 v[10] = c.z + REFLECTION_NORMALIZED_DEVICE_COORDINATE_PARAMETER_D;
310 void Camera::SetReflectByPlane(const Vector4& plane)
312 float* v = mReflectionMtx.AsFloat();
313 float _2ab = -2.0f * plane.x * plane.y;
314 float _2ac = -2.0f * plane.x * plane.z;
315 float _2bc = -2.0f * plane.y * plane.z;
317 v[0] = 1.0f - 2.0f * plane.x * plane.x;
323 v[5] = 1.0f - 2.0f * plane.y * plane.y;
329 v[10] = 1.0f - 2.0f * plane.z * plane.z;
332 v[12] = -2 * plane.x * plane.w;
333 v[13] = -2 * plane.y * plane.w;
334 v[14] = -2 * plane.z * plane.w;
337 mUseReflection = true;
338 mReflectionPlane = plane;
339 mUpdateViewFlag = UPDATE_COUNT;
342 void Camera::RotateProjection(int rotationAngle)
344 mProjectionRotation = rotationAngle;
345 mUpdateProjectionFlag = UPDATE_COUNT;
348 const Matrix& Camera::GetProjectionMatrix(BufferIndex bufferIndex) const
350 return mProjectionMatrix[bufferIndex];
353 const Matrix& Camera::GetViewMatrix(BufferIndex bufferIndex) const
355 return mViewMatrix[bufferIndex];
358 const Matrix& Camera::GetInverseViewProjectionMatrix(BufferIndex bufferIndex) const
360 return mInverseViewProjection[bufferIndex];
363 const Matrix& Camera::GetFinalProjectionMatrix(BufferIndex bufferIndex) const
365 return mFinalProjection[bufferIndex];
368 const PropertyBase* Camera::GetFieldOfView() const
370 return &mFieldOfView;
373 const PropertyBase* Camera::GetOrthographicSize() const
375 return &mOrthographicSize;
378 const PropertyBase* Camera::GetAspectRatio() const
380 return &mAspectRatio;
383 const PropertyInputImpl* Camera::GetProjectionMatrix() const
385 return &mProjectionMatrix;
388 const PropertyInputImpl* Camera::GetViewMatrix() const
393 void Camera::Update(BufferIndex updateBufferIndex)
395 // if this has changes in world position we need to update camera for next 2 frames
396 if(IsLocalMatrixDirty())
398 mUpdateViewFlag = UPDATE_COUNT;
400 if(GetDirtyFlags() & NodePropertyFlags::VISIBLE)
402 // If the visibility changes, the projection matrix needs to be re-calculated.
403 // It may happen the first time an actor is rendered it's rendered only once and becomes invisible,
404 // in the following update the node will be skipped leaving the projection matrix (double buffered)
405 // with the Identity.
406 mUpdateProjectionFlag = UPDATE_COUNT;
409 // If projection matrix relative properties are animated now, flag change.
410 if(IsProjectionMatrixAnimated())
412 mUpdateProjectionFlag = UPDATE_COUNT;
415 // if either matrix changed, we need to recalculate the inverse matrix for hit testing to work
416 uint32_t viewUpdateCount = UpdateViewMatrix(updateBufferIndex);
417 uint32_t projectionUpdateCount = UpdateProjection(updateBufferIndex);
419 // if model or view matrix changed we need to either recalculate the inverse VP or copy previous
420 if(viewUpdateCount > COPY_PREVIOUS_MATRIX || projectionUpdateCount > COPY_PREVIOUS_MATRIX)
422 // either has actually changed so recalculate
423 MatrixUtils::Multiply(mInverseViewProjection[updateBufferIndex], mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
424 UpdateFrustum(updateBufferIndex);
426 // ignore the error, if the view projection is incorrect (non inversible) then you will have tough times anyways
427 static_cast<void>(mInverseViewProjection[updateBufferIndex].Invert());
429 else if(viewUpdateCount == COPY_PREVIOUS_MATRIX || projectionUpdateCount == COPY_PREVIOUS_MATRIX)
431 // neither has actually changed, but we might copied previous frames value so need to
432 // copy the previous inverse and frustum as well
433 mInverseViewProjection[updateBufferIndex] = mInverseViewProjection[updateBufferIndex ? 0 : 1];
434 mFrustum[updateBufferIndex] = mFrustum[updateBufferIndex ? 0 : 1];
438 bool Camera::ViewMatrixUpdated() const
440 return 0u != mUpdateViewFlag;
443 bool Camera::IsProjectionMatrixAnimated() const
445 return !mFieldOfView.IsClean() ||
446 !mOrthographicSize.IsClean() ||
447 !mAspectRatio.IsClean();
450 uint32_t Camera::UpdateViewMatrix(BufferIndex updateBufferIndex)
452 uint32_t retval(mUpdateViewFlag);
453 if(0u != mUpdateViewFlag)
455 if(COPY_PREVIOUS_MATRIX == mUpdateViewFlag)
457 // The projection matrix was updated in the previous frame; copy it
458 mViewMatrix.CopyPrevious(updateBufferIndex);
460 else // UPDATE_COUNT == mUpdateViewFlag
464 // camera orientation taken from node - i.e. look in abitrary, unconstrained direction
465 case Dali::Camera::FREE_LOOK:
467 Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
468 viewMatrix = GetWorldMatrix(updateBufferIndex);
472 const Matrix& owningNodeMatrix(GetWorldMatrix(updateBufferIndex));
473 Vector3 position{}, scale{};
474 Quaternion orientation{};
475 owningNodeMatrix.GetTransformComponents(position, orientation, scale);
476 mReflectionEye = position;
477 mUseReflectionClip = true;
479 Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
480 Matrix oldViewMatrix(viewMatrix);
481 MatrixUtils::Multiply(viewMatrix, oldViewMatrix, mReflectionMtx);
485 mViewMatrix.SetDirty(updateBufferIndex);
489 // camera orientation constrained to look at a target
490 case Dali::Camera::LOOK_AT_TARGET:
492 const Matrix& owningNodeMatrix(GetWorldMatrix(updateBufferIndex));
493 Vector3 position, scale;
494 Quaternion orientation;
495 owningNodeMatrix.GetTransformComponents(position, orientation, scale);
496 Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
500 Vector3 up = orientation.Rotate(Vector3::YAXIS);
501 Vector4 position4 = Vector4(position);
502 Vector4 target4 = Vector4(mTargetPosition);
503 Vector4 up4 = Vector4(up);
507 Vector3 positionNew3;
508 Vector3 targetNewVector3;
512 VectorReflectedByPlane(positionNew, position4, mReflectionPlane);
513 VectorReflectedByPlane(targetNew, target4, mReflectionPlane);
514 VectorReflectedByPlane(upNew, up4, mReflectionPlane);
516 positionNew3 = Vector3(positionNew);
517 targetNewVector3 = Vector3(targetNew);
518 upNew3 = Vector3(upNew);
519 LookAt(viewMatrix, positionNew3, targetNewVector3, upNew3);
521 Matrix oldViewMatrix(viewMatrix);
523 tmp.SetIdentityAndScale(Vector3(-1.0, 1.0, 1.0));
524 MatrixUtils::Multiply(viewMatrix, oldViewMatrix, tmp);
526 mReflectionEye = positionNew;
527 mUseReflectionClip = true;
531 LookAt(viewMatrix, position, mTargetPosition, orientation.Rotate(Vector3::YAXIS));
533 mViewMatrix.SetDirty(updateBufferIndex);
543 void Camera::UpdateFrustum(BufferIndex updateBufferIndex, bool normalize)
545 // Extract the clip matrix planes
547 MatrixUtils::Multiply(clipMatrix, mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
549 const float* cm = clipMatrix.AsFloat();
550 FrustumPlanes& planes = mFrustum[updateBufferIndex];
553 planes.mPlanes[0].mNormal.x = cm[3] + cm[0]; // column 4 + column 1
554 planes.mPlanes[0].mNormal.y = cm[7] + cm[4];
555 planes.mPlanes[0].mNormal.z = cm[11] + cm[8];
556 planes.mPlanes[0].mDistance = cm[15] + cm[12];
559 planes.mPlanes[1].mNormal.x = cm[3] - cm[0]; // column 4 - column 1
560 planes.mPlanes[1].mNormal.y = cm[7] - cm[4];
561 planes.mPlanes[1].mNormal.z = cm[11] - cm[8];
562 planes.mPlanes[1].mDistance = cm[15] - cm[12];
565 planes.mPlanes[2].mNormal.x = cm[3] + cm[1]; // column 4 + column 2
566 planes.mPlanes[2].mNormal.y = cm[7] + cm[5];
567 planes.mPlanes[2].mNormal.z = cm[11] + cm[9];
568 planes.mPlanes[2].mDistance = cm[15] + cm[13];
571 planes.mPlanes[3].mNormal.x = cm[3] - cm[1]; // column 4 - column 2
572 planes.mPlanes[3].mNormal.y = cm[7] - cm[5];
573 planes.mPlanes[3].mNormal.z = cm[11] - cm[9];
574 planes.mPlanes[3].mDistance = cm[15] - cm[13];
577 planes.mPlanes[4].mNormal.x = cm[3] + cm[2]; // column 4 + column 3
578 planes.mPlanes[4].mNormal.y = cm[7] + cm[6];
579 planes.mPlanes[4].mNormal.z = cm[11] + cm[10];
580 planes.mPlanes[4].mDistance = cm[15] + cm[14];
583 planes.mPlanes[5].mNormal.x = cm[3] - cm[2]; // column 4 - column 3
584 planes.mPlanes[5].mNormal.y = cm[7] - cm[6];
585 planes.mPlanes[5].mNormal.z = cm[11] - cm[10];
586 planes.mPlanes[5].mDistance = cm[15] - cm[14];
590 for(uint32_t i = 0; i < 6; ++i)
592 // Normalize planes to ensure correct bounding distance checking
593 Plane& plane = planes.mPlanes[i];
594 float l = 1.0f / plane.mNormal.Length();
596 plane.mDistance *= l;
598 planes.mSign[i] = Vector3(Sign(plane.mNormal.x), Sign(plane.mNormal.y), Sign(plane.mNormal.z));
603 for(uint32_t i = 0; i < 6; ++i)
605 planes.mSign[i] = Vector3(Sign(planes.mPlanes[i].mNormal.x), Sign(planes.mPlanes[i].mNormal.y), Sign(planes.mPlanes[i].mNormal.z));
608 mFrustum[updateBufferIndex ? 0 : 1] = planes;
611 bool Camera::CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin, float radius) const
613 const FrustumPlanes& planes = mFrustum[bufferIndex];
614 for(uint32_t i = 0; i < 6; ++i)
616 if((planes.mPlanes[i].mDistance + planes.mPlanes[i].mNormal.Dot(origin)) < -radius)
624 bool Camera::CheckAABBInFrustum(BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents) const
626 const FrustumPlanes& planes = mFrustum[bufferIndex];
627 for(uint32_t i = 0; i < 6; ++i)
629 if(planes.mPlanes[i].mNormal.Dot(origin + (halfExtents * planes.mSign[i])) > -(planes.mPlanes[i].mDistance))
638 Dali::Rect<int32_t> Camera::GetOrthographicClippingBox(BufferIndex bufferIndex) const
640 const float orthographicSize = mOrthographicSize[bufferIndex];
641 const float aspect = mAspectRatio[bufferIndex];
643 const float halfWidth = mProjectionDirection == DevelCameraActor::ProjectionDirection::VERTICAL ? orthographicSize * aspect : orthographicSize;
644 const float halfHeight = mProjectionDirection == DevelCameraActor::ProjectionDirection::VERTICAL ? orthographicSize : orthographicSize / aspect;
646 return Dali::Rect<int32_t>(-halfWidth, -halfHeight, halfWidth * 2.0f, halfHeight * 2.0f);
649 uint32_t Camera::UpdateProjection(BufferIndex updateBufferIndex)
651 uint32_t retval(mUpdateProjectionFlag);
652 // Early-exit if no update required
653 if(0u != mUpdateProjectionFlag)
655 Matrix& finalProjection = mFinalProjection[updateBufferIndex];
656 finalProjection.SetIdentity();
658 if(COPY_PREVIOUS_MATRIX == mUpdateProjectionFlag)
660 // The projection matrix was updated in the previous frame; copy it
661 mProjectionMatrix.CopyPrevious(updateBufferIndex);
663 finalProjection = mFinalProjection[updateBufferIndex ? 0 : 1];
665 else // UPDATE_COUNT == mUpdateProjectionFlag
667 switch(mProjectionMode)
669 case Dali::Camera::PERSPECTIVE_PROJECTION:
671 Matrix& projectionMatrix = mProjectionMatrix.Get(updateBufferIndex);
672 Perspective(projectionMatrix,
673 mProjectionDirection,
674 mFieldOfView[updateBufferIndex],
675 mAspectRatio[updateBufferIndex],
680 //need to apply custom clipping plane
681 if(mUseReflectionClip)
683 Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
684 Matrix viewInv = viewMatrix;
688 Dali::Vector4 adjReflectPlane = mReflectionPlane;
689 float d = mReflectionPlane.Dot(mReflectionEye);
692 adjReflectPlane.w = -adjReflectPlane.w;
695 Vector4 customClipping = viewInv * adjReflectPlane;
696 AdjustNearPlaneForPerspective(projectionMatrix, customClipping);
701 float* vZ = matZ.AsFloat();
703 MatrixUtils::Multiply(projectionMatrix, projectionMatrix, matZ);
707 case Dali::Camera::ORTHOGRAPHIC_PROJECTION:
709 Matrix& projectionMatrix = mProjectionMatrix.Get(updateBufferIndex);
710 Orthographic(projectionMatrix,
711 mProjectionDirection,
712 mOrthographicSize[updateBufferIndex],
713 mAspectRatio[updateBufferIndex],
721 mProjectionMatrix.SetDirty(updateBufferIndex);
723 Quaternion rotationAngle;
724 switch(mProjectionRotation)
728 rotationAngle = Quaternion(Dali::ANGLE_90, Vector3::ZAXIS);
733 rotationAngle = Quaternion(Dali::ANGLE_180, Vector3::ZAXIS);
738 rotationAngle = Quaternion(Dali::ANGLE_270, Vector3::ZAXIS);
742 rotationAngle = Quaternion(Dali::ANGLE_0, Vector3::ZAXIS);
747 rotation.SetIdentity();
748 rotation.SetTransformComponents(Vector3(1.0f, 1.0f, 1.0f), rotationAngle, Vector3(0.0f, 0.0f, 0.0f));
750 MatrixUtils::Multiply(finalProjection, mProjectionMatrix.Get(updateBufferIndex), rotation);
752 --mUpdateProjectionFlag;
757 } // namespace SceneGraph
759 } // namespace Internal