2 * Copyright (c) 2022 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> gCameraMemoryPool;
56 return T(T(0) < value) - T(value < T(0));
59 void LookAt(Matrix& result, const Vector3& eye, const Vector3& target, const Vector3& up)
61 Vector3 vZ = target - eye;
64 Vector3 vX = up.Cross(vZ);
67 Vector3 vY = vZ.Cross(vX);
70 result.SetInverseTransformComponents(vX, vY, vZ, eye);
73 void Frustum(Matrix& result, float left, float right, float bottom, float top, float near, float far, bool invertYAxis)
75 float deltaZ = far - near;
76 if((near <= 0.0f) || (far <= 0.0f) || Equals(right, left) || Equals(bottom, top) || (deltaZ <= 0.0f))
78 DALI_LOG_ERROR("Invalid parameters passed into Frustum!\n");
79 DALI_ASSERT_DEBUG("Invalid parameters passed into Frustum!");
83 float deltaX = right - left;
84 float deltaY = invertYAxis ? bottom - top : top - bottom;
88 float* m = result.AsFloat();
89 m[0] = -2.0f * near / deltaX;
90 m[1] = m[2] = m[3] = 0.0f;
92 m[5] = -2.0f * near / deltaY;
93 m[4] = m[6] = m[7] = 0.0f;
95 m[8] = (right + left) / deltaX;
96 m[9] = (top + bottom) / deltaY;
97 m[10] = (near + far) / deltaZ;
100 m[14] = -2.0f * near * far / deltaZ;
101 m[12] = m[13] = m[15] = 0.0f;
104 void Perspective(Matrix& result, Dali::DevelCameraActor::ProjectionDirection fovDir, float fov, float aspect, float near, float far, bool invertYAxis)
108 if(fovDir == Dali::DevelCameraActor::ProjectionDirection::VERTICAL)
110 frustumH = tanf(fov * 0.5f) * near;
111 frustumW = frustumH * aspect;
115 frustumW = tanf(fov * 0.5f) * near;
116 frustumH = frustumW / aspect;
119 Frustum(result, -frustumW, frustumW, -frustumH, frustumH, near, far, invertYAxis);
122 void Orthographic(Matrix& result, Dali::DevelCameraActor::ProjectionDirection orthographicDir, float orthographicSize, float aspect, float near, float far, bool invertYAxis)
124 if(EqualsZero(orthographicSize) || EqualsZero(aspect) || Equals(far, near))
126 DALI_LOG_ERROR("Cannot create orthographic projection matrix with a zero dimension.\n");
127 DALI_ASSERT_DEBUG("Cannot create orthographic projection matrix with a zero dimension.");
133 if(orthographicDir == Dali::DevelCameraActor::ProjectionDirection::VERTICAL)
135 halfDeltaY = orthographicSize;
136 halfDeltaX = halfDeltaY * aspect;
140 halfDeltaX = orthographicSize;
141 halfDeltaY = halfDeltaX / aspect;
144 float deltaZ = far - near;
146 float* m = result.AsFloat();
148 m[0] = -1.0f / halfDeltaX;
154 m[5] = (invertYAxis ? 1.0f : -1.0f) / halfDeltaY;
160 m[10] = 2.0f / deltaZ;
165 m[14] = -(near + far) / deltaZ;
169 } // unnamed namespace
171 const Dali::Camera::Type Camera::DEFAULT_TYPE(Dali::Camera::FREE_LOOK);
172 const Dali::Camera::ProjectionMode Camera::DEFAULT_MODE(Dali::Camera::PERSPECTIVE_PROJECTION);
173 const Dali::DevelCameraActor::ProjectionDirection Camera::DEFAULT_PROJECTION_DIRECTION(Dali::DevelCameraActor::VERTICAL);
174 const bool Camera::DEFAULT_INVERT_Y_AXIS(false);
175 const float Camera::DEFAULT_FIELD_OF_VIEW(45.0f * (Math::PI / 180.0f));
176 const float Camera::DEFAULT_ORTHOGRAPHIC_SIZE(400.0f); // half of default height of the screen
177 const float Camera::DEFAULT_ASPECT_RATIO(480.0f / 800.0f); // default width / default height of the screen
178 const float Camera::DEFAULT_NEAR_CLIPPING_PLANE(800.0f); // default height of the screen
179 const float Camera::DEFAULT_FAR_CLIPPING_PLANE(DEFAULT_NEAR_CLIPPING_PLANE + 2.f * DEFAULT_NEAR_CLIPPING_PLANE);
180 const Vector3 Camera::DEFAULT_TARGET_POSITION(0.0f, 0.0f, 0.0f);
184 mUpdateViewFlag(UPDATE_COUNT),
185 mUpdateProjectionFlag(UPDATE_COUNT),
186 mProjectionRotation(0),
188 mProjectionMode(DEFAULT_MODE),
189 mProjectionDirection(DEFAULT_PROJECTION_DIRECTION),
190 mInvertYAxis(DEFAULT_INVERT_Y_AXIS),
191 mFieldOfView(DEFAULT_FIELD_OF_VIEW),
192 mOrthographicSize(DEFAULT_ORTHOGRAPHIC_SIZE),
193 mAspectRatio(DEFAULT_ASPECT_RATIO),
194 mNearClippingPlane(DEFAULT_NEAR_CLIPPING_PLANE),
195 mFarClippingPlane(DEFAULT_FAR_CLIPPING_PLANE),
196 mTargetPosition(DEFAULT_TARGET_POSITION),
199 mInverseViewProjection(Matrix::IDENTITY),
200 mFinalProjection(Matrix::IDENTITY)
202 // set a flag the node to say this is a camera
206 Camera* Camera::New()
208 return new(gCameraMemoryPool.AllocateRawThreadSafe()) Camera();
211 Camera::~Camera() = default;
213 void Camera::operator delete(void* ptr)
215 gCameraMemoryPool.FreeThreadSafe(static_cast<Camera*>(ptr));
218 void Camera::SetType(Dali::Camera::Type type)
223 void Camera::SetProjectionMode(Dali::Camera::ProjectionMode mode)
225 mProjectionMode = mode;
226 mUpdateProjectionFlag = UPDATE_COUNT;
229 void Camera::SetProjectionDirection(Dali::DevelCameraActor::ProjectionDirection direction)
231 mProjectionDirection = direction;
232 mUpdateProjectionFlag = UPDATE_COUNT;
235 void Camera::SetInvertYAxis(bool invertYAxis)
237 mInvertYAxis = invertYAxis;
238 mUpdateProjectionFlag = UPDATE_COUNT;
241 void Camera::BakeFieldOfView(BufferIndex updateBufferIndex, float fieldOfView)
243 mFieldOfView.Bake(updateBufferIndex, fieldOfView);
244 mUpdateProjectionFlag = UPDATE_COUNT;
247 void Camera::BakeOrthographicSize(BufferIndex updateBufferIndex, float orthographicSize)
249 mOrthographicSize.Bake(updateBufferIndex, orthographicSize);
250 mUpdateProjectionFlag = UPDATE_COUNT;
253 void Camera::BakeAspectRatio(BufferIndex updateBufferIndex, float aspectRatio)
255 mAspectRatio.Bake(updateBufferIndex, aspectRatio);
256 mUpdateProjectionFlag = UPDATE_COUNT;
259 void Camera::SetNearClippingPlane(float nearClippingPlane)
261 mNearClippingPlane = nearClippingPlane;
262 mUpdateProjectionFlag = UPDATE_COUNT;
265 void Camera::SetFarClippingPlane(float farClippingPlane)
267 mFarClippingPlane = farClippingPlane;
268 mUpdateProjectionFlag = UPDATE_COUNT;
271 void Camera::SetTargetPosition(const Vector3& targetPosition)
273 mTargetPosition = targetPosition;
274 mUpdateViewFlag = UPDATE_COUNT;
277 void VectorReflectedByPlane(Vector4& out, Vector4& in, Vector4& plane)
279 float d = float(2.0) * plane.Dot(in);
280 out.x = static_cast<float>(in.x - plane.x * d);
281 out.y = static_cast<float>(in.y - plane.y * d);
282 out.z = static_cast<float>(in.z - plane.z * d);
283 out.w = static_cast<float>(in.w - plane.w * d);
286 void Camera::AdjustNearPlaneForPerspective(Matrix& perspective, const Vector4& clipPlane)
289 float* v = perspective.AsFloat();
291 q.x = (Sign(clipPlane.x) + v[8]) / v[0];
292 q.y = (Sign(clipPlane.y) + v[9]) / v[5];
294 q.w = (1.0f + v[10]) / v[14];
296 // Calculate the scaled plane vector
297 Vector4 c = clipPlane * (REFLECTION_NORMALIZED_DEVICE_COORDINATE_PARAMETER_A / q.Dot(clipPlane));
299 // Replace the third row of the projection v
302 v[10] = c.z + REFLECTION_NORMALIZED_DEVICE_COORDINATE_PARAMETER_D;
306 void Camera::SetReflectByPlane(const Vector4& plane)
308 float* v = mReflectionMtx.AsFloat();
309 float _2ab = -2.0f * plane.x * plane.y;
310 float _2ac = -2.0f * plane.x * plane.z;
311 float _2bc = -2.0f * plane.y * plane.z;
313 v[0] = 1.0f - 2.0f * plane.x * plane.x;
319 v[5] = 1.0f - 2.0f * plane.y * plane.y;
325 v[10] = 1.0f - 2.0f * plane.z * plane.z;
328 v[12] = -2 * plane.x * plane.w;
329 v[13] = -2 * plane.y * plane.w;
330 v[14] = -2 * plane.z * plane.w;
333 mUseReflection = true;
334 mReflectionPlane = plane;
335 mUpdateViewFlag = UPDATE_COUNT;
338 void Camera::RotateProjection(int rotationAngle)
340 mProjectionRotation = rotationAngle;
341 mUpdateProjectionFlag = UPDATE_COUNT;
344 const Matrix& Camera::GetProjectionMatrix(BufferIndex bufferIndex) const
346 return mProjectionMatrix[bufferIndex];
349 const Matrix& Camera::GetViewMatrix(BufferIndex bufferIndex) const
351 return mViewMatrix[bufferIndex];
354 const Matrix& Camera::GetInverseViewProjectionMatrix(BufferIndex bufferIndex) const
356 return mInverseViewProjection[bufferIndex];
359 const Matrix& Camera::GetFinalProjectionMatrix(BufferIndex bufferIndex) const
361 return mFinalProjection[bufferIndex];
364 const PropertyBase* Camera::GetFieldOfView() const
366 return &mFieldOfView;
369 const PropertyBase* Camera::GetOrthographicSize() const
371 return &mOrthographicSize;
374 const PropertyBase* Camera::GetAspectRatio() const
376 return &mAspectRatio;
379 const PropertyInputImpl* Camera::GetProjectionMatrix() const
381 return &mProjectionMatrix;
384 const PropertyInputImpl* Camera::GetViewMatrix() const
389 void Camera::Update(BufferIndex updateBufferIndex)
391 // if this has changes in world position we need to update camera for next 2 frames
392 if(IsLocalMatrixDirty())
394 mUpdateViewFlag = UPDATE_COUNT;
396 if(GetDirtyFlags() & NodePropertyFlags::VISIBLE)
398 // If the visibility changes, the projection matrix needs to be re-calculated.
399 // It may happen the first time an actor is rendered it's rendered only once and becomes invisible,
400 // in the following update the node will be skipped leaving the projection matrix (double buffered)
401 // with the Identity.
402 mUpdateProjectionFlag = UPDATE_COUNT;
405 // If projection matrix relative properties are animated now, flag change.
406 if(IsProjectionMatrixAnimated())
408 mUpdateProjectionFlag = UPDATE_COUNT;
411 // if either matrix changed, we need to recalculate the inverse matrix for hit testing to work
412 uint32_t viewUpdateCount = UpdateViewMatrix(updateBufferIndex);
413 uint32_t projectionUpdateCount = UpdateProjection(updateBufferIndex);
415 // if model or view matrix changed we need to either recalculate the inverse VP or copy previous
416 if(viewUpdateCount > COPY_PREVIOUS_MATRIX || projectionUpdateCount > COPY_PREVIOUS_MATRIX)
418 // either has actually changed so recalculate
419 MatrixUtils::Multiply(mInverseViewProjection[updateBufferIndex], mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
420 UpdateFrustum(updateBufferIndex);
422 // ignore the error, if the view projection is incorrect (non inversible) then you will have tough times anyways
423 static_cast<void>(mInverseViewProjection[updateBufferIndex].Invert());
425 else if(viewUpdateCount == COPY_PREVIOUS_MATRIX || projectionUpdateCount == COPY_PREVIOUS_MATRIX)
427 // neither has actually changed, but we might copied previous frames value so need to
428 // copy the previous inverse and frustum as well
429 mInverseViewProjection[updateBufferIndex] = mInverseViewProjection[updateBufferIndex ? 0 : 1];
430 mFrustum[updateBufferIndex] = mFrustum[updateBufferIndex ? 0 : 1];
434 bool Camera::ViewMatrixUpdated() const
436 return 0u != mUpdateViewFlag;
439 bool Camera::IsProjectionMatrixAnimated() const
441 return !mFieldOfView.IsClean() ||
442 !mOrthographicSize.IsClean() ||
443 !mAspectRatio.IsClean();
446 uint32_t Camera::UpdateViewMatrix(BufferIndex updateBufferIndex)
448 uint32_t retval(mUpdateViewFlag);
449 if(0u != mUpdateViewFlag)
451 if(COPY_PREVIOUS_MATRIX == mUpdateViewFlag)
453 // The projection matrix was updated in the previous frame; copy it
454 mViewMatrix.CopyPrevious(updateBufferIndex);
456 else // UPDATE_COUNT == mUpdateViewFlag
460 // camera orientation taken from node - i.e. look in abitrary, unconstrained direction
461 case Dali::Camera::FREE_LOOK:
463 Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
464 viewMatrix = GetWorldMatrix(updateBufferIndex);
468 const Matrix& owningNodeMatrix(GetWorldMatrix(updateBufferIndex));
469 Vector3 position{}, scale{};
470 Quaternion orientation{};
471 owningNodeMatrix.GetTransformComponents(position, orientation, scale);
472 mReflectionEye = position;
473 mUseReflectionClip = true;
475 Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
476 Matrix oldViewMatrix(viewMatrix);
477 MatrixUtils::Multiply(viewMatrix, oldViewMatrix, mReflectionMtx);
481 mViewMatrix.SetDirty(updateBufferIndex);
485 // camera orientation constrained to look at a target
486 case Dali::Camera::LOOK_AT_TARGET:
488 const Matrix& owningNodeMatrix(GetWorldMatrix(updateBufferIndex));
489 Vector3 position, scale;
490 Quaternion orientation;
491 owningNodeMatrix.GetTransformComponents(position, orientation, scale);
492 Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
496 Vector3 up = orientation.Rotate(Vector3::YAXIS);
497 Vector4 position4 = Vector4(position);
498 Vector4 target4 = Vector4(mTargetPosition);
499 Vector4 up4 = Vector4(up);
503 Vector3 positionNew3;
504 Vector3 targetNewVector3;
508 VectorReflectedByPlane(positionNew, position4, mReflectionPlane);
509 VectorReflectedByPlane(targetNew, target4, mReflectionPlane);
510 VectorReflectedByPlane(upNew, up4, mReflectionPlane);
512 positionNew3 = Vector3(positionNew);
513 targetNewVector3 = Vector3(targetNew);
514 upNew3 = Vector3(upNew);
515 LookAt(viewMatrix, positionNew3, targetNewVector3, upNew3);
517 Matrix oldViewMatrix(viewMatrix);
519 tmp.SetIdentityAndScale(Vector3(-1.0, 1.0, 1.0));
520 MatrixUtils::Multiply(viewMatrix, oldViewMatrix, tmp);
522 mReflectionEye = positionNew;
523 mUseReflectionClip = true;
527 LookAt(viewMatrix, position, mTargetPosition, orientation.Rotate(Vector3::YAXIS));
529 mViewMatrix.SetDirty(updateBufferIndex);
539 void Camera::UpdateFrustum(BufferIndex updateBufferIndex, bool normalize)
541 // Extract the clip matrix planes
543 MatrixUtils::Multiply(clipMatrix, mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
545 const float* cm = clipMatrix.AsFloat();
546 FrustumPlanes& planes = mFrustum[updateBufferIndex];
549 planes.mPlanes[0].mNormal.x = cm[3] + cm[0]; // column 4 + column 1
550 planes.mPlanes[0].mNormal.y = cm[7] + cm[4];
551 planes.mPlanes[0].mNormal.z = cm[11] + cm[8];
552 planes.mPlanes[0].mDistance = cm[15] + cm[12];
555 planes.mPlanes[1].mNormal.x = cm[3] - cm[0]; // column 4 - column 1
556 planes.mPlanes[1].mNormal.y = cm[7] - cm[4];
557 planes.mPlanes[1].mNormal.z = cm[11] - cm[8];
558 planes.mPlanes[1].mDistance = cm[15] - cm[12];
561 planes.mPlanes[2].mNormal.x = cm[3] + cm[1]; // column 4 + column 2
562 planes.mPlanes[2].mNormal.y = cm[7] + cm[5];
563 planes.mPlanes[2].mNormal.z = cm[11] + cm[9];
564 planes.mPlanes[2].mDistance = cm[15] + cm[13];
567 planes.mPlanes[3].mNormal.x = cm[3] - cm[1]; // column 4 - column 2
568 planes.mPlanes[3].mNormal.y = cm[7] - cm[5];
569 planes.mPlanes[3].mNormal.z = cm[11] - cm[9];
570 planes.mPlanes[3].mDistance = cm[15] - cm[13];
573 planes.mPlanes[4].mNormal.x = cm[3] + cm[2]; // column 4 + column 3
574 planes.mPlanes[4].mNormal.y = cm[7] + cm[6];
575 planes.mPlanes[4].mNormal.z = cm[11] + cm[10];
576 planes.mPlanes[4].mDistance = cm[15] + cm[14];
579 planes.mPlanes[5].mNormal.x = cm[3] - cm[2]; // column 4 - column 3
580 planes.mPlanes[5].mNormal.y = cm[7] - cm[6];
581 planes.mPlanes[5].mNormal.z = cm[11] - cm[10];
582 planes.mPlanes[5].mDistance = cm[15] - cm[14];
586 for(uint32_t i = 0; i < 6; ++i)
588 // Normalize planes to ensure correct bounding distance checking
589 Plane& plane = planes.mPlanes[i];
590 float l = 1.0f / plane.mNormal.Length();
592 plane.mDistance *= l;
594 planes.mSign[i] = Vector3(Sign(plane.mNormal.x), Sign(plane.mNormal.y), Sign(plane.mNormal.z));
599 for(uint32_t i = 0; i < 6; ++i)
601 planes.mSign[i] = Vector3(Sign(planes.mPlanes[i].mNormal.x), Sign(planes.mPlanes[i].mNormal.y), Sign(planes.mPlanes[i].mNormal.z));
604 mFrustum[updateBufferIndex ? 0 : 1] = planes;
607 bool Camera::CheckSphereInFrustum(BufferIndex bufferIndex, const Vector3& origin, float radius) const
609 const FrustumPlanes& planes = mFrustum[bufferIndex];
610 for(uint32_t i = 0; i < 6; ++i)
612 if((planes.mPlanes[i].mDistance + planes.mPlanes[i].mNormal.Dot(origin)) < -radius)
620 bool Camera::CheckAABBInFrustum(BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents) const
622 const FrustumPlanes& planes = mFrustum[bufferIndex];
623 for(uint32_t i = 0; i < 6; ++i)
625 if(planes.mPlanes[i].mNormal.Dot(origin + (halfExtents * planes.mSign[i])) > -(planes.mPlanes[i].mDistance))
634 Dali::Rect<int32_t> Camera::GetOrthographicClippingBox(BufferIndex bufferIndex) const
636 const float orthographicSize = mOrthographicSize[bufferIndex];
637 const float aspect = mAspectRatio[bufferIndex];
639 const float halfWidth = mProjectionDirection == DevelCameraActor::ProjectionDirection::VERTICAL ? orthographicSize * aspect : orthographicSize;
640 const float halfHeight = mProjectionDirection == DevelCameraActor::ProjectionDirection::VERTICAL ? orthographicSize : orthographicSize / aspect;
642 return Dali::Rect<int32_t>(-halfWidth, -halfHeight, halfWidth * 2.0f, halfHeight * 2.0f);
645 uint32_t Camera::UpdateProjection(BufferIndex updateBufferIndex)
647 uint32_t retval(mUpdateProjectionFlag);
648 // Early-exit if no update required
649 if(0u != mUpdateProjectionFlag)
651 Matrix& finalProjection = mFinalProjection[updateBufferIndex];
652 finalProjection.SetIdentity();
654 if(COPY_PREVIOUS_MATRIX == mUpdateProjectionFlag)
656 // The projection matrix was updated in the previous frame; copy it
657 mProjectionMatrix.CopyPrevious(updateBufferIndex);
659 finalProjection = mFinalProjection[updateBufferIndex ? 0 : 1];
661 else // UPDATE_COUNT == mUpdateProjectionFlag
663 switch(mProjectionMode)
665 case Dali::Camera::PERSPECTIVE_PROJECTION:
667 Matrix& projectionMatrix = mProjectionMatrix.Get(updateBufferIndex);
668 Perspective(projectionMatrix,
669 mProjectionDirection,
670 mFieldOfView[updateBufferIndex],
671 mAspectRatio[updateBufferIndex],
676 //need to apply custom clipping plane
677 if(mUseReflectionClip)
679 Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
680 Matrix viewInv = viewMatrix;
684 Dali::Vector4 adjReflectPlane = mReflectionPlane;
685 float d = mReflectionPlane.Dot(mReflectionEye);
688 adjReflectPlane.w = -adjReflectPlane.w;
691 Vector4 customClipping = viewInv * adjReflectPlane;
692 AdjustNearPlaneForPerspective(projectionMatrix, customClipping);
697 float* vZ = matZ.AsFloat();
699 MatrixUtils::Multiply(projectionMatrix, projectionMatrix, matZ);
703 case Dali::Camera::ORTHOGRAPHIC_PROJECTION:
705 Matrix& projectionMatrix = mProjectionMatrix.Get(updateBufferIndex);
706 Orthographic(projectionMatrix,
707 mProjectionDirection,
708 mOrthographicSize[updateBufferIndex],
709 mAspectRatio[updateBufferIndex],
717 mProjectionMatrix.SetDirty(updateBufferIndex);
719 Quaternion rotationAngle;
720 switch(mProjectionRotation)
724 rotationAngle = Quaternion(Dali::ANGLE_90, Vector3::ZAXIS);
729 rotationAngle = Quaternion(Dali::ANGLE_180, Vector3::ZAXIS);
734 rotationAngle = Quaternion(Dali::ANGLE_270, Vector3::ZAXIS);
738 rotationAngle = Quaternion(Dali::ANGLE_0, Vector3::ZAXIS);
743 rotation.SetIdentity();
744 rotation.SetTransformComponents(Vector3(1.0f, 1.0f, 1.0f), rotationAngle, Vector3(0.0f, 0.0f, 0.0f));
746 MatrixUtils::Multiply(finalProjection, mProjectionMatrix.Get(updateBufferIndex), rotation);
748 --mUpdateProjectionFlag;
753 } // namespace SceneGraph
755 } // namespace Internal