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