DALi Version 2.2.11
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / camera-parameters.cpp
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17 #include "dali-scene3d/public-api/loader/camera-parameters.h"
18 #include "dali-scene3d/public-api/loader/utils.h"
19 #include "dali/devel-api/actors/camera-actor-devel.h"
20 #include "dali/integration-api/debug.h"
21 #include "dali/public-api/actors/camera-actor.h"
22 #include "dali/public-api/math/quaternion.h"
23
24 namespace Dali
25 {
26 namespace Scene3D
27 {
28 namespace Loader
29 {
30 namespace
31 {
32 /**
33  * @brief Creates a perspective matrix.
34  *
35  * @param[out] result The perspective matrix.
36  * @param[in] left The coordinate for the left vertical clipping plane.
37  * @param[in] right The coordinate for the right vertical clipping plane.
38  * @param[in] bottom The coordinate for the bottom horizontal clipping plane.
39  * @param[in] top The coordinate for the top horizontal clipping plane.
40  * @param[in] near The distance to the near depth clipping plane.
41  * @param[in] far The distance to the far depth clipping plane.
42  * @param[in] invertYAxis Whether to invert the 'Y' axis.
43  */
44 void Frustum(Matrix& result, float left, float right, float bottom, float top, float nearPlane, float farPlane, bool invertYAxis)
45 {
46   float deltaZ = farPlane - nearPlane;
47   if((nearPlane <= 0.0f) || (farPlane <= 0.0f) || Equals(right, left) || Equals(bottom, top) || (deltaZ <= 0.0f))
48   {
49     DALI_LOG_ERROR("Invalid parameters passed into Frustum!\n");
50     DALI_ASSERT_DEBUG("Invalid parameters passed into Frustum!");
51     return;
52   }
53
54   float deltaX = right - left;
55   float deltaY = invertYAxis ? bottom - top : top - bottom;
56
57   result.SetIdentity();
58
59   float* m = result.AsFloat();
60   m[0]     = -2.0f * nearPlane / deltaX;
61   m[1] = m[2] = m[3] = 0.0f;
62
63   m[5] = -2.0f * nearPlane / deltaY;
64   m[4] = m[6] = m[7] = 0.0f;
65
66   m[8]  = (right + left) / deltaX;
67   m[9]  = (top + bottom) / deltaY;
68   m[10] = (nearPlane + farPlane) / deltaZ;
69   m[11] = 1.0f;
70
71   m[14] = -2.0f * nearPlane * farPlane / deltaZ;
72   m[12] = m[13] = m[15] = 0.0f;
73 }
74
75 /**
76  * @brief Creates a perspective projection matrix.
77  *
78  * It calls Frustum()
79  *
80  * @param[out] result The perspective projection matrix.
81  * @param[in] fovy The vertical field of view.
82  * @param[in] aspect The aspect ratio.
83  * @param[in] nearPlane The distance to the near depth clipping plane.
84  * @param[in] farPlane The distance to the far depth clipping plane.
85  * @param[in] invertYAxis Whether to invert the 'Y' axis.
86  */
87 void Perspective(Matrix& result, float fovy, float aspect, float nearPlane, float farPlane, bool invertYAxis)
88 {
89   float frustumH = tanf(fovy * 0.5f) * nearPlane;
90   float frustumW = frustumH * aspect;
91
92   Frustum(result, -frustumW, frustumW, -frustumH, frustumH, nearPlane, farPlane, invertYAxis);
93 }
94
95 /**
96 * @brief Creates an orthographic projection matrix.
97 *
98 * @param[out] result The orthographic projection matrix.
99 * @param[in] left The coordinate for the left vertical clipping plane.
100 * @param[in] right The coordinate for the right vertical clipping plane.
101 * @param[in] bottom The coordinate for the bottom horizontal clipping plane.
102 * @param[in] top The coordinate for the top horizontal clipping plane.
103 * @param[in] nearPlane The distance to the near depth clipping plane.
104 * @param[in] farPlane The distance to the far depth clipping plane.
105 * @param[in] invertYAxis Whether to invert the 'Y' axis.
106 */
107 void Orthographic(Matrix& result, float left, float right, float bottom, float top, float nearPlane, float farPlane, bool invertYAxis)
108 {
109   if(Equals(right, left) || Equals(top, bottom) || Equals(farPlane, nearPlane))
110   {
111     DALI_LOG_ERROR("Cannot create orthographic projection matrix with a zero dimension.\n");
112     DALI_ASSERT_DEBUG("Cannot create orthographic projection matrix with a zero dimension.");
113     return;
114   }
115
116   float deltaX = right - left;
117   float deltaY = invertYAxis ? bottom - top : top - bottom;
118   float deltaZ = farPlane - nearPlane;
119
120   float* m = result.AsFloat();
121   m[0]     = -2.0f / deltaX;
122   m[1]     = 0.0f;
123   m[2]     = 0.0f;
124   m[3]     = 0.0f;
125
126   m[4] = 0.0f;
127   m[5] = -2.0f / deltaY;
128   m[6] = 0.0f;
129   m[7] = 0.0f;
130
131   m[8]  = 0.0f;
132   m[9]  = 0.0f;
133   m[10] = 2.0f / deltaZ;
134   m[11] = 0.0f;
135   m[12] = -(right + left) / deltaX;
136   m[13] = -(top + bottom) / deltaY;
137   m[14] = -(nearPlane + farPlane) / deltaZ;
138   m[15] = 1.0f;
139 }
140
141 } // namespace
142
143 ViewProjection CameraParameters::GetViewProjection() const
144 {
145   ViewProjection viewProjection;
146   // The projection matrix.
147   if(isPerspective)
148   {
149     Perspective(viewProjection.GetProjection(),
150                 Radian(Degree(yFov)),
151                 1.f,
152                 zNear,
153                 zFar,
154                 true);
155   }
156   else
157   {
158     Orthographic(viewProjection.GetProjection(),
159                  -orthographicSize * aspectRatio,
160                  orthographicSize * aspectRatio,
161                  orthographicSize,
162                  -orthographicSize,
163                  zNear,
164                  zFar,
165                  true);
166   }
167
168   // The view matrix.
169   const Quaternion viewQuaternion(ANGLE_180, Vector3::YAXIS);
170   Vector3          translation;
171   Quaternion       cameraOrientation;
172   Vector3          scale;
173   matrix.GetTransformComponents(translation, cameraOrientation, scale);
174   cameraOrientation *= viewQuaternion;
175
176   viewProjection.GetView().SetInverseTransformComponents(scale,
177                                                          cameraOrientation,
178                                                          translation);
179
180   viewProjection.Update();
181   return viewProjection;
182 }
183
184 void CameraParameters::CalculateTransformComponents(Vector3& position, Quaternion& orientation, Vector3& scale) const
185 {
186   matrix.GetTransformComponents(position, orientation, scale);
187
188   // The CameraActor is expected to look down the negative Z axis, towards the scene.
189   // Here we emulate the default direction of the camera in DALi.
190   Quaternion viewQuaternion(ANGLE_180, Vector3::YAXIS);
191   orientation *= viewQuaternion;
192 }
193
194 void CameraParameters::ConfigureCamera(CameraActor& camera) const
195 {
196   SetActorCentered(camera);
197
198   if(isPerspective)
199   {
200     camera.SetProjectionMode(Camera::PERSPECTIVE_PROJECTION);
201     camera.SetNearClippingPlane(zNear);
202     camera.SetFarClippingPlane(zFar);
203     camera.SetFieldOfView(Radian(Degree(yFov)));
204   }
205   else
206   {
207     camera.SetProjectionMode(Camera::ORTHOGRAPHIC_PROJECTION);
208     camera.SetNearClippingPlane(zNear);
209     camera.SetFarClippingPlane(zFar);
210     camera.SetAspectRatio(aspectRatio);
211     camera.SetProperty(Dali::DevelCameraActor::Property::ORTHOGRAPHIC_SIZE, orthographicSize);
212   }
213
214   // model
215   Vector3    camTranslation;
216   Vector3    camScale;
217   Quaternion camOrientation;
218   CalculateTransformComponents(camTranslation, camOrientation, camScale);
219
220   camera.SetInvertYAxis(true);
221   camera.SetProperty(Actor::Property::POSITION, camTranslation);
222   camera.SetProperty(Actor::Property::ORIENTATION, camOrientation);
223   camera.SetProperty(Actor::Property::SCALE, camScale);
224 }
225
226 } // namespace Loader
227 } // namespace Scene3D
228 } // namespace Dali