2 // Open Service Platform
3 // Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
9 // http://www.apache.org/licenses/LICENSE-2.0/
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
19 * @file FUi_Matrix3Df.h
20 * @brief Header file of _Matrix3Df class
22 * This file contains declarations _Matrix3Df class.
27 #include "FUi_Matrix3Df.h"
29 #define PI 3.141592653f
34 float identityTransform[4][4] =
36 { 1.0f, 0.0f, 0.0f, 0.0f },
37 { 0.0f, 1.0f, 0.0f, 0.0f },
38 { 0.0f, 0.0f, 1.0f, 0.0f },
39 { 0.0f, 0.0f, 0.0f, 1.0f }
44 namespace Tizen { namespace Ui { namespace Animations
47 _Matrix3Df::_Matrix3Df(void)
52 _Matrix3Df::_Matrix3Df(const float* pValues)
54 memcpy(__m, pValues, sizeof(__m));
55 __complexity = GenericMatrix;
59 _Matrix3Df::Assign(const _Matrix3Df& rhs)
61 memcpy(__m, rhs.__m, sizeof(__m));
62 __complexity = rhs.__complexity;
68 _Matrix3Df::operator =(const _Matrix3Df& rhs)
77 _Matrix3Df::operator ==(const _Matrix3Df& rhs) const
79 return (__m[0][0] == rhs.__m[0][0] &&
80 __m[0][1] == rhs.__m[0][1] &&
81 __m[0][2] == rhs.__m[0][2] &&
82 __m[0][3] == rhs.__m[0][3] &&
83 __m[1][0] == rhs.__m[1][0] &&
84 __m[1][1] == rhs.__m[1][1] &&
85 __m[1][2] == rhs.__m[1][2] &&
86 __m[1][3] == rhs.__m[1][3] &&
87 __m[2][0] == rhs.__m[2][0] &&
88 __m[2][1] == rhs.__m[2][1] &&
89 __m[2][2] == rhs.__m[2][2] &&
90 __m[2][3] == rhs.__m[2][3] &&
91 __m[3][0] == rhs.__m[3][0] &&
92 __m[3][1] == rhs.__m[3][1] &&
93 __m[3][2] == rhs.__m[3][2] &&
94 __m[3][3] == rhs.__m[3][3]);
98 _Matrix3Df::operator !=(const _Matrix3Df& rhs) const
100 return (__m[0][0] != rhs.__m[0][0] ||
101 __m[0][1] != rhs.__m[0][1] ||
102 __m[0][2] != rhs.__m[0][2] ||
103 __m[0][3] != rhs.__m[0][3] ||
104 __m[1][0] != rhs.__m[1][0] ||
105 __m[1][1] != rhs.__m[1][1] ||
106 __m[1][2] != rhs.__m[1][2] ||
107 __m[1][3] != rhs.__m[1][3] ||
108 __m[2][0] != rhs.__m[2][0] ||
109 __m[2][1] != rhs.__m[2][1] ||
110 __m[2][2] != rhs.__m[2][2] ||
111 __m[2][3] != rhs.__m[2][3] ||
112 __m[3][0] != rhs.__m[3][0] ||
113 __m[3][1] != rhs.__m[3][1] ||
114 __m[3][2] != rhs.__m[3][2] ||
115 __m[3][3] != rhs.__m[3][3]);
119 _Matrix3Df::Optimize(void)
121 if (__m[3][3] != 1.0f)
123 __complexity = GenericMatrix;
127 if (__m[1][0] != 0.0f || __m[2][0] != 0.0f || __m[2][1] != 0.0f)
129 __complexity = GenericMatrix;
133 if (__m[0][1] != 0.0f || __m[0][2] != 0.0f || __m[0][3] != 0.0f ||
134 __m[1][2] != 0.0f || __m[1][3] != 0.0f || __m[2][3] != 0.0f)
136 __complexity = GenericMatrix;
140 bool isTranslate = (__m[3][0] != 0.0f || __m[3][1] != 0.0f || __m[3][2] != 0.0f);
141 bool isDiagonal = (__m[0][0] == 1.0f && __m[1][1] == 1.0f && __m[2][2] == 1.0f);
143 if (isTranslate && isDiagonal)
144 __complexity = TranslationMatrix;
145 else if (isTranslate)
146 __complexity = GenericMatrix;
148 __complexity = IdentityMatrix;
150 __complexity = ScaleMatrix;
154 _Matrix3Df::operator *=(const _Matrix3Df& rhs)
156 if (__complexity == IdentityMatrix)
160 else if (rhs.__complexity == IdentityMatrix)
173 _Matrix3Df::MultiplyMatrix(const _Matrix3Df& matrix)
175 *this = *this * matrix;
181 _Matrix3Df::Concatenate(const _Matrix3Df* matrix)
183 return Concatenate(*matrix);
187 _Matrix3Df::Concatenate(const _Matrix3Df& matrix)
189 *this = matrix * *this;
195 _Matrix3Df::GetDeterminant(void) const
197 float a0, a1, a2, a3, a4, a5;
198 float b0, b1, b2, b3, b4, b5;
201 a0 = __m[0][0] * __m[1][1] - __m[0][1] * __m[1][0];
202 a1 = __m[0][0] * __m[1][2] - __m[0][2] * __m[1][0];
203 a2 = __m[0][0] * __m[1][3] - __m[0][3] * __m[1][0];
204 a3 = __m[0][1] * __m[1][2] - __m[0][2] * __m[1][1];
205 a4 = __m[0][1] * __m[1][3] - __m[0][3] * __m[1][1];
206 a5 = __m[0][2] * __m[1][3] - __m[0][3] * __m[1][2];
208 b0 = __m[2][0] * __m[3][1] - __m[2][1] * __m[3][0];
209 b1 = __m[2][0] * __m[3][2] - __m[2][2] * __m[3][0];
210 b2 = __m[2][0] * __m[3][3] - __m[2][3] * __m[3][0];
211 b3 = __m[2][1] * __m[3][2] - __m[2][2] * __m[3][1];
212 b4 = __m[2][1] * __m[3][3] - __m[2][3] * __m[3][1];
213 b5 = __m[2][2] * __m[3][3] - __m[2][3] * __m[3][2];
215 det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
221 _Matrix3Df::IsInvertible(void) const
223 if (__complexity == IdentityMatrix)
226 if (__complexity == TranslationMatrix)
229 return !_FloatHardCompare(GetDeterminant(), 0.0f);
233 _Matrix3Df::Invert(void)
236 // Optimize using NEON
237 float a0, a1, a2, a3, a4, a5;
238 float b0, b1, b2, b3, b4, b5;
241 if (__complexity == IdentityMatrix)
244 if (__complexity == TranslationMatrix)
246 __m[3][0] = -__m[3][0];
247 __m[3][1] = -__m[3][1];
248 __m[3][2] = -__m[3][2];
253 a0 = __m[0][0] * __m[1][1] - __m[0][1] * __m[1][0];
254 a1 = __m[0][0] * __m[1][2] - __m[0][2] * __m[1][0];
255 a2 = __m[0][0] * __m[1][3] - __m[0][3] * __m[1][0];
256 a3 = __m[0][1] * __m[1][2] - __m[0][2] * __m[1][1];
257 a4 = __m[0][1] * __m[1][3] - __m[0][3] * __m[1][1];
258 a5 = __m[0][2] * __m[1][3] - __m[0][3] * __m[1][2];
260 b0 = __m[2][0] * __m[3][1] - __m[2][1] * __m[3][0];
261 b1 = __m[2][0] * __m[3][2] - __m[2][2] * __m[3][0];
262 b2 = __m[2][0] * __m[3][3] - __m[2][3] * __m[3][0];
263 b3 = __m[2][1] * __m[3][2] - __m[2][2] * __m[3][1];
264 b4 = __m[2][1] * __m[3][3] - __m[2][3] * __m[3][1];
265 b5 = __m[2][2] * __m[3][3] - __m[2][3] * __m[3][2];
267 det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
268 if (_FloatHardCompare(det, 0.0f))
272 float inverse_m[4][4];
274 inverse_m[0][0] = +__m[1][1] * b5 - __m[1][2] * b4 + __m[1][3] * b3;
275 inverse_m[1][0] = -__m[1][0] * b5 + __m[1][2] * b2 + __m[1][3] * b1;
276 inverse_m[2][0] = +__m[1][0] * b4 - __m[1][1] * b2 + __m[1][3] * b0;
277 inverse_m[3][0] = -__m[1][0] * b3 + __m[1][1] * b1 - __m[1][2] * b0;
278 inverse_m[0][1] = -__m[0][1] * b5 + __m[0][2] * b4 - __m[0][3] * b3;
279 inverse_m[1][1] = +__m[0][0] * b5 - __m[0][2] * b2 + __m[0][3] * b1;
280 inverse_m[2][1] = -__m[0][0] * b4 + __m[0][1] * b2 - __m[0][3] * b0;
281 inverse_m[3][1] = +__m[0][0] * b3 - __m[0][1] * b1 + __m[0][2] * b0;
282 inverse_m[0][2] = +__m[3][1] * a5 - __m[3][2] * a4 + __m[3][3] * a3;
283 inverse_m[1][2] = -__m[3][0] * a5 + __m[3][2] * a2 - __m[3][3] * a1;
284 inverse_m[2][2] = +__m[3][0] * a4 - __m[3][1] * a2 + __m[3][3] * a0;
285 inverse_m[3][2] = -__m[3][0] * a3 + __m[3][1] * a1 - __m[3][2] * a0;
286 inverse_m[0][3] = -__m[2][1] * a5 + __m[2][2] * a4 - __m[2][3] * a3;
287 inverse_m[1][3] = +__m[2][0] * a5 - __m[2][2] * a2 + __m[2][3] * a1;
288 inverse_m[2][3] = -__m[2][0] * a4 + __m[2][1] * a2 - __m[2][3] * a0;
289 inverse_m[3][3] = +__m[2][0] * a3 - __m[2][1] * a1 + __m[2][2] * a0;
291 for (int i = 0; i < 4; i++)
293 for (int j = 0; j < 4; j++)
294 inverse_m[j][i] /= det;
297 memcpy(__m, inverse_m, sizeof(__m));
298 __complexity = GenericMatrix;
304 _Matrix3Df::LoadIdentity(void)
306 memcpy(__m, identityTransform, sizeof(__m));
307 __complexity = IdentityMatrix;
311 _Matrix3Df::Transpose(void)
316 for (i = 0; i < 4; i++)
318 for (j = i + 1; j < 4; j++)
321 __m[i][j] = __m[j][i];
326 __complexity = GenericMatrix;
330 _Matrix3Df::Translate(float tx, float ty, float tz)
332 if (__complexity == IdentityMatrix)
337 __complexity = TranslationMatrix;
339 else if (__complexity == TranslationMatrix)
345 else if (__complexity == ScaleMatrix)
347 __m[3][0] = __m[0][0] * tx;
348 __m[3][1] = __m[1][1] * ty;
349 __m[3][2] = __m[1][2] * tz;
350 __complexity = GenericMatrix;
355 __m[3][0] += (__m[0][0] * tx + __m[1][0] * ty + __m[2][0] * tz);
356 __m[3][1] += (__m[0][1] * tx + __m[1][1] * ty + __m[2][1] * tz);
357 __m[3][2] += (__m[0][2] * tx + __m[1][2] * ty + __m[2][2] * tz);
358 __m[3][3] += (__m[0][3] * tx + __m[1][3] * ty + __m[2][3] * tz);
359 __complexity = GenericMatrix;
363 f4Dest = vld1q_f32(m_mtx.m[3]);
364 f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[0]), tx);
365 f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[1]), ty);
366 f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[2]), tz);
368 vst1q_f32(m_mtx.m[3], f4Dest);
374 _Matrix3Df::Scale(float sx, float sy, float sz)
401 if (__complexity == IdentityMatrix)
402 __complexity = ScaleMatrix;
404 __complexity = GenericMatrix;
407 vst1q_f32(m_mtx.m[0], vmulq_n_f32(vld1q_f32(m_mtx.m[0]), sx));
408 vst1q_f32(m_mtx.m[1], vmulq_n_f32(vld1q_f32(m_mtx.m[1]), sy));
409 vst1q_f32(m_mtx.m[2], vmulq_n_f32(vld1q_f32(m_mtx.m[2]), sz));
414 _Matrix3Df::Shear(float xy, float yz, float zx, float yx, float zy, float xz)
416 _Matrix3Df ShearMatrix;
418 // refer: http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q43
420 if (xy == 0.0f && yz == 0.0f && zx == 0.0f &&
421 yx == 0.0f && zy == 0.0f && xz == 0.0f)
425 memcpy(ShearMatrix.__m, identityTransform, sizeof(ShearMatrix.__m));
427 ShearMatrix.__m[0][1] = xy;
428 ShearMatrix.__m[0][2] = xz;
430 ShearMatrix.__m[1][0] = yx;
431 ShearMatrix.__m[1][2] = yz;
433 ShearMatrix.__m[2][0] = zx;
434 ShearMatrix.__m[2][1] = zy;
436 ShearMatrix.__complexity = GenericMatrix;
438 *this = *this * ShearMatrix;
442 _Matrix3Df::Rotate(float angle, float x, float y, float z)
448 // Rotation using quaternion
450 angle = angle * M_PI / 180.0f;
453 float sinA = sinf(angle);
454 float cosA = cosf(angle);
455 float sinA2 = sinA * sinA;
458 float length = sqrtf(x * x + y * y + z * z);
461 // bad vector, just use something reasonable
470 else if (length != 1.0f)
478 float mat[4][4] = { {0.0f, }, };
480 // optimize case where axis is along major axis
481 if (x == 1.0f && y == 0.0f && z == 0.0f)
487 mat[1][1] = 1.0f - 2.0f * sinA2;
488 mat[1][2] = 2.0f * sinA * cosA;
490 mat[2][1] = -2.0f * sinA * cosA;
491 mat[2][2] = 1.0f - 2.0f * sinA2;
492 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
493 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
496 else if (x == 0.0f && y == 1.0f && z == 0.0f)
498 mat[0][0] = 1.0f - 2.0f * sinA2;
500 mat[0][2] = -2.0f * sinA * cosA;
504 mat[2][0] = 2.0f * sinA * cosA;
506 mat[2][2] = 1.0f - 2.0f * sinA2;
507 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
508 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
511 else if (x == 0.0f && y == 0.0f && z == 1.0f)
513 mat[0][0] = 1.0f - 2.0f * sinA2;
514 mat[0][1] = 2.0f * sinA * cosA;
516 mat[1][0] = -2.0f * sinA * cosA;
517 mat[1][1] = 1.0f - 2.0f * sinA2;
522 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
523 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
532 mat[0][0] = 1.0f - 2.0f * (y2 + z2) * sinA2;
533 mat[0][1] = 2.0f * (x * y * sinA2 + z * sinA * cosA);
534 mat[0][2] = 2.0f * (x * z * sinA2 - y * sinA * cosA);
535 mat[1][0] = 2.0f * (y * x * sinA2 - z * sinA * cosA);
536 mat[1][1] = 1.0f - 2.0f * (z2 + x2) * sinA2;
537 mat[1][2] = 2.0f * (y * z * sinA2 + x * sinA * cosA);
538 mat[2][0] = 2.0f * (z * x * sinA2 + y * sinA * cosA);
539 mat[2][1] = 2.0f * (z * y * sinA2 - x * sinA * cosA);
540 mat[2][2] = 1.0f - 2.0f * (x2 + y2) * sinA2;
541 mat[0][3] = mat[1][3] = mat[2][3] = 0.0f;
542 mat[3][0] = mat[3][1] = mat[3][2] = 0.0f;
546 *this *= _Matrix3Df((const float*)mat);
549 float sinAngle, cosAngle;
555 mag = sqrtf(x * x + y * y + z * z);
556 sinAngle = sinf(angle * PI / 180.0f);
557 cosAngle = cosf(angle * PI / 180.0f);
561 float xx, yy, zz, xy, yz, zx, xs, ys, zs;
577 oneMinusCos = 1.0f - cosAngle;
579 rotMat.__m[0][0] = (oneMinusCos * xx) + cosAngle;
580 rotMat.__m[1][0] = (oneMinusCos * xy) - zs;
581 rotMat.__m[2][0] = (oneMinusCos * zx) + ys;
582 rotMat.__m[3][0] = 0.0f;
584 rotMat.__m[0][1] = (oneMinusCos * xy) + zs;
585 rotMat.__m[1][1] = (oneMinusCos * yy) + cosAngle;
586 rotMat.__m[2][1] = (oneMinusCos * yz) - xs;
587 rotMat.__m[3][1] = 0.0f;
589 rotMat.__m[0][2] = (oneMinusCos * zx) - ys;
590 rotMat.__m[1][2] = (oneMinusCos * yz) + xs;
591 rotMat.__m[2][2] = (oneMinusCos * zz) + cosAngle;
592 rotMat.__m[3][2] = 0.0f;
594 rotMat.__m[0][3] = 0.0f;
595 rotMat.__m[1][3] = 0.0f;
596 rotMat.__m[2][3] = 0.0f;
597 rotMat.__m[3][3] = 1.0f;
599 rotMat.__complexity = GenericMatrix;
601 *this = *this * rotMat;
607 _Matrix3Df::MakeOrthogonal(float left, float right, float bottom, float top, float n, float f)
612 memcpy(mat.__m, identityTransform, sizeof(mat.__m));
620 w = ALMOST_ZERO_FLOAT;
622 h = ALMOST_ZERO_FLOAT;
624 d = ALMOST_ZERO_FLOAT;
626 mat.__m[0][0] = 2.0f / w;
627 mat.__m[1][1] = 2.0f / h;
628 mat.__m[2][2] = -2.0f / d;
630 mat.__m[3][0] = -(right + left) / w;
631 mat.__m[3][1] = -(bottom + top) / h;
632 mat.__m[3][2] = -(n + f) / d;
633 mat.__m[3][3] = 1.0f;
635 mat.__complexity = GenericMatrix;
641 _Matrix3Df::MakeFrustum(float left, float right, float bottom, float top, float nearZ, float farZ)
646 memcpy(mat.__m, identityTransform, sizeof(mat.__m));
654 w = ALMOST_ZERO_FLOAT;
656 h = ALMOST_ZERO_FLOAT;
658 d = ALMOST_ZERO_FLOAT;
660 mat.__m[0][0] = 2.0f * nearZ / w;
661 mat.__m[1][1] = 2.0f * nearZ / h;
662 mat.__m[2][0] = (right + left) / w;
663 mat.__m[2][1] = (top + bottom) / h;
664 mat.__m[2][2] = -(farZ + nearZ) / d;
665 mat.__m[2][3] = -1.0f;
666 mat.__m[3][2] = -2.0f * farZ * nearZ / d;
667 mat.__m[3][3] = 0.0f;
669 mat.__complexity = GenericMatrix;
675 _Matrix3Df::MakePerspective(float fovy, float aspect, float nearZ, float farZ)
677 float frustumW, frustumH;
679 frustumH = tanf(fovy / 360.0f * PI) * nearZ;
680 frustumW = frustumH * aspect;
682 MakeFrustum(-frustumW, frustumW, -frustumH, frustumH, nearZ, farZ);
686 _Matrix3Df::MakeLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)
689 float x[3], y[3], z[3];
692 // Make rotation matrix
694 z[0] = eyeX - centerX;
695 z[1] = eyeY - centerY;
696 z[2] = eyeZ - centerZ;
698 mag = sqrtf(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
701 // mpichler, 19950515
712 // X vector = Y cross Z
713 x[0] = y[1] * z[2] - y[2] * z[1];
714 x[1] = -y[0] * z[2] + y[2] * z[0];
715 x[2] = y[0] * z[1] - y[1] * z[0];
717 // Recompute Y = Z cross X
718 y[0] = z[1] * x[2] - z[2] * x[1];
719 y[1] = -z[0] * x[2] + z[2] * x[0];
720 y[2] = z[0] * x[1] - z[1] * x[0];
722 // mpichler, 19950515
723 // cross product gives area of parallelogram, which is < 1.0 for
724 // non-perpendicular unit-length vectors; so normalize x, y here
725 mag = sqrtf(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
733 mag = sqrtf(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
741 mat.__m[0][0] = x[0];
742 mat.__m[1][0] = x[1];
743 mat.__m[2][0] = x[2];
744 mat.__m[3][0] = 0.0f;
745 mat.__m[0][1] = y[0];
746 mat.__m[1][1] = y[1];
747 mat.__m[2][1] = y[2];
748 mat.__m[3][1] = 0.0f;
749 mat.__m[0][2] = z[0];
750 mat.__m[1][2] = z[1];
751 mat.__m[2][2] = z[2];
752 mat.__m[3][2] = 0.0f;
754 mat.__complexity = GenericMatrix;
758 // Translate Eye to Origin
759 Translate(-eyeX, -eyeY, -eyeZ);
763 _Matrix3Df::MakeTransformAtAnchor(float x, float y, float z)
765 *this = _Matrix3DfTr(x, y, z) * (*this) * _Matrix3DfTr(-x, -y, -z);
771 _Matrix3Df::Normalize(void)
776 if (w == 1.0f || w == 0.0f)
779 for (int i = 0; i < 4; i++)
781 for (int j = 0; j < 4; j++)
785 __complexity = GenericMatrix;
791 _Matrix3Df::Transform(float* pX, float* pY, float* pZ) const
800 if (__complexity == IdentityMatrix)
804 else if (__complexity == TranslationMatrix)
810 else if (__complexity == ScaleMatrix)
818 *pX = (__m[0][0] * x) + (__m[1][0] * y) + (__m[2][0] * z) + (__m[3][0]);
819 *pY = (__m[0][1] * x) + (__m[1][1] * y) + (__m[2][1] * z) + (__m[3][1]);
820 *pZ = (__m[0][2] * x) + (__m[1][2] * y) + (__m[2][2] * z) + (__m[3][2]);
821 w = (__m[0][3] * x) + (__m[1][3] * y) + (__m[2][3] * z) + (__m[3][3]);
823 // TODO: what if w == 0 ????
836 f4Dest = vmulq_n_f32(vld1q_f32(m_mtx.m[0]), *pX);
837 f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[1]), *pY);
838 f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[2]), *pZ);
839 f4Dest = vmlaq_n_f32(f4Dest, vld1q_f32(m_mtx.m[3]), 1.0f);
841 vst1q_f32(pVector, f4Dest);
843 *pX = pVector[0] / pVector[3];
844 *pY = pVector[1] / pVector[3];
845 *pZ = pVector[2] / pVector[3];
850 // Needless to check 4th row ??
853 }}} // Tizen::Ui::Animations