2 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/public-api/math/matrix3.h>
22 #include <cstdint> // uint32_t
23 #include <cstring> // memcpy
27 #include <dali/public-api/math/math-utils.h>
47 const uint32_t NUM_BYTES_IN_ROW = 3*sizeof(float);
48 const uint32_t NUM_BYTES_IN_MATRIX = 9*sizeof(float);
54 const Matrix3 Matrix3::IDENTITY(1.0f, 0.0f, 0.0f,
61 memset(m, 0, NUM_BYTES_IN_MATRIX);
64 Matrix3::Matrix3(const Matrix3& m)
66 memcpy( mElements, m.mElements, NUM_BYTES_IN_MATRIX );
69 Matrix3::Matrix3(const Matrix& matrix)
71 const float* m4 = matrix.AsFloat();
72 memcpy(&mElements[S00], m4, NUM_BYTES_IN_ROW);
73 memcpy(&mElements[S10], m4+4, NUM_BYTES_IN_ROW);
74 memcpy(&mElements[S20], m4+8, NUM_BYTES_IN_ROW);
77 Matrix3::Matrix3(float s00, float s01, float s02, float s10, float s11, float s12, float s20, float s21, float s22)
91 void Matrix3::SetIdentity()
93 memset(mElements, 0, NUM_BYTES_IN_MATRIX);
99 Matrix3::Matrix3( Matrix3&& matrix )
101 memcpy( mElements, matrix.mElements, NUM_BYTES_IN_MATRIX );
104 Matrix3& Matrix3::operator=( Matrix3&& matrix )
106 if( this != &matrix )
108 memcpy( AsFloat(), matrix.AsFloat(), NUM_BYTES_IN_MATRIX );
113 Matrix3& Matrix3::operator=( const Matrix3& matrix )
115 // no point copying if self assigning
116 if( this != &matrix )
118 memcpy( AsFloat(), matrix.AsFloat(), NUM_BYTES_IN_MATRIX );
123 Matrix3& Matrix3::operator=( const Matrix& matrix )
125 const float* m4 = matrix.AsFloat();
126 memcpy(&mElements[S00], m4, NUM_BYTES_IN_ROW);
127 memcpy(&mElements[S10], m4+4, NUM_BYTES_IN_ROW);
128 memcpy(&mElements[S20], m4+8, NUM_BYTES_IN_ROW);
132 bool Matrix3::Invert()
134 bool succeeded = false;
137 cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
138 cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
139 cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
141 cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
142 cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
143 cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
145 cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
146 cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
147 cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
149 float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
151 // In the case where the determinant is exactly zero, the matrix is non-invertible
152 if( ! EqualsZero( det ) )
155 for( int32_t i = 0; i < 9; i++ )
157 mElements[i] = cof[i] * det;
164 bool Matrix3::Transpose()
167 tmp = mElements[S01]; mElements[S01] = mElements[S10]; mElements[S10]=tmp;
168 tmp = mElements[S02]; mElements[S02] = mElements[S20]; mElements[S20]=tmp;
169 tmp = mElements[S21]; mElements[S21] = mElements[S12]; mElements[S12]=tmp;
173 bool Matrix3::ScaledInverseTranspose()
175 bool succeeded = false;
178 cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
179 cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
180 cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
182 cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
183 cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
184 cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
186 cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
187 cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
188 cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
190 float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
192 // In the case where the determinant is exactly zero, the matrix is non-invertible
193 if( ! EqualsZero( det ) )
195 // Use average rather than determinant to remove rounding to zero errors in further multiplication
197 for(uint32_t i=0;i<9;i++)
201 float scale = 9.0f/sum; // Inverse of the average values
204 // Ensure the signs of the inverse are correct
208 mElements[S00] = cof[S00] * scale;
209 mElements[S01] = cof[S10] * scale;
210 mElements[S02] = cof[S20] * scale;
212 mElements[S10] = cof[S01] * scale;
213 mElements[S11] = cof[S11] * scale;
214 mElements[S12] = cof[S21] * scale;
216 mElements[S20] = cof[S02] * scale;
217 mElements[S21] = cof[S12] * scale;
218 mElements[S22] = cof[S22] * scale;
225 void Matrix3::Scale(float scale)
227 mElements[S00] *= scale;
228 mElements[S01] *= scale;
229 mElements[S02] *= scale;
230 mElements[S10] *= scale;
231 mElements[S11] *= scale;
232 mElements[S12] *= scale;
233 mElements[S20] *= scale;
234 mElements[S21] *= scale;
235 mElements[S22] *= scale;
238 float Matrix3::Magnitude() const
241 for(uint32_t i=0;i<9;i++)
243 avg+=fabsf(mElements[i]);
249 void Matrix3::Multiply( Matrix3& result, const Matrix3& lhs, const Matrix3& rhs )
251 float* temp = result.AsFloat();
252 const float* rhsPtr = rhs.AsFloat();
253 const float* lhsPtr = lhs.AsFloat();
255 for( int32_t i=0; i < 3; i++ )
258 int32_t loc1 = loc + 1;
259 int32_t loc2 = loc + 2;
261 float value0 = lhsPtr[loc];
262 float value1 = lhsPtr[loc1];
263 float value2 = lhsPtr[loc2];
264 temp[loc] = (value0 * rhsPtr[0]) +
265 (value1 * rhsPtr[3]) +
266 (value2 * rhsPtr[6]);
268 temp[loc1] = (value0 * rhsPtr[1]) +
269 (value1 * rhsPtr[4]) +
270 (value2 * rhsPtr[7]);
272 temp[loc2] = (value0 * rhsPtr[2]) +
273 (value1 * rhsPtr[5]) +
274 (value2 * rhsPtr[8]);
278 bool Matrix3::operator==(const Matrix3 & rhs) const
281 Equals( mElements[0], rhs.mElements[0]) &&
282 Equals( mElements[1], rhs.mElements[1]) &&
283 Equals( mElements[2], rhs.mElements[2]) &&
284 Equals( mElements[3], rhs.mElements[3]) &&
285 Equals( mElements[4], rhs.mElements[4]) &&
286 Equals( mElements[5], rhs.mElements[5]) &&
287 Equals( mElements[6], rhs.mElements[6]) &&
288 Equals( mElements[7], rhs.mElements[7]) &&
289 Equals( mElements[8], rhs.mElements[8]));
292 bool Matrix3::operator!=(const Matrix3& rhs) const
294 return !(*this == rhs);
297 std::ostream& operator<< (std::ostream& o, const Matrix3& matrix)
299 return o << "[ " << matrix.mElements[0] << ", " << matrix.mElements[1] << ", " << matrix.mElements[2] << ", "
300 << matrix.mElements[3] << ", " << matrix.mElements[4] << ", " << matrix.mElements[5] << ", "
301 << matrix.mElements[6] << ", " << matrix.mElements[7] << ", " << matrix.mElements[8] << " ]";