2 * Copyright (c) 2022 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/internal/common/matrix-utils.h>
28 #include <dali/public-api/math/math-utils.h>
48 const uint32_t NUM_BYTES_IN_ROW = 3 * sizeof(float);
49 const uint32_t NUM_BYTES_IN_MATRIX = 9 * sizeof(float);
54 const Matrix3 Matrix3::IDENTITY(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
59 memset(m, 0, NUM_BYTES_IN_MATRIX);
62 Matrix3::Matrix3(const Matrix3& m)
64 memcpy(mElements, m.mElements, NUM_BYTES_IN_MATRIX);
67 Matrix3::Matrix3(const Matrix& matrix)
69 const float* m4 = matrix.AsFloat();
70 memcpy(&mElements[S00], m4, NUM_BYTES_IN_ROW);
71 memcpy(&mElements[S10], m4 + 4, NUM_BYTES_IN_ROW);
72 memcpy(&mElements[S20], m4 + 8, NUM_BYTES_IN_ROW);
75 Matrix3::Matrix3(float s00, float s01, float s02, float s10, float s11, float s12, float s20, float s21, float s22)
88 void Matrix3::SetIdentity()
90 memset(mElements, 0, NUM_BYTES_IN_MATRIX);
91 mElements[S00] = 1.0f;
92 mElements[S11] = 1.0f;
93 mElements[S22] = 1.0f;
96 Matrix3::Matrix3(Matrix3&& matrix) noexcept
98 memcpy(mElements, matrix.mElements, NUM_BYTES_IN_MATRIX);
101 Matrix3& Matrix3::operator=(Matrix3&& matrix) noexcept
105 memcpy(AsFloat(), matrix.AsFloat(), NUM_BYTES_IN_MATRIX);
110 Matrix3& Matrix3::operator=(const Matrix3& matrix)
112 // no point copying if self assigning
115 memcpy(AsFloat(), matrix.AsFloat(), NUM_BYTES_IN_MATRIX);
120 Matrix3& Matrix3::operator=(const Matrix& matrix)
122 const float* m4 = matrix.AsFloat();
123 memcpy(&mElements[S00], m4, NUM_BYTES_IN_ROW);
124 memcpy(&mElements[S10], m4 + 4, NUM_BYTES_IN_ROW);
125 memcpy(&mElements[S20], m4 + 8, NUM_BYTES_IN_ROW);
129 bool Matrix3::Invert()
131 bool succeeded = false;
134 cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
135 cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
136 cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
138 cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
139 cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
140 cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
142 cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
143 cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
144 cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
146 float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
148 // In the case where the determinant is exactly zero, the matrix is non-invertible
152 for(int32_t i = 0; i < 9; i++)
154 mElements[i] = cof[i] * det;
161 bool Matrix3::Transpose()
164 tmp = mElements[S01];
165 mElements[S01] = mElements[S10];
166 mElements[S10] = tmp;
167 tmp = mElements[S02];
168 mElements[S02] = mElements[S20];
169 mElements[S20] = tmp;
170 tmp = mElements[S21];
171 mElements[S21] = mElements[S12];
172 mElements[S12] = tmp;
176 bool Matrix3::ScaledInverseTranspose()
178 bool succeeded = false;
181 cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
182 cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
183 cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
185 cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
186 cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
187 cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
189 cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
190 cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
191 cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
193 float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
195 // In the case where the determinant is exactly zero, the matrix is non-invertible
198 // Use average rather than determinant to remove rounding to zero errors in further multiplication
200 for(uint32_t i = 0; i < 9; i++)
202 sum += fabsf(cof[i]);
204 float scale = 9.0f / sum; // Inverse of the average values
207 // Ensure the signs of the inverse are correct
211 mElements[S00] = cof[S00] * scale;
212 mElements[S01] = cof[S10] * scale;
213 mElements[S02] = cof[S20] * scale;
215 mElements[S10] = cof[S01] * scale;
216 mElements[S11] = cof[S11] * scale;
217 mElements[S12] = cof[S21] * scale;
219 mElements[S20] = cof[S02] * scale;
220 mElements[S21] = cof[S12] * scale;
221 mElements[S22] = cof[S22] * scale;
228 void Matrix3::Scale(float scale)
230 mElements[S00] *= scale;
231 mElements[S01] *= scale;
232 mElements[S02] *= scale;
233 mElements[S10] *= scale;
234 mElements[S11] *= scale;
235 mElements[S12] *= scale;
236 mElements[S20] *= scale;
237 mElements[S21] *= scale;
238 mElements[S22] *= scale;
241 float Matrix3::Magnitude() const
244 for(uint32_t i = 0; i < 9; i++)
246 avg += fabsf(mElements[i]);
251 void Matrix3::Multiply(Matrix3& result, const Matrix3& lhs, const Matrix3& rhs)
253 Internal::MatrixUtils::Multiply(result, lhs, rhs);
256 Matrix3 Matrix3::operator*(const Matrix3& rhs) const
259 Internal::MatrixUtils::Multiply(result, rhs, *this);
263 Matrix3& Matrix3::operator*=(const Matrix3& rhs)
265 Internal::MatrixUtils::MultiplyAssign(*this, rhs);
269 Vector3 Matrix3::operator*(const Vector3& rhs) const
271 return Vector3(rhs.x * mElements[S00] + rhs.y * mElements[S10] + rhs.z * mElements[S20],
272 rhs.x * mElements[S01] + rhs.y * mElements[S11] + rhs.z * mElements[S21],
273 rhs.x * mElements[S02] + rhs.y * mElements[S12] + rhs.z * mElements[S22]);
276 bool Matrix3::operator==(const Matrix3& rhs) const
279 Equals(mElements[0], rhs.mElements[0]) &&
280 Equals(mElements[1], rhs.mElements[1]) &&
281 Equals(mElements[2], rhs.mElements[2]) &&
282 Equals(mElements[3], rhs.mElements[3]) &&
283 Equals(mElements[4], rhs.mElements[4]) &&
284 Equals(mElements[5], rhs.mElements[5]) &&
285 Equals(mElements[6], rhs.mElements[6]) &&
286 Equals(mElements[7], rhs.mElements[7]) &&
287 Equals(mElements[8], rhs.mElements[8]));
290 bool Matrix3::operator!=(const Matrix3& rhs) const
292 return !(*this == rhs);
295 std::ostream& operator<<(std::ostream& o, const Matrix3& matrix)
297 return o << "[ " << matrix.mElements[0] << ", " << matrix.mElements[1] << ", " << matrix.mElements[2] << ", "
298 << matrix.mElements[3] << ", " << matrix.mElements[4] << ", " << matrix.mElements[5] << ", "
299 << matrix.mElements[6] << ", " << matrix.mElements[7] << ", " << matrix.mElements[8] << " ]";