Merge "Combine Internal::ProxyObject & Internal::Object" into tizen
[platform/core/uifw/dali-core.git] / dali / public-api / math / matrix3.cpp
1 /*
2  * Copyright (c) 2014 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/public-api/math/matrix3.h>
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/math/math-utils.h>
23
24 // EXTERNAL INCLUDES
25 #include <string.h>
26 #include <iostream>
27
28
29 #define S00 0
30 #define S01 1
31 #define S02 2
32 #define S10 3
33 #define S11 4
34 #define S12 5
35 #define S20 6
36 #define S21 7
37 #define S22 8
38
39 /*
40  * S00 S01 S02
41  * S10 S11 S12
42  * S20 S21 S22
43  */
44
45 namespace
46 {
47 const size_t NUM_BYTES_IN_ROW    = 3*sizeof(float);
48 const size_t NUM_BYTES_IN_MATRIX = 9*sizeof(float);
49 }
50
51 namespace Dali
52 {
53
54 const Matrix3 Matrix3::IDENTITY(1.0f, 0.0f, 0.0f,
55                                 0.0f, 1.0f, 0.0f,
56                                 0.0f, 0.0f, 1.0f);
57
58 Matrix3::Matrix3()
59 {
60   float* m = AsFloat();
61   memset(m, 0, NUM_BYTES_IN_MATRIX);
62   mElements[S00]=1.0f;
63   mElements[S11]=1.0f;
64   mElements[S22]=1.0f;
65 }
66
67 Matrix3::Matrix3(const Matrix3& m)
68 {
69   memcpy( mElements, m.mElements, NUM_BYTES_IN_MATRIX );
70 }
71
72 Matrix3::Matrix3(const Matrix& matrix)
73 {
74   const float* m4 = matrix.AsFloat();
75   memcpy(&mElements[S00], m4,   NUM_BYTES_IN_ROW);
76   memcpy(&mElements[S10], m4+4, NUM_BYTES_IN_ROW);
77   memcpy(&mElements[S20], m4+8, NUM_BYTES_IN_ROW);
78 }
79
80 Matrix3::Matrix3(float s00, float s01, float s02, float s10, float s11, float s12, float s20, float s21, float s22)
81 {
82   mElements[S00] = s00;
83   mElements[S01] = s01;
84   mElements[S02] = s02;
85   mElements[S10] = s10;
86   mElements[S11] = s11;
87   mElements[S12] = s12;
88   mElements[S20] = s20;
89   mElements[S21] = s21;
90   mElements[S22] = s22;
91 }
92
93
94 void Matrix3::SetIdentity()
95 {
96   memset(mElements, 0, NUM_BYTES_IN_MATRIX);
97   mElements[S00]=1.0f;
98   mElements[S11]=1.0f;
99   mElements[S22]=1.0f;
100 }
101
102 Matrix3& Matrix3::operator=( const Matrix3& matrix )
103 {
104   // no point copying if self assigning
105   if( this != &matrix )
106   {
107     memcpy( AsFloat(), matrix.AsFloat(), NUM_BYTES_IN_MATRIX );
108   }
109   return *this;
110 }
111
112 Matrix3& Matrix3::operator=( const Matrix& matrix )
113 {
114   const float* m4 = matrix.AsFloat();
115   memcpy(&mElements[S00], m4,   NUM_BYTES_IN_ROW);
116   memcpy(&mElements[S10], m4+4, NUM_BYTES_IN_ROW);
117   memcpy(&mElements[S20], m4+8, NUM_BYTES_IN_ROW);
118   return *this;
119 }
120
121 bool Matrix3::Invert()
122 {
123   bool succeeded = false;
124
125   float cof[9];
126   cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
127   cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
128   cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
129
130   cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
131   cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
132   cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
133
134   cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
135   cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
136   cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
137
138   float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
139
140   // In the case where the determinant is exactly zero, the matrix is non-invertible
141   if( ! EqualsZero( det ) )
142   {
143     det = 1.0 / det;
144     for (int i = 0; i < 9; i++)
145     {
146       mElements[i] = cof[i] * det;
147     }
148     succeeded = true;
149   }
150   return succeeded;
151 }
152
153 bool Matrix3::Transpose()
154 {
155   float tmp;
156   tmp = mElements[S01]; mElements[S01] = mElements[S10]; mElements[S10]=tmp;
157   tmp = mElements[S02]; mElements[S02] = mElements[S20]; mElements[S20]=tmp;
158   tmp = mElements[S21]; mElements[S21] = mElements[S12]; mElements[S12]=tmp;
159   return true;
160 }
161
162 bool Matrix3::ScaledInverseTranspose()
163 {
164   bool succeeded = false;
165
166   float cof[9];
167   cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
168   cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
169   cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
170
171   cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
172   cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
173   cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
174
175   cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
176   cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
177   cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
178
179   float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
180
181   // In the case where the determinant is exactly zero, the matrix is non-invertible
182   if( ! EqualsZero( det ) )
183   {
184     // Use average rather than determinant to remove rounding to zero errors in further multiplication
185     float sum=0;
186     for(size_t i=0;i<9;i++)
187     {
188       sum+=fabsf(cof[i]);
189     }
190     float scale = 9.0f/sum; // Inverse of the average values
191     if (det < 0)
192     {
193       // Ensure the signs of the inverse are correct
194       scale = -scale;
195     }
196
197     mElements[S00] = cof[S00] * scale;
198     mElements[S01] = cof[S10] * scale;
199     mElements[S02] = cof[S20] * scale;
200
201     mElements[S10] = cof[S01] * scale;
202     mElements[S11] = cof[S11] * scale;
203     mElements[S12] = cof[S21] * scale;
204
205     mElements[S20] = cof[S02] * scale;
206     mElements[S21] = cof[S12] * scale;
207     mElements[S22] = cof[S22] * scale;
208
209     succeeded = true;
210   }
211   return succeeded;
212 }
213
214 void Matrix3::Scale(float scale)
215 {
216   mElements[S00] *= scale;
217   mElements[S01] *= scale;
218   mElements[S02] *= scale;
219   mElements[S10] *= scale;
220   mElements[S11] *= scale;
221   mElements[S12] *= scale;
222   mElements[S20] *= scale;
223   mElements[S21] *= scale;
224   mElements[S22] *= scale;
225 }
226
227 float Matrix3::Magnitude() const
228 {
229   float avg=0;
230   for(size_t i=0;i<9;i++)
231   {
232     avg+=fabsf(mElements[i]);
233   }
234   return avg/3.0f;
235 }
236
237
238 void Matrix3::Multiply( Matrix3& result, const Matrix3& lhs, const Matrix3& rhs )
239 {
240   float* temp = result.AsFloat();
241   const float* rhsPtr  = rhs.AsFloat();
242   const float* lhsPtr = lhs.AsFloat();
243
244   for( int i=0; i < 3; i++ )
245   {
246     int loc = i * 3;
247     int loc1 = loc + 1;
248     int loc2 = loc + 2;
249
250     float value0 = lhsPtr[loc];
251     float value1 = lhsPtr[loc1];
252     float value2 = lhsPtr[loc2];
253     temp[loc]  = (value0 * rhsPtr[0]) +
254                  (value1 * rhsPtr[3]) +
255                  (value2 * rhsPtr[6]);
256
257     temp[loc1] = (value0 * rhsPtr[1]) +
258                  (value1 * rhsPtr[4]) +
259                  (value2 * rhsPtr[7]);
260
261     temp[loc2] = (value0 * rhsPtr[2]) +
262                  (value1 * rhsPtr[5]) +
263                  (value2 * rhsPtr[8]);
264   }
265 }
266
267 bool Matrix3::operator==(const Matrix3 & rhs) const
268 {
269   return (
270     Equals( mElements[0], rhs.mElements[0]) &&
271     Equals( mElements[1], rhs.mElements[1]) &&
272     Equals( mElements[2], rhs.mElements[2]) &&
273     Equals( mElements[3], rhs.mElements[3]) &&
274     Equals( mElements[4], rhs.mElements[4]) &&
275     Equals( mElements[5], rhs.mElements[5]) &&
276     Equals( mElements[6], rhs.mElements[6]) &&
277     Equals( mElements[7], rhs.mElements[7]) &&
278     Equals( mElements[8], rhs.mElements[8]));
279 }
280
281 bool Matrix3::operator!=(const Matrix3& rhs) const
282 {
283   return !(*this == rhs);
284 }
285
286 std::ostream& operator<< (std::ostream& o, const Matrix3& matrix)
287 {
288   return o << "[ [" << matrix.mElements[0] << ", " << matrix.mElements[1] << ", " << matrix.mElements[2]  << "], "
289              << "[" << matrix.mElements[3] << ", " << matrix.mElements[4] << ", " << matrix.mElements[5]  << "], "
290              << "[" << matrix.mElements[6] << ", " << matrix.mElements[7] << ", " << matrix.mElements[8]  << "] ]";
291 }
292
293 } // namespace Dali