[SRUK] Initial copy from Tizen 2.2 version
[platform/core/uifw/dali-core.git] / dali / public-api / math / vector3.cpp
1 //
2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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 // CLASS HEADER
18 #include <dali/public-api/math/vector3.h>
19 #include <dali/public-api/math/quaternion.h>
20
21 // EXTERNAL INCLUDES
22 #include <math.h>
23
24 // INTERNAL INCLUDES
25 #include <dali/public-api/common/dali-common.h>
26 #include <dali/public-api/math/vector2.h>
27 #include <dali/public-api/math/vector4.h>
28 #include <dali/public-api/math/math-utils.h>
29 #include <dali/internal/render/common/performance-monitor.h>
30
31 namespace Dali
32 {
33 using Internal::PerformanceMonitor;
34
35 const Vector3 Vector3::ONE(1.0f, 1.0f, 1.0f);
36 const Vector3 Vector3::XAXIS(1.0f, 0.0f, 0.0f);
37 const Vector3 Vector3::YAXIS(0.0f, 1.0f, 0.0f);
38 const Vector3 Vector3::ZAXIS(0.0f, 0.0f, 1.0f);
39 const Vector3 Vector3::NEGATIVE_XAXIS(-1.0f, 0.0f, 0.0f);
40 const Vector3 Vector3::NEGATIVE_YAXIS(0.0f, -1.0f, 0.0f);
41 const Vector3 Vector3::NEGATIVE_ZAXIS(0.0f, 0.0f, -1.0f);
42 const Vector3 Vector3::ZERO(0.0f, 0.0f, 0.0f);
43
44 Vector3::Vector3( const Vector2& vec2 )
45 : x(vec2.x),
46   y(vec2.y),
47   z(0.0f)
48 {
49 }
50
51 Vector3::Vector3( const Vector4& vec4 )
52 : x(vec4.x),
53   y(vec4.y),
54   z(vec4.z)
55 {
56 }
57
58 Vector3& Vector3::operator=(const Vector2& rhs)
59 {
60   x = rhs.x;
61   y = rhs.y;
62   z = 0.0f;
63
64   return *this;
65 }
66
67 Vector3& Vector3::operator=(const Vector4& rhs)
68 {
69   x = rhs.x;
70   y = rhs.y;
71   z = rhs.z;
72
73   return *this;
74 }
75
76 Vector3& Vector3::operator*=(const Quaternion& rhs)
77 {
78   // nVidia SDK implementation
79   Vector3 qvec(rhs.mVector.x, rhs.mVector.y, rhs.mVector.z);
80
81   Vector3 uv( (qvec.y * z) - (qvec.z * y),
82               (qvec.z * x) - (qvec.x * z),
83               (qvec.x * y) - (qvec.y * x) );
84
85   Vector3 uuv( (qvec.y * uv.z) - (qvec.z * uv.y),
86                (qvec.z * uv.x) - (qvec.x * uv.z),
87                (qvec.x * uv.y) - (qvec.y * uv.x) );
88
89   uv *= rhs.mVector.w;
90
91   x += (uv.x + uuv.x) * 2.0f;
92   y += (uv.y + uuv.y) * 2.0f;
93   z += (uv.z + uuv.z) * 2.0f;
94
95   return *this;
96 }
97
98 bool Vector3::operator==(const Vector3& rhs) const
99 {
100   if (fabsf(x - rhs.x) > GetRangedEpsilon(x, rhs.x) )
101   {
102     return false;
103   }
104   if (fabsf(y - rhs.y) > GetRangedEpsilon(y, rhs.y) )
105   {
106     return false;
107   }
108   if (fabsf(z - rhs.z) > GetRangedEpsilon(z, rhs.z) )
109   {
110     return false;
111   }
112
113   return true;
114 }
115
116 float Vector3::Dot(const Vector3 &other) const
117 {
118   MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
119
120   return x * other.x + y * other.y + z * other.z;
121 }
122
123 Vector3 Vector3::Cross(const Vector3 &other) const
124 {
125   MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,6);
126
127   return Vector3( (y * other.z) - (z * other.y),
128                   (z * other.x) - (x * other.z),
129                   (x * other.y) - (y * other.x));
130 }
131
132 float Vector3::Length() const
133 {
134   MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
135
136   return sqrtf(x*x + y*y + z*z);
137 }
138
139 float Vector3::LengthSquared() const
140 {
141   MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
142
143   return x*x + y*y + z*z;
144 }
145
146 void Vector3::Normalize()
147 {
148   float length = Length();
149   if( ! EqualsZero(length) )
150   {
151     MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
152
153     const float inverseLength = 1.0f / length;
154     x *= inverseLength;
155     y *= inverseLength;
156     z *= inverseLength;
157   }
158 }
159
160 void Vector3::Clamp( const Vector3& min, const Vector3& max )
161 {
162   Dali::ClampInPlace<float>( x, min.x, max.x );
163   Dali::ClampInPlace<float>( y, min.y, max.y );
164   Dali::ClampInPlace<float>( z, min.z, max.z );
165 }
166
167 std::ostream& operator<< (std::ostream& o, const Vector3& vector)
168 {
169   return o << "[" << vector.x << ", " << vector.y << ", " << vector.z << "]";
170 }
171
172 Vector3 Clamp( const Vector3& v, const float& min, const float& max )
173 {
174   Vector3 result( v );
175   result.Clamp( Vector3( min, min, min ) , Vector3( max, max, max ) );
176
177   return result;
178 }
179
180 Vector3 FitKeepAspectRatio( const Vector3& target, const Vector3& source )
181 {
182   float scale = 0.0f;
183
184   if ( fabsf(source.x) > 0.0f )
185   {
186     scale = target.x / source.x;
187   }
188
189   if ( fabsf(source.y) > 0.0f )
190   {
191     if ( scale > Math::MACHINE_EPSILON_1 )
192     {
193       scale =  std::min( scale, target.y / source.y );
194     }
195     else
196     {
197       scale = target.y / source.y;
198     }
199   }
200
201   if ( fabsf(source.z) > 0.0f )
202   {
203     if ( scale > Math::MACHINE_EPSILON_1 )
204     {
205       scale =  std::min( scale, target.z / source.z );
206     }
207     else
208     {
209       scale = target.z / source.z;
210     }
211   }
212
213   if ( scale < Math::MACHINE_EPSILON_1 )
214   {
215     scale = 1.0f;
216   }
217
218   return Vector3( scale, scale, scale );
219 }
220
221 Vector3 FillKeepAspectRatio( const Vector3& target, const Vector3& source )
222 {
223   float scale = 0.0f;
224
225   if ( fabsf(source.x) > 0.0f )
226   {
227     scale = target.x / source.x;
228   }
229
230   if ( fabsf(source.y) > 0.0f )
231   {
232     if ( scale > Math::MACHINE_EPSILON_1 )
233     {
234       scale =  std::max( scale, target.y / source.y );
235     }
236     else
237     {
238       scale = target.y / source.y;
239     }
240   }
241
242   if ( fabsf(source.z) > 0.0f )
243   {
244     if ( scale > Math::MACHINE_EPSILON_1 )
245     {
246       scale =  std::max( scale, target.z / source.z );
247     }
248     else
249     {
250       scale = target.z / source.z;
251     }
252   }
253
254   if ( scale < Math::MACHINE_EPSILON_1 )
255   {
256     scale = 1.0f;
257   }
258
259   return Vector3( scale, scale, scale );
260 }
261
262 Vector3 FillXYKeepAspectRatio( const Vector3& target, const Vector3& source )
263 {
264   float scale = 0.0f;
265
266   if ( fabsf(source.x) > 0.0f )
267   {
268     scale = target.x / source.x;
269   }
270
271   if ( fabsf(source.y) > 0.0f )
272   {
273     if ( scale > Math::MACHINE_EPSILON_1 )
274     {
275       scale =  std::max( scale, target.y / source.y );
276     }
277     else
278     {
279       scale = target.y / source.y;
280     }
281   }
282
283   if ( scale < Math::MACHINE_EPSILON_1 )
284   {
285     scale = 1.0f;
286   }
287
288   return Vector3( scale, scale, scale );
289 }
290
291 Vector3 ShrinkInsideKeepAspectRatio( const Vector3& target, const Vector3& source )
292 {
293   // calculate source size vs target size to see if we need to shrink
294   float widthScale = 1.0f;
295   if( target.width < source.width )
296   {
297     // not enough width, width needs to shrink
298     widthScale = target.width / source.width;
299   }
300   float heightScale = 1.0f;
301   if( target.height < source.height )
302   {
303     // not enough height, height needs to shrink
304     heightScale = target.height / source.height;
305   }
306   float depthScale = 1.0f;
307   if( target.depth < source.depth )
308   {
309     // not enough depth, depth needs to shrink
310     depthScale = target.depth / source.depth;
311   }
312   // use smaller of the scales
313   float scale = std::min( std::min( widthScale, heightScale ), depthScale );
314
315   // check if we need to scale
316   if( scale < 1.0f )
317   {
318     // scale natural size to fit inside
319     return Vector3( scale, scale, scale );
320   }
321   // there is enough space so use source size
322   return Vector3::ONE;
323 }
324
325 } // namespace Dali