ffdd632b82306a7139e301b7c76609a6727d4510
[platform/core/uifw/dali-core.git] / dali / internal / event / common / projection.cpp
1 /*
2  * Copyright (c) 2018 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
18 // CLASS HEADER
19 #include <dali/internal/event/common/projection.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/math/rect.h>
23 #include <dali/public-api/math/matrix.h>
24 #include <dali/public-api/math/vector4.h>
25 #include <dali/public-api/math/vector2.h>
26 #include <dali/public-api/math/viewport.h>
27 #include <dali/integration-api/debug.h>
28 #include <dali/public-api/math/math-utils.h>
29
30 namespace Dali
31 {
32
33 namespace Internal
34 {
35
36 bool Unproject( const Vector4& windowPos,
37                 const Matrix& inverseMvp,
38                 float viewportWidth,
39                 float viewportHeight,
40                 Vector4& objectPos )
41 {
42   objectPos.x = windowPos.x;
43   objectPos.y = windowPos.y;
44   objectPos.z = windowPos.z;
45   objectPos.w = 1.0f;
46
47   objectPos.x = objectPos.x / viewportWidth;
48   objectPos.y = objectPos.y / viewportHeight;
49
50   objectPos.x = objectPos.x * 2.0f - 1.0f;
51   objectPos.y = objectPos.y * 2.0f - 1.0f;
52   objectPos.z = objectPos.z * 2.0f - 1.0f;
53
54   objectPos = inverseMvp * objectPos;
55
56   // In the case where objectPos.w is exactly zero, the unproject fails
57   if ( EqualsZero( objectPos.w ) )
58   {
59     return false;
60   }
61
62   objectPos.x /= objectPos.w;
63   objectPos.y /= objectPos.w;
64   objectPos.z /= objectPos.w;
65
66   return true;
67 }
68
69 bool UnprojectFull( const Vector4& windowPos,
70                     const Matrix& modelView,
71                     const Matrix& projection,
72                     float viewportWidth,
73                     float viewportHeight,
74                     Vector4& objectPos )
75 {
76   Matrix invertedMvp( false ); // Don't initialize.
77   Matrix::Multiply( invertedMvp, modelView, projection );
78
79   if (invertedMvp.Invert())
80   {
81     return Unproject( windowPos, invertedMvp, viewportWidth, viewportHeight, objectPos );
82   }
83
84   return false;
85 }
86
87 bool XyPlaneIntersect( const Vector4& pointA, const Vector4& pointB, Vector4& intersect )
88 {
89   const Vector4* near = NULL;
90   const Vector4* far = NULL;
91
92   if ( pointA.z > 0.0f && pointB.z < 0.0f )
93   {
94     near = &pointA;
95     far  = &pointB;
96   }
97   else if ( pointB.z > 0.0f && pointA.z < 0.0f )
98   {
99     near = &pointB;
100     far  = &pointA;
101   }
102   else
103   {
104     return false; // ray does not cross xy plane
105   }
106
107   float dist = near->z / (near->z - far->z);
108
109   intersect.x = near->x + (far->x - near->x) * dist;
110   intersect.y = near->y + (far->y - near->y) * dist;
111   intersect.z = 0.0f;
112
113   return true;
114 }
115
116 bool ProjectFull( const Vector4& position,
117                   const Matrix& modelView,
118                   const Matrix& projection,
119                   float viewportX,
120                   float viewportY,
121                   float viewportWidth,
122                   float viewportHeight,
123                   Vector4& windowPos )
124 {
125   bool ok = false;
126
127   Matrix Mvp( false ); // Don't initialize.
128   Matrix::Multiply( Mvp, modelView, projection );
129
130   Vector4 p = Mvp * position;
131
132   Vector2 depthRange(0,1);
133
134   if( !EqualsZero( p.w ) )
135   {
136     float div = 1.0f / p.w;
137
138     windowPos = Vector4( (1 + p.x * div) * viewportWidth  / 2 + viewportX,
139                          (1 - p.y * div) * viewportHeight / 2 + viewportY,
140                          (p.z * div) * (depthRange.y - depthRange.x) + depthRange.x,
141                          div);
142     ok = true;
143   }
144
145   return ok;
146 }
147
148
149 } // namespace Internal
150
151 } // namespace Dali