Move some static Matrix / Matrix3 operations into specific file.
Previous logic doesn't support multiply-asign operations.
A = A * B; (valid. Because A operator=({result-of-(A*B)}))
A *= B; (invalid)
To resolve this issue, we plan to implement another operator *= for Matrix.
To seperate codes more clean + If we plan to make some util API about Matrix
(something like Internal::MatrixUtils::MultiplyProjectionMatrix)
Make another file for matrix utils internal.
TODO : Internal::MatrixUtils::MultiplyProjectionMatrix use NEON.
TODO : Make projection matrix use MatrixUtils after camera refator finished
Change-Id: I4333c52c93fb24f618ed509fe101a83e4a9f36c1
Signed-off-by: Eunki, Hong <eunkiki.hong@samsung.com>
utc-Dali-Internal-IndexedConstStringMap.cpp
utc-Dali-Internal-IndexedIntegerMap.cpp
utc-Dali-Internal-LongPressGesture.cpp
+ utc-Dali-Internal-MatrixUtils.cpp
utc-Dali-Internal-MemoryPoolObjectAllocator.cpp
utc-Dali-Internal-OwnerPointer.cpp
utc-Dali-Internal-PinchGesture.cpp
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/actors/camera-actor-devel.h>
+#include <dali/internal/common/matrix-utils.h>
+#include <dali/public-api/dali-core.h>
+#include <stdlib.h>
+
+#include <iostream>
+#include <sstream>
+
+using namespace Dali;
+
+namespace
+{
+// Final projection matrix logic, calculated at scene-graph-camera.
+Matrix CalculateFinalProjectionMatrix(Matrix projection, uint32_t mProjectionRotation)
+{
+ Matrix finalProjection;
+ Quaternion rotationAngle;
+ switch(mProjectionRotation)
+ {
+ case 90:
+ {
+ rotationAngle = Quaternion(Dali::ANGLE_90, Vector3::ZAXIS);
+ break;
+ }
+ case 180:
+ {
+ rotationAngle = Quaternion(Dali::ANGLE_180, Vector3::ZAXIS);
+ break;
+ }
+ case 270:
+ {
+ rotationAngle = Quaternion(Dali::ANGLE_270, Vector3::ZAXIS);
+ break;
+ }
+ default:
+ rotationAngle = Quaternion(Dali::ANGLE_0, Vector3::ZAXIS);
+ break;
+ }
+
+ Matrix rotation;
+ rotation.SetIdentity();
+ rotation.SetTransformComponents(Vector3(1.0f, 1.0f, 1.0f), rotationAngle, Vector3(0.0f, 0.0f, 0.0f));
+
+ Dali::Internal::MatrixUtils::Multiply(finalProjection, projection, rotation);
+
+ return finalProjection;
+}
+
+} // namespace
+
+void utc_dali_internal_matrix_utils_startup(void)
+{
+ test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_matrix_utils_cleanup(void)
+{
+ test_return_value = TET_PASS;
+}
+
+// Dali::Matrix
+
+int UtcDaliMatrixUtilsMultiplyMatrixP(void)
+{
+ const float ll[16] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
+ const float rr[16] = {1.0f, 5.0f, 0.0f, 0.0f, 2.0f, 6.0f, 0.0f, 0.0f, 3.0f, 7.0f, 0.0f, 0.0f, 4.0f, 8.0f, 0.0f, 0.0f};
+ Matrix left(ll);
+ Matrix right(rr);
+
+ const float els[16] = {26.0f, 32.0f, 38.0f, 44.0f, 32.0f, 40.0f, 48.0f, 56.0f, 38.0f, 48.0f, 58.0f, 68.0f, 44.0f, 56.0f, 68.0f, 80.0f};
+ Matrix result(els);
+
+ Matrix multResult;
+
+ // Get result by Multiply API
+ Internal::MatrixUtils::Multiply(multResult, right, left);
+ DALI_TEST_EQUALS(multResult, result, 0.01f, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliMatrixUtilsMultiplyMatrixQuaternionP(void)
+{
+ Matrix m1 = Matrix::IDENTITY;
+
+ float els[] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.707f, 0.707f, 0.0f, 0.0f, -0.707f, 0.707f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+ Matrix result(els);
+
+ Quaternion q(Radian(Degree(45.0f)), Vector3::XAXIS);
+ Matrix m2(false);
+ Internal::MatrixUtils::Multiply(m2, m1, q);
+
+ DALI_TEST_EQUALS(m2, result, 0.01f, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliMatrixUtilsMultiplyProjectionMatrix(void)
+{
+ tet_infoline("Multiplication Assign operator with self matrix\n");
+
+ Matrix viewMatrix;
+ Matrix projectionMatrix;
+ Matrix finalProjectionMatrix;
+
+ Matrix expectViewProjection;
+ Matrix resultViewProjection;
+
+ TestApplication application;
+
+ Vector2 sceneSize = application.GetScene().GetSize();
+
+ CameraActor camera = CameraActor::New();
+ DALI_TEST_CHECK(camera);
+ application.GetScene().Add(camera);
+
+ // Rotate camera 4 times
+ for(int32_t i = 0; i < 4; i++)
+ {
+ int32_t rotationAngle = i * 90;
+ tet_printf("Window rotation angle : %d\n", rotationAngle);
+
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+
+ for(int32_t repeatCount = 0; repeatCount < 10; repeatCount++)
+ {
+ Vector3 pos = Vector3(Dali::Random::Range(-50.0f, 50.0f), Dali::Random::Range(-50.0f, 50.0f), Dali::Random::Range(-50.0f, 50.0f));
+ Vector3 axis = Vector3(Dali::Random::Range(1.0f, 50.0f), Dali::Random::Range(-50.0f, 50.0f), Dali::Random::Range(-50.0f, 50.0f));
+ float radian = Dali::Random::Range(0.0f, 5.0f);
+ Quaternion orientation = Quaternion(Radian(radian), axis);
+
+ camera.SetPerspectiveProjection(sceneSize);
+
+ // Change ViewMatrix randomly.
+ camera.SetProperty(Dali::Actor::Property::POSITION, pos);
+ camera.SetProperty(Dali::Actor::Property::ORIENTATION, orientation);
+
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+
+ camera.GetProperty(CameraActor::CameraActor::Property::PROJECTION_MATRIX).Get(projectionMatrix);
+ camera.GetProperty(CameraActor::CameraActor::Property::VIEW_MATRIX).Get(viewMatrix);
+ finalProjectionMatrix = CalculateFinalProjectionMatrix(projectionMatrix, rotationAngle);
+
+ // Get result by Multiply API
+ Internal::MatrixUtils::Multiply(expectViewProjection, viewMatrix, finalProjectionMatrix);
+ // Get result by MultiplyProjectionMatrix API
+ Internal::MatrixUtils::MultiplyProjectionMatrix(resultViewProjection, viewMatrix, finalProjectionMatrix);
+
+ {
+ std::ostringstream oss;
+ oss << "projection : " << projectionMatrix << "\n";
+ oss << "final : " << finalProjectionMatrix << "\n";
+ oss << "view : " << viewMatrix << "\n";
+ oss << "expect : " << expectViewProjection << "\n";
+ oss << "result : " << resultViewProjection << "\n";
+ tet_printf("pespective : \n%s\n", oss.str().c_str());
+ }
+
+ DALI_TEST_EQUALS(resultViewProjection, expectViewProjection, 0.01f, TEST_LOCATION);
+
+ camera.SetOrthographicProjection(sceneSize);
+
+ // Change ViewMatrix randomly.
+ camera.SetProperty(Dali::Actor::Property::POSITION, pos);
+ camera.SetProperty(Dali::Actor::Property::ORIENTATION, orientation);
+
+ application.SendNotification();
+ application.Render();
+ application.SendNotification();
+ application.Render();
+
+ camera.GetProperty(CameraActor::CameraActor::Property::PROJECTION_MATRIX).Get(projectionMatrix);
+ camera.GetProperty(CameraActor::CameraActor::Property::VIEW_MATRIX).Get(viewMatrix);
+ finalProjectionMatrix = CalculateFinalProjectionMatrix(projectionMatrix, rotationAngle);
+
+ // Get result by Multiply API
+ Internal::MatrixUtils::Multiply(expectViewProjection, viewMatrix, finalProjectionMatrix);
+ // Get result by MultiplyProjectionMatrix API
+ Internal::MatrixUtils::MultiplyProjectionMatrix(resultViewProjection, viewMatrix, finalProjectionMatrix);
+
+ {
+ std::ostringstream oss;
+ oss << "projection : " << projectionMatrix << "\n";
+ oss << "final : " << finalProjectionMatrix << "\n";
+ oss << "view : " << viewMatrix << "\n";
+ oss << "expect : " << expectViewProjection << "\n";
+ oss << "result : " << resultViewProjection << "\n";
+ tet_printf("orthographic : \n%s\n", oss.str().c_str());
+ }
+
+ DALI_TEST_EQUALS(resultViewProjection, expectViewProjection, 0.01f, TEST_LOCATION);
+ }
+ }
+
+ END_TEST;
+}
+
+int UtcDaliMatrixUtilsMultiplyAssignMatrix01P(void)
+{
+ tet_infoline("Multiplication Assign operator\n");
+ const float ll[16] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 0.0f, 0.0f, 11.0f, 12.0f, 0.0f, 0.0f};
+ const float rr[16] = {1.0f, 5.0f, 9.0f, 10.0f, 2.0f, 6.0f, 11.0f, 12.0f, 3.0f, 7.0f, 0.0f, 0.0f, 4.0f, 8.0f, 0.0f, 0.0f};
+ Matrix left(ll);
+ Matrix right(rr);
+
+ const float els[16] = {217.0f, 242.0f, 38.0f, 44.0f, 263.0f, 294.0f, 48.0f, 56.0f, 38.0f, 48.0f, 58.0f, 68.0f, 44.0f, 56.0f, 68.0f, 80.0f};
+ Matrix result(els);
+
+ // Get result by MultiplyAssign API
+ Internal::MatrixUtils::MultiplyAssign(left, right);
+ DALI_TEST_EQUALS(left, result, 0.01f, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliMatrixUtilsMultiplyAssignMatrix02P(void)
+{
+ tet_infoline("Multiplication Assign operator with self matrix\n");
+ const float ll[16] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 0.0f, 0.0f, 11.0f, 12.0f, 0.0f, 0.0f};
+ Matrix left(ll);
+
+ const float els[16] = {82.0f, 92.0f, 17.0f, 20.0f, 186.0f, 212.0f, 57.0f, 68.0f, 59.0f, 78.0f, 97.0f, 116.0f, 71.0f, 94.0f, 117.0f, 140.0f};
+ Matrix result(els);
+
+ // Get result by MultiplyAssign API
+ Internal::MatrixUtils::MultiplyAssign(left, left);
+ DALI_TEST_EQUALS(left, result, 0.01f, TEST_LOCATION);
+
+ END_TEST;
+}
+
+// Dali::Matrix3
+
+int UtcDaliMatrixUtilsMultiplyMatrix3P(void)
+{
+ Matrix3 left(
+ 1.0f, 2.0f, 3.0f, 5.0f, 6.0f, 7.0f, 0.0f, 0.0f, 0.0f);
+ Matrix3 right(
+ 1.0f, 5.0f, 0.0f, 2.0f, 6.0f, 0.0f, 3.0f, 7.0f, 0.0f);
+
+ Matrix3 result(
+ 26.0f, 32.0f, 38.0f, 32.0f, 40.0f, 48.0f, 38.0f, 48.0f, 58.0f);
+
+ Matrix3 multResult;
+
+ // Get result by Multiply API
+ Internal::MatrixUtils::Multiply(multResult, right, left);
+ DALI_TEST_EQUALS(multResult, result, 0.01f, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliMatrixUtilsMultiplyAssignMatrix301P(void)
+{
+ tet_infoline("Multiplication Assign operator\n");
+ Matrix3 left(
+ 1.0f, 2.0f, 3.0f, 5.0f, 6.0f, 7.0f, 9.0f, 10.0f, 0.0f);
+ Matrix3 right(
+ 1.0f, 5.0f, 9.0f, 2.0f, 6.0f, 11.0f, 3.0f, 7.0f, 0.0f);
+
+ Matrix3 result(
+ 107.0f, 122.0f, 38.0f, 131.0f, 150.0f, 48.0f, 38.0f, 48.0f, 58.0f);
+
+ // Get result by MultiplyAssign API
+ Internal::MatrixUtils::MultiplyAssign(left, right);
+ DALI_TEST_EQUALS(left, result, 0.01f, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliMatrixUtilsMultiplyAssignMatrix302P(void)
+{
+ tet_infoline("Multiplication Assign operator with self matrix\n");
+ Matrix3 left(
+ 1.0f, 2.0f, 3.0f, 5.0f, 6.0f, 7.0f, 9.0f, 10.0f, 0.0f);
+
+ Matrix3 result(
+ 38.0f, 44.0f, 17.0f, 98.0f, 116.0f, 57.0f, 59.0f, 78.0f, 97.0f);
+
+ // Get result by MultiplyAssign API
+ Internal::MatrixUtils::MultiplyAssign(left, left);
+ DALI_TEST_EQUALS(left, result, 0.01f, TEST_LOCATION);
+
+ END_TEST;
+}
END_TEST;
}
+int UtcDaliMatrixOperatorMultiplyAssign01P(void)
+{
+ tet_infoline("Multiplication Assign operator\n");
+ const float ll[16] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 0.0f, 0.0f, 11.0f, 12.0f, 0.0f, 0.0f};
+ const float rr[16] = {1.0f, 5.0f, 9.0f, 10.0f, 2.0f, 6.0f, 11.0f, 12.0f, 3.0f, 7.0f, 0.0f, 0.0f, 4.0f, 8.0f, 0.0f, 0.0f};
+ Matrix left(ll);
+ Matrix right(rr);
+ Matrix copyedLeft(ll);
+
+ const float els[16] = {217.0f, 242.0f, 38.0f, 44.0f, 263.0f, 294.0f, 48.0f, 56.0f, 38.0f, 48.0f, 58.0f, 68.0f, 44.0f, 56.0f, 68.0f, 80.0f};
+ Matrix result(els);
+
+ // Get result by operator*
+ Matrix multResult = left * right;
+ DALI_TEST_EQUALS(multResult, result, 0.01f, TEST_LOCATION);
+
+ // Get result by operator*=
+ left *= right;
+ DALI_TEST_EQUALS(left, result, 0.01f, TEST_LOCATION);
+
+ END_TEST;
+}
+
+int UtcDaliMatrixOperatorMultiplyAssign02P(void)
+{
+ tet_infoline("Multiplication Assign operator with self matrix\n");
+ const float ll[16] = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 0.0f, 0.0f, 11.0f, 12.0f, 0.0f, 0.0f};
+ Matrix left(ll);
+ Matrix copyedLeft(ll);
+
+ const float els[16] = {82.0f, 92.0f, 17.0f, 20.0f, 186.0f, 212.0f, 57.0f, 68.0f, 59.0f, 78.0f, 97.0f, 116.0f, 71.0f, 94.0f, 117.0f, 140.0f};
+ Matrix result(els);
+
+ // Get result by operator*
+ Matrix multResult = left * copyedLeft;
+ DALI_TEST_EQUALS(multResult, result, 0.01f, TEST_LOCATION);
+
+ // Get result by operator*=
+ left *= left;
+ DALI_TEST_EQUALS(left, result, 0.01f, TEST_LOCATION);
+
+ END_TEST;
+}
+
int UtcDaliMatrixOperatorEqualsP(void)
{
Matrix m1 = Matrix::IDENTITY;
END_TEST;
}
+int UtcDaliMatrix3OperatorMultiplyAssign01P(void)
+{
+ tet_infoline("Multiplication Assign operator\n");
+ Matrix3 left(
+ 1.0f, 2.0f, 3.0f, 5.0f, 6.0f, 7.0f, 9.0f, 10.0f, 0.0f);
+ Matrix3 right(
+ 1.0f, 5.0f, 9.0f, 2.0f, 6.0f, 11.0f, 3.0f, 7.0f, 0.0f);
+ Matrix3 copiedLeft(left);
+
+ Matrix3 result(
+ 107.0f, 122.0f, 38.0f, 131.0f, 150.0f, 48.0f, 38.0f, 48.0f, 58.0f);
+
+ // Get result by operator*
+ Matrix3 multResult = left * right;
+ DALI_TEST_EQUALS(multResult, result, 0.01f, TEST_LOCATION);
+
+ // Get result by operator*=
+ left *= right;
+ DALI_TEST_EQUALS(left, result, 0.01f, TEST_LOCATION);
+ END_TEST;
+}
+
+int UtcDaliMatrix3OperatorMultiplyAssign02P(void)
+{
+ tet_infoline("Multiplication Assign operator with self matrix\n");
+ Matrix3 left(
+ 1.0f, 2.0f, 3.0f, 5.0f, 6.0f, 7.0f, 9.0f, 10.0f, 0.0f);
+ Matrix3 copiedLeft(left);
+
+ Matrix3 result(
+ 38.0f, 44.0f, 17.0f, 98.0f, 116.0f, 57.0f, 59.0f, 78.0f, 97.0f);
+
+ // Get result by operator*
+ Matrix3 multResult = left * copiedLeft;
+ DALI_TEST_EQUALS(multResult, result, 0.01f, TEST_LOCATION);
+
+ // Get result by operator*=
+ left *= left;
+ DALI_TEST_EQUALS(left, result, 0.01f, TEST_LOCATION);
+ END_TEST;
+}
+
int UtcDaliMatrix3EqualityOperator(void)
{
Matrix3 m1(0.0f, 3.0f, 6.0f, 12.0f, 15.0f, 18.0f, 24.0f, 27.0f, 30.0f);
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADERS
+#include <dali/internal/common/matrix-utils.h>
+
+// EXTERNAL INCLUDES
+#include <cstdint> // uint32_t
+#include <cstring> // memcpy
+
+// INTERNAL INCLUDE
+#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/matrix3.h>
+#include <dali/public-api/math/quaternion.h>
+
+namespace
+{
+const uint32_t NUM_BYTES_IN_MATRIX(16 * sizeof(float));
+const uint32_t NUM_BYTES_IN_MATRIX3(9 * sizeof(float));
+
+} // namespace
+
+namespace Dali::Internal
+{
+using Internal::PerformanceMonitor;
+
+namespace MatrixUtils
+{
+// Dali::Quaternion
+
+void ConvertQuaternion(float*& result, const Dali::Quaternion& rotation)
+{
+ MATH_INCREASE_COUNTER(PerformanceMonitor::QUATERNION_TO_MATRIX);
+
+ const float xx = rotation.mVector.x * rotation.mVector.x;
+ const float yy = rotation.mVector.y * rotation.mVector.y;
+ const float zz = rotation.mVector.z * rotation.mVector.z;
+ const float xy = rotation.mVector.x * rotation.mVector.y;
+ const float xz = rotation.mVector.x * rotation.mVector.z;
+ const float wx = rotation.mVector.w * rotation.mVector.x;
+ const float wy = rotation.mVector.w * rotation.mVector.y;
+ const float wz = rotation.mVector.w * rotation.mVector.z;
+ const float yz = rotation.mVector.y * rotation.mVector.z;
+
+ // clang-format off
+ result[0] = 1.0f - 2.0f * (yy + zz);
+ result[1] = 2.0f * (xy + wz);
+ result[2] = 2.0f * (xz - wy);
+ result[3] = 0.0f;
+
+ result[4] = 2.0f * (xy - wz);
+ result[5] = 1.0f - 2.0f * (xx + zz);
+ result[6] = 2.0f * (yz + wx);
+ result[7] = 0.0f;
+
+ result[8] = 2.0f * (xz + wy);
+ result[9] = 2.0f * (yz - wx);
+ result[10]= 1.0f - 2.0f * (xx + yy);
+ result[11]= 0.0f;
+
+ result[12]= 0.0f;
+ result[13]= 0.0f;
+ result[14]= 0.0f;
+ result[15]= 1.0f;
+ // clang-format on
+}
+
+// Dali::Matrix
+
+void Multiply(Dali::Matrix& result, const Dali::Matrix& lhs, const Dali::Matrix& rhs)
+{
+ MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
+ MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY, 64); // 64 = 16*4
+
+ float* temp = result.AsFloat();
+ const float* rhsPtr = rhs.AsFloat();
+ const float* lhsPtr = lhs.AsFloat();
+
+#ifndef __ARM_NEON__
+
+ for(int32_t i = 0; i < 4; i++)
+ {
+ // i<<2 gives the first vector / column
+ const int32_t loc0 = i << 2;
+ const int32_t loc1 = loc0 + 1;
+ const int32_t loc2 = loc0 + 2;
+ const int32_t loc3 = loc0 + 3;
+
+ const float value0 = lhsPtr[loc0];
+ const float value1 = lhsPtr[loc1];
+ const float value2 = lhsPtr[loc2];
+ const float value3 = lhsPtr[loc3];
+
+ temp[loc0] = (value0 * rhsPtr[0]) +
+ (value1 * rhsPtr[4]) +
+ (value2 * rhsPtr[8]) +
+ (value3 * rhsPtr[12]);
+
+ temp[loc1] = (value0 * rhsPtr[1]) +
+ (value1 * rhsPtr[5]) +
+ (value2 * rhsPtr[9]) +
+ (value3 * rhsPtr[13]);
+
+ temp[loc2] = (value0 * rhsPtr[2]) +
+ (value1 * rhsPtr[6]) +
+ (value2 * rhsPtr[10]) +
+ (value3 * rhsPtr[14]);
+
+ temp[loc3] = (value0 * rhsPtr[3]) +
+ (value1 * rhsPtr[7]) +
+ (value2 * rhsPtr[11]) +
+ (value3 * rhsPtr[15]);
+ }
+
+#else
+
+ // 64 32bit registers,
+ // aliased to
+ // d = 64 bit double-word d0 -d31
+ // q =128 bit quad-word q0 -q15 (enough to handle a column of 4 floats in a matrix)
+ // e.g. q0 = d0 and d1
+
+ // load and stores interleaved as NEON can load and store while calculating
+ asm volatile(
+ "VLDM %1, {q0-q3} \n\t" // load matrix 1 (lhsPtr) q[0..q3]
+ "VLDM %0, {q8-q11} \n\t" // load matrix 2 (rhsPtr) q[q8-q11]
+ "VMUL.F32 q12, q8, d0[0] \n\t" // column 0 = rhsPtr[0..3] * lhsPtr[0..3]
+ "VMUL.F32 q13, q8, d2[0] \n\t" // column 1 = rhsPtr[0..3] * lhsPtr[4..7]
+ "VMUL.F32 q14, q8, d4[0] \n\t" // column 2 = rhsPtr[0..3] * lhsPtr[8..11]
+ "VMUL.F32 q15, q8, d6[0] \n\t" // column 3 = rhsPtr[0..3] * lhsPtr[12..15]
+
+ "VMLA.F32 q12, q9, d0[1] \n\t" // column 0 += rhsPtr[4..7] * lhsPtr[0..3]
+ "VMLA.F32 q13, q9, d2[1] \n\t" // column 1 += rhsPtr[4..7] * lhsPtr[4..7]
+ "VMLA.F32 q14, q9, d4[1] \n\t" // column 2 += rhsPtr[4..7] * lhsPtr[8..11]
+ "VMLA.F32 q15, q9, d6[1] \n\t" // column 3 += rhsPtr[4..7] * lhsPtr[12..15]
+
+ "VMLA.F32 q12, q10, d1[0] \n\t" // column 0 += rhsPtr[8..11] * lhsPtr[0..3]
+ "VMLA.F32 q13, q10, d3[0] \n\t" // column 1 += rhsPtr[8..11] * lhsPtr[4..7]
+ "VMLA.F32 q14, q10, d5[0] \n\t" // column 2 += rhsPtr[8..11] * lhsPtr[8..11]
+ "VMLA.F32 q15, q10, d7[0] \n\t" // column 3 += rhsPtr[8..11] * lhsPtr[12..15]
+
+ "VMLA.F32 q12, q11, d1[1] \n\t" // column 0 += rhsPtr[12..15] * lhsPtr[0..3]
+ "VMLA.F32 q13, q11, d3[1] \n\t" // column 1 += rhsPtr[12..15] * lhsPtr[4..7]
+ "VMLA.F32 q14, q11, d5[1] \n\t" // column 2 += rhsPtr[12..15] * lhsPtr[8..11]
+ "VMLA.F32 q15, q11, d7[1] \n\t" // column 3 += rhsPtr[12..15] * lhsPtr[12..15]
+ "VSTM %2, {q12-q15} \n\t" // store entire output matrix.
+ : "+r"(rhsPtr), "+r"(lhsPtr), "+r"(temp)
+ :
+ : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory");
+
+#endif
+}
+
+void Multiply(Dali::Matrix& result, const Dali::Matrix& lhs, const Dali::Quaternion& rhs)
+{
+ MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
+ MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY, 54); // 54 = 36+18
+
+ float matrix[16];
+ float* rhsPtr = &matrix[0];
+ ConvertQuaternion(rhsPtr, rhs);
+
+ // quaternion contains just rotation so it really only needs 3x3 matrix
+
+ float* temp = result.AsFloat();
+ const float* lhsPtr = lhs.AsFloat();
+
+#ifndef __ARM_NEON__
+
+ for(int32_t i = 0; i < 4; i++)
+ {
+ // i<<2 gives the first vector / column
+ const int32_t loc0 = i << 2;
+ const int32_t loc1 = loc0 + 1;
+ const int32_t loc2 = loc0 + 2;
+ const int32_t loc3 = loc0 + 3;
+
+ const float value0 = lhsPtr[loc0];
+ const float value1 = lhsPtr[loc1];
+ const float value2 = lhsPtr[loc2];
+ const float value3 = lhsPtr[loc3];
+
+ temp[loc0] = (value0 * rhsPtr[0]) +
+ (value1 * rhsPtr[4]) +
+ (value2 * rhsPtr[8]) +
+ (0.0f); //value3 * rhsPtr[12] is 0.0f
+
+ temp[loc1] = (value0 * rhsPtr[1]) +
+ (value1 * rhsPtr[5]) +
+ (value2 * rhsPtr[9]) +
+ (0.0f); //value3 * rhsPtr[13] is 0.0f
+
+ temp[loc2] = (value0 * rhsPtr[2]) +
+ (value1 * rhsPtr[6]) +
+ (value2 * rhsPtr[10]) +
+ (0.0f); //value3 * rhsPtr[14] is 0.0f
+
+ temp[loc3] = (0.0f) + //value0 * rhsPtr[3] is 0.0f
+ (0.0f) + //value1 * rhsPtr[7] is 0.0f
+ (0.0f) + //value2 * rhsPtr[11] is 0.0f
+ (value3); // rhsPtr[15] is 1.0f
+ }
+
+#else
+
+ // 64 32bit registers,
+ // aliased to
+ // d = 64 bit double-word d0 -d31
+ // q =128 bit quad-word q0 -q15 (enough to handle a column of 4 floats in a matrix)
+ // e.g. q0 = d0 and d1
+ // load and stores interleaved as NEON can load and store while calculating
+ asm volatile(
+ "VLDM %1, {q4-q6} \n\t" // load matrix 1 (lhsPtr)
+ "VLD1.F32 {q7}, [%2]! \n\t" // load matrix 2 (rhsPtr) [0..3]
+ "VMUL.F32 q0, q7, d8[0] \n\t" // column 0 = rhsPtr[0..3] * lhsPtr[0..3]
+ "VMUL.F32 q1, q7, d10[0] \n\t" // column 1 = rhsPtr[0..3] * lhsPtr[4..7]
+ "VMUL.F32 q2, q7, d12[0] \n\t" // column 2 = rhsPtr[0..3] * lhsPtr[8..11]
+ "VLD1.F32 {q7}, [%2]! \n\t" // load matrix 2 (rhsPtr) [4..7]
+ "VMLA.F32 q0, q7, d8[1] \n\t" // column 0+= rhsPtr[4..7] * lhsPtr[0..3]
+ "VMLA.F32 q1, q7, d10[1] \n\t" // column 1+= rhsPtr[4..7] * lhsPtr[4..7]
+ "VMLA.F32 q2, q7, d12[1] \n\t" // column 2+= rhsPtr[4..7] * lhsPtr[8..11]
+ "VLD1.F32 {q7}, [%2]! \n\t" // load matrix 2 (rhsPtr) [8..11]
+ "VMLA.F32 q0, q7, d9[0] \n\t" // column 0+= rhsPtr[8..11] * lhsPtr[0..3]
+ "VMLA.F32 q1, q7, d11[0] \n\t" // column 1+= rhsPtr[8..11] * lhsPtr[4..7]
+ "VMLA.F32 q2, q7, d13[0] \n\t" // column 2+= rhsPtr[8..11] * lhsPtr[8..11]
+ "VSTM %0, {q0-q2} \n\t" // store entire output matrix.
+ :
+ : "r"(temp), "r"(lhsPtr), "r"(rhsPtr)
+ : "%r0", "%q0", "%q1", "%q2", "%q4", "%q5", "%q6", "%q7", "memory");
+
+ temp[12] = 0.0f;
+ temp[13] = 0.0f;
+ temp[14] = 0.0f;
+ temp[15] = 1.0f;
+#endif
+}
+
+void MultiplyProjectionMatrix(Dali::Matrix& result, const Dali::Matrix& lhs, const Dali::Matrix& projection)
+{
+ // TODO : Implement with NEON.
+ // Current NEON code is copy of Multiply.
+
+ MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
+ MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY, 32); // 32 = 8*4
+
+ float* temp = result.AsFloat();
+ const float* rhsPtr = projection.AsFloat();
+ const float* lhsPtr = lhs.AsFloat();
+
+#ifndef __ARM_NEON__
+
+ // We only use rhsPtr's 0, 1, 4, 5, 10, 11, 14, 15 index.
+ const float rhs0 = rhsPtr[0];
+ const float rhs1 = rhsPtr[1];
+ const float rhs4 = rhsPtr[4];
+ const float rhs5 = rhsPtr[5];
+ const float rhs10 = rhsPtr[10];
+ const float rhs11 = rhsPtr[11];
+ const float rhs14 = rhsPtr[14];
+ const float rhs15 = rhsPtr[15];
+
+ for(int32_t i = 0; i < 4; i++)
+ {
+ // i<<2 gives the first vector / column
+ const int32_t loc0 = i << 2;
+ const int32_t loc1 = loc0 + 1;
+ const int32_t loc2 = loc0 + 2;
+ const int32_t loc3 = loc0 + 3;
+
+ const float value0 = lhsPtr[loc0];
+ const float value1 = lhsPtr[loc1];
+ const float value2 = lhsPtr[loc2];
+ const float value3 = lhsPtr[loc3];
+
+ temp[loc0] = (value0 * rhs0) + (value1 * rhs4);
+ temp[loc1] = (value0 * rhs1) + (value1 * rhs5);
+ temp[loc2] = (value2 * rhs10) + (value3 * rhs14);
+ temp[loc3] = (value2 * rhs11) + (value3 * rhs15);
+ }
+
+#else
+
+ // 64 32bit registers,
+ // aliased to
+ // d = 64 bit double-word d0 -d31
+ // q =128 bit quad-word q0 -q15 (enough to handle a column of 4 floats in a matrix)
+ // e.g. q0 = d0 and d1
+
+ // load and stores interleaved as NEON can load and store while calculating
+ asm volatile(
+ "VLDM %1, {q0-q3} \n\t" // load matrix 1 (lhsPtr) q[0..q3]
+ "VLDM %0, {q8-q11} \n\t" // load matrix 2 (rhsPtr) q[q8-q11]
+ "VMUL.F32 q12, q8, d0[0] \n\t" // column 0 = rhsPtr[0..3] * lhsPtr[0..3]
+ "VMUL.F32 q13, q8, d2[0] \n\t" // column 1 = rhsPtr[0..3] * lhsPtr[4..7]
+ "VMUL.F32 q14, q8, d4[0] \n\t" // column 2 = rhsPtr[0..3] * lhsPtr[8..11]
+ "VMUL.F32 q15, q8, d6[0] \n\t" // column 3 = rhsPtr[0..3] * lhsPtr[12..15]
+
+ "VMLA.F32 q12, q9, d0[1] \n\t" // column 0 += rhsPtr[4..7] * lhsPtr[0..3]
+ "VMLA.F32 q13, q9, d2[1] \n\t" // column 1 += rhsPtr[4..7] * lhsPtr[4..7]
+ "VMLA.F32 q14, q9, d4[1] \n\t" // column 2 += rhsPtr[4..7] * lhsPtr[8..11]
+ "VMLA.F32 q15, q9, d6[1] \n\t" // column 3 += rhsPtr[4..7] * lhsPtr[12..15]
+
+ "VMLA.F32 q12, q10, d1[0] \n\t" // column 0 += rhsPtr[8..11] * lhsPtr[0..3]
+ "VMLA.F32 q13, q10, d3[0] \n\t" // column 1 += rhsPtr[8..11] * lhsPtr[4..7]
+ "VMLA.F32 q14, q10, d5[0] \n\t" // column 2 += rhsPtr[8..11] * lhsPtr[8..11]
+ "VMLA.F32 q15, q10, d7[0] \n\t" // column 3 += rhsPtr[8..11] * lhsPtr[12..15]
+
+ "VMLA.F32 q12, q11, d1[1] \n\t" // column 0 += rhsPtr[12..15] * lhsPtr[0..3]
+ "VMLA.F32 q13, q11, d3[1] \n\t" // column 1 += rhsPtr[12..15] * lhsPtr[4..7]
+ "VMLA.F32 q14, q11, d5[1] \n\t" // column 2 += rhsPtr[12..15] * lhsPtr[8..11]
+ "VMLA.F32 q15, q11, d7[1] \n\t" // column 3 += rhsPtr[12..15] * lhsPtr[12..15]
+ "VSTM %2, {q12-q15} \n\t" // store entire output matrix.
+ : "+r"(rhsPtr), "+r"(lhsPtr), "+r"(temp)
+ :
+ : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory");
+
+#endif
+}
+
+void MultiplyAssign(Dali::Matrix& result, const Dali::Matrix& rhs)
+{
+ MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
+ MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY, 64); // 64 = 16*4
+
+ // TODO : Implement with NEON.
+
+ float* lhsPtr = result.AsFloat();
+ const float* rhsPtr = rhs.AsFloat();
+ float* temp = nullptr;
+
+ if(lhsPtr == rhsPtr)
+ {
+ // If rhs is same matrix with result, we need to copy temperal vaules.
+ temp = static_cast<float*>(malloc(NUM_BYTES_IN_MATRIX));
+ memcpy(temp, rhsPtr, NUM_BYTES_IN_MATRIX);
+ rhsPtr = temp;
+ }
+
+ // Calculate and store as row major.
+ for(int32_t i = 0; i < 4; i++)
+ {
+ const int32_t loc0 = i;
+ const int32_t loc1 = loc0 | 4;
+ const int32_t loc2 = loc0 | 8;
+ const int32_t loc3 = loc0 | 12;
+
+ const float value0 = lhsPtr[loc0];
+ const float value1 = lhsPtr[loc1];
+ const float value2 = lhsPtr[loc2];
+ const float value3 = lhsPtr[loc3];
+
+ lhsPtr[loc0] = (value0 * rhsPtr[0]) +
+ (value1 * rhsPtr[1]) +
+ (value2 * rhsPtr[2]) +
+ (value3 * rhsPtr[3]);
+
+ lhsPtr[loc1] = (value0 * rhsPtr[4]) +
+ (value1 * rhsPtr[5]) +
+ (value2 * rhsPtr[6]) +
+ (value3 * rhsPtr[7]);
+
+ lhsPtr[loc2] = (value0 * rhsPtr[8]) +
+ (value1 * rhsPtr[9]) +
+ (value2 * rhsPtr[10]) +
+ (value3 * rhsPtr[11]);
+
+ lhsPtr[loc3] = (value0 * rhsPtr[12]) +
+ (value1 * rhsPtr[13]) +
+ (value2 * rhsPtr[14]) +
+ (value3 * rhsPtr[15]);
+ }
+
+ if(temp)
+ {
+ // If we allocate temperal memory, we should free it.
+ free(temp);
+ }
+}
+
+// Dali::Matrix3
+
+void Multiply(Dali::Matrix3& result, const Dali::Matrix3& lhs, const Dali::Matrix3& rhs)
+{
+ float* temp = result.AsFloat();
+ const float* rhsPtr = rhs.AsFloat();
+ const float* lhsPtr = lhs.AsFloat();
+
+ for(int32_t i = 0; i < 3; i++)
+ {
+ const int32_t loc0 = i * 3;
+ const int32_t loc1 = loc0 + 1;
+ const int32_t loc2 = loc0 + 2;
+
+ const float value0 = lhsPtr[loc0];
+ const float value1 = lhsPtr[loc1];
+ const float value2 = lhsPtr[loc2];
+
+ temp[loc0] = (value0 * rhsPtr[0]) +
+ (value1 * rhsPtr[3]) +
+ (value2 * rhsPtr[6]);
+
+ temp[loc1] = (value0 * rhsPtr[1]) +
+ (value1 * rhsPtr[4]) +
+ (value2 * rhsPtr[7]);
+
+ temp[loc2] = (value0 * rhsPtr[2]) +
+ (value1 * rhsPtr[5]) +
+ (value2 * rhsPtr[8]);
+ }
+}
+
+void MultiplyAssign(Dali::Matrix3& result, const Dali::Matrix3& rhs)
+{
+ float* lhsPtr = result.AsFloat();
+ const float* rhsPtr = rhs.AsFloat();
+ float* temp = nullptr;
+
+ if(lhsPtr == rhsPtr)
+ {
+ // If rhs is same matrix with result, we need to copy temperal vaules.
+ temp = static_cast<float*>(malloc(NUM_BYTES_IN_MATRIX3));
+ memcpy(temp, rhsPtr, NUM_BYTES_IN_MATRIX3);
+ rhsPtr = temp;
+ }
+
+ // Calculate and store as row major.
+ for(int32_t i = 0; i < 3; i++)
+ {
+ const int32_t loc0 = i;
+ const int32_t loc1 = loc0 + 3;
+ const int32_t loc2 = loc0 + 6;
+
+ const float value0 = lhsPtr[loc0];
+ const float value1 = lhsPtr[loc1];
+ const float value2 = lhsPtr[loc2];
+
+ lhsPtr[loc0] = (value0 * rhsPtr[0]) +
+ (value1 * rhsPtr[1]) +
+ (value2 * rhsPtr[2]);
+
+ lhsPtr[loc1] = (value0 * rhsPtr[3]) +
+ (value1 * rhsPtr[4]) +
+ (value2 * rhsPtr[5]);
+
+ lhsPtr[loc2] = (value0 * rhsPtr[6]) +
+ (value1 * rhsPtr[7]) +
+ (value2 * rhsPtr[8]);
+ }
+
+ if(temp)
+ {
+ // If we allocate temperal memory, we should free it.
+ free(temp);
+ }
+}
+
+} // namespace MatrixUtils
+} // namespace Dali::Internal
--- /dev/null
+#ifndef DALI_INTERNAL_MATRIX_UTILS_H
+#define DALI_INTERNAL_MATRIX_UTILS_H
+
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+class Matrix;
+class Matrix3;
+class Quaternion;
+
+namespace Internal
+{
+namespace MatrixUtils
+{
+// Quaternion
+
+/**
+ * @brief Function to convert from Quaternion to Matrix as float16 array form
+ *
+ * @SINCE_2_1.46
+ * @param[out] result Result stored float16 array. It must have at least 16 * sizeof(float) bytes.
+ * @param[in] rotation Input Quaternion.
+ */
+void ConvertQuaternion(float*& result, const Dali::Quaternion& rotation);
+
+// Matrix
+
+/**
+ * @copydoc Dali::Matrix::Multiply
+ */
+void Multiply(Dali::Matrix& result, const Dali::Matrix& lhs, const Dali::Matrix& rhs);
+
+/**
+ * @copydoc Dali::Matrix::Multiply
+ */
+void Multiply(Dali::Matrix& result, const Dali::Matrix& lhs, const Dali::Quaternion& rhs);
+
+/**
+ * @brief Function to multiply projection matrix and store the result onto third.
+ *
+ * This API assume that projection is Projection Matrix which top/bottom/left/right is symmetrical.
+ *
+ * Perspective matrix only has 0, 5, 10, 11, 14 (14 is const value, 1.0f).
+ * Orthographic matrix only has 0, 5, 10, 14, 15 (15 is const value, 1.0f).
+ * If window rotated, we use 1, 4 index instead of 0, 5.
+ * So we only need 8 values to multiplication.
+ *
+ * Use this method in time critical path as it does not require temporaries.
+ *
+ * result = projection * lhs
+ *
+ * @SINCE_2_1.46
+ * @param[out] result Result of the multiplication
+ * @param[in] lhs Matrix, this cannot be same matrix as result
+ * @param[in] projection Projection Matrix, this can be same matrix as result
+ */
+void MultiplyProjectionMatrix(Dali::Matrix& result, const Dali::Matrix& lhs, const Dali::Matrix& projection);
+
+/**
+ * @brief Function to multiply two matrices and store the result onto first one.
+ *
+ * result = result * rhs
+ * result *= rhs
+ *
+ * @note This method might copy data internally.
+ *
+ * @SINCE_2_1.46
+ * @param[in,out] result Result of the multiplication
+ * @param[in] rhs Matrix, this can be same matrix as result
+ */
+void MultiplyAssign(Dali::Matrix& result, const Dali::Matrix& rhs);
+
+// Matrix3
+
+/**
+ * @copydoc Dali::Matrix3::Multiply
+ */
+void Multiply(Dali::Matrix3& result, const Dali::Matrix3& lhs, const Dali::Matrix3& rhs);
+
+/**
+ * @brief Function to multiply two matrices and store the result onto first one.
+ *
+ * result = result * rhs
+ * result *= rhs
+ *
+ * @note This method might copy data internally.
+ *
+ * @SINCE_2_1.46
+ * @param[in,out] result Result of the multiplication
+ * @param[in] rhs Matrix, this can be same matrix as result
+ */
+void MultiplyAssign(Dali::Matrix3& result, const Dali::Matrix3& rhs);
+
+} // namespace MatrixUtils
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_MATH_UTILS_H
* limitations under the License.
*/
+#include <dali/internal/common/matrix-utils.h>
#include <dali/internal/event/actors/actor-coords.h>
#include <dali/internal/event/common/event-thread-services.h>
#include <dali/internal/event/common/projection.h>
{
// Get the ModelView matrix
Matrix modelView;
- Matrix::Multiply(modelView, worldMatrix, viewMatrix);
+ MatrixUtils::Multiply(modelView, worldMatrix, viewMatrix);
// Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
Matrix invertedMvp(false /*don't init*/);
- Matrix::Multiply(invertedMvp, modelView, projectionMatrix);
+ MatrixUtils::Multiply(invertedMvp, modelView, projectionMatrix);
bool success = invertedMvp.Invert();
// Convert to GL coordinates
//Update the world matrix
Matrix tempMatrix;
- Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
+ MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix);
worldMatrix = tempMatrix;
}
else
{
localMatrix.SetTransformComponents(localScale, localOrientation, Vector3::ZERO);
Matrix tempMatrix;
- Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
+ MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix);
worldMatrix = tempMatrix;
worldMatrix.SetTranslation(actorPosition + centerPosition);
}
localPosition = actorPosition + centerPosition + (parentOrigin - Vector3(0.5f, 0.5f, 0.5f)) * parentSize;
localMatrix.SetTransformComponents(localScale, localOrientation, localPosition);
Matrix tempMatrix;
- Matrix::Multiply(tempMatrix, localMatrix, worldMatrix);
+ MatrixUtils::Multiply(tempMatrix, localMatrix, worldMatrix);
worldMatrix = tempMatrix;
}
}
// INTERNAL INCLUDES
#include <dali/devel-api/actors/camera-actor-devel.h>
+#include <dali/internal/common/matrix-utils.h>
#include <dali/internal/event/common/projection.h>
#include <dali/internal/event/common/property-helper.h>
#include <dali/internal/event/common/thread-local-storage.h>
// Transforms the touch point from the screen reference system to the world reference system.
Matrix invViewProjection(false); // Don't initialize.
- Matrix::Multiply(invViewProjection, viewMatrix, projectionMatrix);
+ MatrixUtils::Multiply(invViewProjection, viewMatrix, projectionMatrix);
if(!invViewProjection.Invert())
{
DALI_ASSERT_DEBUG(false);
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
// INTERNAL INCLUDES
#include <dali/integration-api/debug.h>
+#include <dali/internal/common/matrix-utils.h>
#include <dali/public-api/math/math-utils.h>
#include <dali/public-api/math/matrix.h>
#include <dali/public-api/math/rect.h>
Vector4& objectPos)
{
Matrix invertedMvp(false); // Don't initialize.
- Matrix::Multiply(invertedMvp, modelView, projection);
+ MatrixUtils::Multiply(invertedMvp, modelView, projection);
if(invertedMvp.Invert())
{
bool ok = false;
Matrix Mvp(false); // Don't initialize.
- Matrix::Multiply(Mvp, modelView, projection);
+ MatrixUtils::Multiply(Mvp, modelView, projection);
Vector4 p = Mvp * position;
${internal_src_dir}/common/blending-options.cpp
${internal_src_dir}/common/core-impl.cpp
${internal_src_dir}/common/math.cpp
+ ${internal_src_dir}/common/matrix-utils.cpp
${internal_src_dir}/common/message-buffer.cpp
${internal_src_dir}/common/mutex-trace.cpp
${internal_src_dir}/common/image-sampler.cpp
#include <dali/graphics-api/graphics-types.h>
#include <dali/integration-api/debug.h>
#include <dali/internal/common/image-sampler.h>
+#include <dali/internal/common/matrix-utils.h>
#include <dali/internal/event/rendering/texture-impl.h>
#include <dali/internal/render/common/render-instruction.h>
#include <dali/internal/render/data-providers/node-data-provider.h>
mRenderCallbackInput.size = size;
mRenderCallbackInput.projection = projectionMatrix;
- Matrix::Multiply(mRenderCallbackInput.mvp, modelViewMatrix, projectionMatrix);
+ MatrixUtils::Multiply(mRenderCallbackInput.mvp, modelViewMatrix, projectionMatrix);
// submit draw
commandBuffer.DrawNative(&info);
if(mvpUniformInfo && !mvpUniformInfo->name.empty())
{
Matrix modelViewProjectionMatrix(false);
- Matrix::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
+ MatrixUtils::Multiply(modelViewProjectionMatrix, modelViewMatrix, projectionMatrix);
WriteDefaultUniform(mvpUniformInfo, *uboView, modelViewProjectionMatrix);
}
#define DALI_INTERNAL_SCENE_GRAPH_ANIMATABLE_PROPERTY_H
/*
- * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <limits>
// INTERNAL INCLUDES
+#include <dali/internal/common/matrix-utils.h>
#include <dali/internal/common/message.h>
#include <dali/internal/event/common/event-thread-services.h>
#include <dali/internal/event/common/property-input-impl.h>
}
public:
-
/**
* Mark the property as dirty so that it will be reset to the base value in the next two frames.
*/
void SetRelative(BufferIndex bufferIndex, const Matrix& delta)
{
Matrix temp;
- Matrix::Multiply(temp, mValue[bufferIndex], delta);
+ MatrixUtils::Multiply(temp, mValue[bufferIndex], delta);
mValue[bufferIndex] = temp;
OnSet();
void BakeRelative(BufferIndex bufferIndex, const Matrix& delta)
{
Matrix temp;
- Matrix::Multiply(temp, mValue[bufferIndex], delta);
+ MatrixUtils::Multiply(temp, mValue[bufferIndex], delta);
mValue[bufferIndex] = temp;
mBaseValue = temp;
void SetRelative(BufferIndex bufferIndex, const Matrix3& delta)
{
Matrix3 temp;
- Matrix3::Multiply(temp, mValue[bufferIndex], delta);
+ MatrixUtils::Multiply(temp, mValue[bufferIndex], delta);
mValue[bufferIndex] = temp;
OnSet();
}
void BakeRelative(BufferIndex bufferIndex, const Matrix3& delta)
{
Matrix3 temp;
- Matrix3::Multiply(temp, mValue[bufferIndex], delta);
+ MatrixUtils::Multiply(temp, mValue[bufferIndex], delta);
mValue[bufferIndex] = temp;
mBaseValue = temp;
// INTERNAL INCLUDES
#include <dali/integration-api/debug.h>
+#include <dali/internal/common/matrix-utils.h>
#include <dali/internal/event/actors/layer-impl.h> // for the default sorting function
#include <dali/internal/render/common/render-instruction-container.h>
#include <dali/internal/render/common/render-instruction.h>
if(size.LengthSquared() > Math::MACHINE_EPSILON_1000)
{
- Matrix::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix);
+ MatrixUtils::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix);
nodeModelViewMatrixSet = true;
// Assume actors are at z=0, compute AABB in view space & test rect intersection
if(!nodeModelViewMatrixSet)
{
- Matrix::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix);
+ MatrixUtils::Multiply(nodeModelViewMatrix, nodeWorldMatrix, viewMatrix);
}
item.mModelViewMatrix = nodeModelViewMatrix;
//INTERNAL INCLUDES
#include <dali/internal/common/math.h>
+#include <dali/internal/common/matrix-utils.h>
#include <dali/public-api/common/constants.h>
namespace Dali
}
//Update the world matrix
- Matrix::Multiply(mWorld[i], mLocal[i], mWorld[parentIndex]);
+ MatrixUtils::Multiply(mWorld[i], mLocal[i], mWorld[parentIndex]);
}
else
{
//Don't inherit position
CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i], mSize[i], half, topLeft);
mLocal[i].SetTransformComponents(localScale, localOrientation, Vector3::ZERO);
- Matrix::Multiply(mWorld[i], mLocal[i], parentMatrix);
+ MatrixUtils::Multiply(mWorld[i], mLocal[i], parentMatrix);
mWorld[i].SetTranslation(mTxComponentAnimatable[i].mPosition + centerPosition);
}
else
CalculateCenterPosition(centerPosition, mTxComponentStatic[i], mTxComponentAnimatable[i], mSize[i], half, topLeft);
localPosition = mTxComponentAnimatable[i].mPosition + centerPosition + (mTxComponentStatic[i].mParentOrigin - half) * mSize[parentIndex];
mLocal[i].SetTransformComponents(localScale, localOrientation, localPosition);
- Matrix::Multiply(mWorld[i], mLocal[i], parentMatrix);
+ MatrixUtils::Multiply(mWorld[i], mLocal[i], parentMatrix);
}
mLocalMatrixDirty[i] = mComponentDirty[i] || (localMatrix != mLocal[i]);
// INTERNAL INCLUDES
#include <dali/integration-api/debug.h>
+#include <dali/internal/common/matrix-utils.h>
#include <dali/internal/common/memory-pool-object-allocator.h>
#include <dali/internal/update/nodes/node.h>
#include <dali/public-api/common/dali-common.h>
if(viewUpdateCount > COPY_PREVIOUS_MATRIX || projectionUpdateCount > COPY_PREVIOUS_MATRIX)
{
// either has actually changed so recalculate
- Matrix::Multiply(mInverseViewProjection[updateBufferIndex], mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
+ MatrixUtils::Multiply(mInverseViewProjection[updateBufferIndex], mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
UpdateFrustum(updateBufferIndex);
// ignore the error, if the view projection is incorrect (non inversible) then you will have tough times anyways
Matrix& viewMatrix = mViewMatrix.Get(updateBufferIndex);
Matrix oldViewMatrix(viewMatrix);
- Matrix::Multiply(viewMatrix, oldViewMatrix, mReflectionMtx);
+ MatrixUtils::Multiply(viewMatrix, oldViewMatrix, mReflectionMtx);
}
viewMatrix.Invert();
Matrix oldViewMatrix(viewMatrix);
Matrix tmp;
tmp.SetIdentityAndScale(Vector3(-1.0, 1.0, 1.0));
- Matrix::Multiply(viewMatrix, oldViewMatrix, tmp);
+ MatrixUtils::Multiply(viewMatrix, oldViewMatrix, tmp);
mReflectionEye = positionNew;
mUseReflectionClip = true;
{
// Extract the clip matrix planes
Matrix clipMatrix;
- Matrix::Multiply(clipMatrix, mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
+ MatrixUtils::Multiply(clipMatrix, mViewMatrix[updateBufferIndex], mProjectionMatrix[updateBufferIndex]);
const float* cm = clipMatrix.AsFloat();
FrustumPlanes& planes = mFrustum[updateBufferIndex];
matZ.SetIdentity();
float* vZ = matZ.AsFloat();
vZ[10] = -vZ[10];
- Matrix::Multiply(projectionMatrix, projectionMatrix, matZ);
+ MatrixUtils::Multiply(projectionMatrix, projectionMatrix, matZ);
}
break;
}
rotation.SetIdentity();
rotation.SetTransformComponents(Vector3(1.0f, 1.0f, 1.0f), rotationAngle, Vector3(0.0f, 0.0f, 0.0f));
- Matrix::Multiply(finalProjection, mProjectionMatrix.Get(updateBufferIndex), rotation);
+ MatrixUtils::Multiply(finalProjection, mProjectionMatrix.Get(updateBufferIndex), rotation);
}
--mUpdateProjectionFlag;
}
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <ostream>
// INTERNAL INCLUDES
+#include <dali/internal/common/matrix-utils.h>
#include <dali/internal/render/common/performance-monitor.h>
#include <dali/public-api/common/dali-common.h>
#include <dali/public-api/math/math-utils.h>
const uint32_t ROW1_OFFSET(4);
const uint32_t ROW2_OFFSET(8);
const uint32_t ROW3_OFFSET(12);
-
-/**
- * Helper to convert to Quaternion to float16 array
- */
-void Convert(float*& m, const Dali::Quaternion& rotation)
-{
- const float xx = rotation.mVector.x * rotation.mVector.x;
- const float yy = rotation.mVector.y * rotation.mVector.y;
- const float zz = rotation.mVector.z * rotation.mVector.z;
- const float xy = rotation.mVector.x * rotation.mVector.y;
- const float xz = rotation.mVector.x * rotation.mVector.z;
- const float wx = rotation.mVector.w * rotation.mVector.x;
- const float wy = rotation.mVector.w * rotation.mVector.y;
- const float wz = rotation.mVector.w * rotation.mVector.z;
- const float yz = rotation.mVector.y * rotation.mVector.z;
-
- // clang-format off
- m[0] = 1.0f - 2.0f * (yy + zz);
- m[1] = 2.0f * (xy + wz);
- m[2] = 2.0f * (xz - wy);
- m[3] = 0.0f;
-
- m[4] = 2.0f * (xy - wz);
- m[5] = 1.0f - 2.0f * (xx + zz);
- m[6] = 2.0f * (yz + wx);
- m[7] = 0.0f;
-
- m[8] = 2.0f * (xz + wy);
- m[9] = 2.0f * (yz - wx);
- m[10]= 1.0f - 2.0f * (xx + yy);
- m[11]= 0.0f;
-
- m[12]= 0.0f;
- m[13]= 0.0f;
- m[14]= 0.0f;
- m[15]= 1.0f;
- // clang-format on
-}
} // namespace
namespace Dali
MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY, 18);
float* matrixPtr = &mMatrix[0];
- Convert(matrixPtr, rotation);
+ Internal::MatrixUtils::ConvertQuaternion(matrixPtr, rotation);
}
Matrix::Matrix(const Matrix& matrix)
void Matrix::Multiply(Matrix& result, const Matrix& lhs, const Matrix& rhs)
{
- MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
- MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY, 64); // 64 = 16*4
-
- float* temp = result.AsFloat();
- const float* rhsPtr = rhs.AsFloat();
- const float* lhsPtr = lhs.AsFloat();
-
-#ifndef __ARM_NEON__
-
- for(int32_t i = 0; i < 4; i++)
- {
- // i<<2 gives the first vector / column
- int32_t loc = i << 2;
- int32_t loc1 = loc + 1;
- int32_t loc2 = loc + 2;
- int32_t loc3 = loc + 3;
- float value0 = lhsPtr[loc];
- float value1 = lhsPtr[loc1];
- float value2 = lhsPtr[loc2];
- float value3 = lhsPtr[loc3];
-
- temp[loc] = (value0 * rhsPtr[0]) +
- (value1 * rhsPtr[4]) +
- (value2 * rhsPtr[8]) +
- (value3 * rhsPtr[12]);
-
- temp[loc1] = (value0 * rhsPtr[1]) +
- (value1 * rhsPtr[5]) +
- (value2 * rhsPtr[9]) +
- (value3 * rhsPtr[13]);
-
- temp[loc2] = (value0 * rhsPtr[2]) +
- (value1 * rhsPtr[6]) +
- (value2 * rhsPtr[10]) +
- (value3 * rhsPtr[14]);
-
- temp[loc3] = (value0 * rhsPtr[3]) +
- (value1 * rhsPtr[7]) +
- (value2 * rhsPtr[11]) +
- (value3 * rhsPtr[15]);
- }
-
-#else
-
- // 64 32bit registers,
- // aliased to
- // d = 64 bit double-word d0 -d31
- // q =128 bit quad-word q0 -q15 (enough to handle a column of 4 floats in a matrix)
- // e.g. q0 = d0 and d1
-
- // load and stores interleaved as NEON can load and store while calculating
- asm volatile(
- "VLDM %1, {q0-q3} \n\t" // load matrix 1 (lhsPtr) q[0..q3]
- "VLDM %0, {q8-q11} \n\t" // load matrix 2 (rhsPtr) q[q8-q11]
- "VMUL.F32 q12, q8, d0[0] \n\t" // column 0 = rhsPtr[0..3] * lhsPtr[0..3]
- "VMUL.F32 q13, q8, d2[0] \n\t" // column 1 = rhsPtr[0..3] * lhsPtr[4..7]
- "VMUL.F32 q14, q8, d4[0] \n\t" // column 2 = rhsPtr[0..3] * lhsPtr[8..11]
- "VMUL.F32 q15, q8, d6[0] \n\t" // column 3 = rhsPtr[0..3] * lhsPtr[12..15]
-
- "VMLA.F32 q12, q9, d0[1] \n\t" // column 0 += rhsPtr[4..7] * lhsPtr[0..3]
- "VMLA.F32 q13, q9, d2[1] \n\t" // column 1 += rhsPtr[4..7] * lhsPtr[4..7]
- "VMLA.F32 q14, q9, d4[1] \n\t" // column 2 += rhsPtr[4..7] * lhsPtr[8..11]
- "VMLA.F32 q15, q9, d6[1] \n\t" // column 3 += rhsPtr[4..7] * lhsPtr[12..15]
-
- "VMLA.F32 q12, q10, d1[0] \n\t" // column 0 += rhsPtr[8..11] * lhsPtr[0..3]
- "VMLA.F32 q13, q10, d3[0] \n\t" // column 1 += rhsPtr[8..11] * lhsPtr[4..7]
- "VMLA.F32 q14, q10, d5[0] \n\t" // column 2 += rhsPtr[8..11] * lhsPtr[8..11]
- "VMLA.F32 q15, q10, d7[0] \n\t" // column 3 += rhsPtr[8..11] * lhsPtr[12..15]
-
- "VMLA.F32 q12, q11, d1[1] \n\t" // column 0 += rhsPtr[12..15] * lhsPtr[0..3]
- "VMLA.F32 q13, q11, d3[1] \n\t" // column 1 += rhsPtr[12..15] * lhsPtr[4..7]
- "VMLA.F32 q14, q11, d5[1] \n\t" // column 2 += rhsPtr[12..15] * lhsPtr[8..11]
- "VMLA.F32 q15, q11, d7[1] \n\t" // column 3 += rhsPtr[12..15] * lhsPtr[12..15]
- "VSTM %2, {q12-q15} \n\t" // store entire output matrix.
- : "+r"(rhsPtr), "+r"(lhsPtr), "+r"(temp)
- :
- : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory");
-
-#endif
+ Internal::MatrixUtils::Multiply(result, lhs, rhs);
}
void Matrix::Multiply(Matrix& result, const Matrix& lhs, const Quaternion& rhs)
{
- MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
- MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY, 54); // 54 = 36+18
-
- float matrix[16];
- float* rhsPtr = &matrix[0];
- Convert(rhsPtr, rhs);
-
- // quaternion contains just rotation so it really only needs 3x3 matrix
-
- float* temp = result.AsFloat();
- const float* lhsPtr = lhs.AsFloat();
-
-#ifndef __ARM_NEON__
-
- for(int32_t i = 0; i < 4; i++)
- {
- // i<<2 gives the first vector / column
- int32_t loc = i << 2;
- int32_t loc1 = loc + 1;
- int32_t loc2 = loc + 2;
- int32_t loc3 = loc + 3;
- float value0 = lhsPtr[loc];
- float value1 = lhsPtr[loc1];
- float value2 = lhsPtr[loc2];
- float value3 = lhsPtr[loc3];
-
- temp[loc] = (value0 * rhsPtr[0]) +
- (value1 * rhsPtr[4]) +
- (value2 * rhsPtr[8]) +
- (0.0f); //value3 * rhsPtr[12] is 0.0f
-
- temp[loc1] = (value0 * rhsPtr[1]) +
- (value1 * rhsPtr[5]) +
- (value2 * rhsPtr[9]) +
- (0.0f); //value3 * rhsPtr[13] is 0.0f
-
- temp[loc2] = (value0 * rhsPtr[2]) +
- (value1 * rhsPtr[6]) +
- (value2 * rhsPtr[10]) +
- (0.0f); //value3 * rhsPtr[14] is 0.0f
-
- temp[loc3] = (0.0f) + //value0 * rhsPtr[3] is 0.0f
- (0.0f) + //value1 * rhsPtr[7] is 0.0f
- (0.0f) + //value2 * rhsPtr[11] is 0.0f
- (value3); // rhsPtr[15] is 1.0f
- }
-
-#else
+ Internal::MatrixUtils::Multiply(result, lhs, rhs);
+}
- // 64 32bit registers,
- // aliased to
- // d = 64 bit double-word d0 -d31
- // q =128 bit quad-word q0 -q15 (enough to handle a column of 4 floats in a matrix)
- // e.g. q0 = d0 and d1
- // load and stores interleaved as NEON can load and store while calculating
- asm volatile(
- "VLDM %1, {q4-q6} \n\t" // load matrix 1 (lhsPtr)
- "VLD1.F32 {q7}, [%2]! \n\t" // load matrix 2 (rhsPtr) [0..3]
- "VMUL.F32 q0, q7, d8[0] \n\t" // column 0 = rhsPtr[0..3] * lhsPtr[0..3]
- "VMUL.F32 q1, q7, d10[0] \n\t" // column 1 = rhsPtr[0..3] * lhsPtr[4..7]
- "VMUL.F32 q2, q7, d12[0] \n\t" // column 2 = rhsPtr[0..3] * lhsPtr[8..11]
- "VLD1.F32 {q7}, [%2]! \n\t" // load matrix 2 (rhsPtr) [4..7]
- "VMLA.F32 q0, q7, d8[1] \n\t" // column 0+= rhsPtr[4..7] * lhsPtr[0..3]
- "VMLA.F32 q1, q7, d10[1] \n\t" // column 1+= rhsPtr[4..7] * lhsPtr[4..7]
- "VMLA.F32 q2, q7, d12[1] \n\t" // column 2+= rhsPtr[4..7] * lhsPtr[8..11]
- "VLD1.F32 {q7}, [%2]! \n\t" // load matrix 2 (rhsPtr) [8..11]
- "VMLA.F32 q0, q7, d9[0] \n\t" // column 0+= rhsPtr[8..11] * lhsPtr[0..3]
- "VMLA.F32 q1, q7, d11[0] \n\t" // column 1+= rhsPtr[8..11] * lhsPtr[4..7]
- "VMLA.F32 q2, q7, d13[0] \n\t" // column 2+= rhsPtr[8..11] * lhsPtr[8..11]
- "VSTM %0, {q0-q2} \n\t" // store entire output matrix.
- :
- : "r"(temp), "r"(lhsPtr), "r"(rhsPtr)
- : "%r0", "%q0", "%q1", "%q2", "%q4", "%q5", "%q6", "%q7", "memory");
+Matrix Matrix::operator*(const Matrix& rhs) const
+{
+ Matrix result(false);
+ Internal::MatrixUtils::Multiply(result, rhs, *this);
+ return result;
+}
- temp[12] = 0.0f;
- temp[13] = 0.0f;
- temp[14] = 0.0f;
- temp[15] = 1.0f;
-#endif
+Matrix& Matrix::operator*=(const Matrix& rhs)
+{
+ Internal::MatrixUtils::MultiplyAssign(*this, rhs);
+ return *this;
}
Vector4 Matrix::operator*(const Vector4& rhs) const
#define DALI_MATRIX_H
/*
- * Copyright (c) 2020 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
{
return mMatrix;
}
-
/**
* @brief Function to multiply two matrices and store the result onto third.
*
* @param[in] rhs The Matrix to multiply this by
* @return A Matrix containing the result
*/
- Matrix operator*(const Matrix& rhs) const
- {
- Matrix result(false);
- Multiply(result, rhs, *this);
- return result;
- }
+ Matrix operator*(const Matrix& rhs) const;
+
+ /**
+ * @brief Multiplication assignment operator.
+ *
+ * This Matrix *= rhs
+ *
+ * @note It makes some memory allocate & copy internally.
+ *
+ * @SINCE_2_1.46
+ * @param[in] rhs The Matrix to multiply this by
+ * @return Itself
+ */
+ Matrix& operator*=(const Matrix& rhs);
/**
* @brief The multiplication operator.
#include <ostream>
// INTERNAL INCLUDES
+#include <dali/internal/common/matrix-utils.h>
#include <dali/public-api/math/math-utils.h>
#define S00 0
void Matrix3::Multiply(Matrix3& result, const Matrix3& lhs, const Matrix3& rhs)
{
- float* temp = result.AsFloat();
- const float* rhsPtr = rhs.AsFloat();
- const float* lhsPtr = lhs.AsFloat();
+ Internal::MatrixUtils::Multiply(result, lhs, rhs);
+}
- for(int32_t i = 0; i < 3; i++)
- {
- int32_t loc = i * 3;
- int32_t loc1 = loc + 1;
- int32_t loc2 = loc + 2;
-
- float value0 = lhsPtr[loc];
- float value1 = lhsPtr[loc1];
- float value2 = lhsPtr[loc2];
- temp[loc] = (value0 * rhsPtr[0]) +
- (value1 * rhsPtr[3]) +
- (value2 * rhsPtr[6]);
-
- temp[loc1] = (value0 * rhsPtr[1]) +
- (value1 * rhsPtr[4]) +
- (value2 * rhsPtr[7]);
-
- temp[loc2] = (value0 * rhsPtr[2]) +
- (value1 * rhsPtr[5]) +
- (value2 * rhsPtr[8]);
- }
+Matrix3 Matrix3::operator*(const Matrix3& rhs) const
+{
+ Matrix3 result;
+ Internal::MatrixUtils::Multiply(result, rhs, *this);
+ return result;
+}
+
+Matrix3& Matrix3::operator*=(const Matrix3& rhs)
+{
+ Internal::MatrixUtils::MultiplyAssign(*this, rhs);
+ return *this;
}
Vector3 Matrix3::operator*(const Vector3& rhs) const
* @param[in] rhs The Matrix to multiply this by
* @return A Matrix containing the result
*/
- Matrix3 operator*(const Matrix3& rhs) const
- {
- Matrix3 result;
- Multiply(result, rhs, *this);
- return result;
- }
+ Matrix3 operator*(const Matrix3& rhs) const;
+
+ /**
+ * @brief Multiplication assignment operator.
+ *
+ * This Matrix *= rhs
+ *
+ * @note It makes some memory allocate & copy internally.
+ *
+ * @SINCE_2_1.46
+ * @param[in] rhs The Matrix to multiply this by
+ * @return Itself
+ */
+ Matrix3& operator*=(const Matrix3& rhs);
/**
* @brief The multiplication operator.