Browse Source

Math: removed integer/float RectangularMatrix multiplication and division.

We would need to duplicate all the functionality found in Vector, which
I don't think is needed at all. If anyone needs to do this, it is
possible to "linearize" the matrix into long vector and do the
operations on it.

Also updated subclass operator implementation, added tests for it, both
for proper returned value and proper result type.
pull/23/head
Vladimír Vondruš 13 years ago
parent
commit
78417dfefa
  1. 25
      src/Math/Matrix.h
  2. 4
      src/Math/Matrix3.h
  3. 4
      src/Math/Matrix4.h
  4. 93
      src/Math/RectangularMatrix.h
  5. 117
      src/Math/Test/RectangularMatrixTest.cpp

25
src/Math/Matrix.h

@ -180,17 +180,7 @@ template<std::size_t size, class T> class Matrix: public RectangularMatrix<size,
#endif #endif
}; };
#ifndef DOXYGEN_GENERATING_OUTPUT MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(Matrix<size, T>)
template<std::size_t size, class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Matrix<size, T>>::type operator*(U number, const Matrix<size, T>& matrix) {
return number*RectangularMatrix<size, size, T>(matrix);
}
template<std::size_t size, class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Matrix<size, T>>::type operator/(U number, const Matrix<size, T>& matrix) {
return number/RectangularMatrix<size, size, T>(matrix);
}
template<std::size_t size, class T> inline Matrix<size, T> operator*(const Vector<size, T>& vector, const RectangularMatrix<size, 1, T>& matrix) {
return RectangularMatrix<1, size, T>(vector)*matrix;
}
#endif
/** @debugoperator{Magnum::Math::Matrix} */ /** @debugoperator{Magnum::Math::Matrix} */
template<std::size_t size, class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix<size, T>& value) { template<std::size_t size, class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix<size, T>& value) {
@ -198,7 +188,7 @@ template<std::size_t size, class T> inline Corrade::Utility::Debug operator<<(Co
} }
#ifndef DOXYGEN_GENERATING_OUTPUT #ifndef DOXYGEN_GENERATING_OUTPUT
#define MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Type, VectorType, size) \ #define MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(size, Type, VectorType) \
VectorType<T>& operator[](std::size_t col) { \ VectorType<T>& operator[](std::size_t col) { \
return static_cast<VectorType<T>&>(Matrix<size, T>::operator[](col)); \ return static_cast<VectorType<T>&>(Matrix<size, T>::operator[](col)); \
} \ } \
@ -225,17 +215,6 @@ template<std::size_t size, class T> inline Corrade::Utility::Debug operator<<(Co
return Matrix<size, T>::invertedOrthogonal(); \ return Matrix<size, T>::invertedOrthogonal(); \
} }
#define MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Type, size) \
template<class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Type<T>>::type operator*(U number, const Type<T>& matrix) { \
return number*Matrix<size, T>(matrix); \
} \
template<class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, Type<T>>::type operator/(U number, const Type<T>& matrix) { \
return number/Matrix<size, T>(matrix); \
} \
template<class T> inline Type<T> operator*(const Vector<size, T>& vector, const RectangularMatrix<size, 1, T>& matrix) { \
return RectangularMatrix<1, size, T>(vector)*matrix; \
}
namespace Implementation { namespace Implementation {
template<std::size_t size, class T> class MatrixDeterminant { template<std::size_t size, class T> class MatrixDeterminant {

4
src/Math/Matrix3.h

@ -299,10 +299,10 @@ template<class T> class Matrix3: public Matrix<3, T> {
} }
MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(3, 3, Matrix3<T>) MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(3, 3, Matrix3<T>)
MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Matrix3, Vector3, 3) MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(3, Matrix3, Vector3)
}; };
MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Matrix3, 3) MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(3, Matrix3)
/** @debugoperator{Magnum::Math::Matrix3} */ /** @debugoperator{Magnum::Math::Matrix3} */
template<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix3<T>& value) { template<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix3<T>& value) {

4
src/Math/Matrix4.h

@ -367,10 +367,10 @@ template<class T> class Matrix4: public Matrix<4, T> {
} }
MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(4, 4, Matrix4<T>) MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(4, 4, Matrix4<T>)
MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(Matrix4, Vector4, 4) MAGNUM_MATRIX_SUBCLASS_IMPLEMENTATION(4, Matrix4, Vector4)
}; };
MAGNUM_MATRIX_SUBCLASS_OPERATOR_IMPLEMENTATION(Matrix4, 4) MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(4, Matrix4)
/** @debugoperator{Magnum::Math::Matrix4} */ /** @debugoperator{Magnum::Math::Matrix4} */
template<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix4<T>& value) { template<class T> inline Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Matrix4<T>& value) {

93
src/Math/RectangularMatrix.h

@ -271,11 +271,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* \boldsymbol A_j = a \boldsymbol A_j * \boldsymbol A_j = a \boldsymbol A_j
* @f] * @f]
*/ */
#ifndef DOXYGEN_GENERATING_OUTPUT RectangularMatrix<cols, rows, T>& operator*=(T number) {
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>&>::type operator*=(U number) {
#else
template<class U> RectangularMatrix<cols, rows, T>& operator*=(U number) {
#endif
for(std::size_t i = 0; i != cols; ++i) for(std::size_t i = 0; i != cols; ++i)
_data[i] *= number; _data[i] *= number;
@ -285,14 +281,10 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Multiply matrix with number * @brief Multiply matrix with number
* *
* @see operator*=(U), operator*(U, const RectangularMatrix<cols, rows, T>&) * @see operator*=(T), operator*(T, const RectangularMatrix<cols, rows, T>&)
*/ */
#ifndef DOXYGEN_GENERATING_OUTPUT RectangularMatrix<cols, rows, T> operator*(T number) const {
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>>::type operator*(U number) const { return RectangularMatrix<cols, rows, T>(*this) *= number;
#else
template<class U> RectangularMatrix<cols, rows, T> operator*(U number) const {
#endif
return RectangularMatrix<cols, rows, T>(*this)*=number;
} }
/** /**
@ -302,11 +294,7 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
* \boldsymbol A_j = \frac{\boldsymbol A_j} a * \boldsymbol A_j = \frac{\boldsymbol A_j} a
* @f] * @f]
*/ */
#ifndef DOXYGEN_GENERATING_OUTPUT RectangularMatrix<cols, rows, T>& operator/=(T number) {
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>&>::type operator/=(U number) {
#else
template<class U> RectangularMatrix<cols, rows, T>& operator/=(U number) {
#endif
for(std::size_t i = 0; i != cols; ++i) for(std::size_t i = 0; i != cols; ++i)
_data[i] /= number; _data[i] /= number;
@ -316,14 +304,11 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** /**
* @brief Divide matrix with number * @brief Divide matrix with number
* *
* @see operator/=(), operator/(U, const RectangularMatrix<cols, rows, T>&) * @see operator/=(T),
* operator/(T, const RectangularMatrix<cols, rows, T>&)
*/ */
#ifndef DOXYGEN_GENERATING_OUTPUT RectangularMatrix<cols, rows, T> operator/(T number) const {
template<class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>>::type operator/(U number) const { return RectangularMatrix<cols, rows, T>(*this) /= number;
#else
template<class U> RectangularMatrix<cols, rows, T> operator/(U number) const {
#endif
return RectangularMatrix<cols, rows, T>(*this)/=number;
} }
/** /**
@ -385,13 +370,16 @@ template<std::size_t cols, std::size_t rows, class T> class RectangularMatrix {
/** @relates RectangularMatrix /** @relates RectangularMatrix
@brief Multiply number with matrix @brief Multiply number with matrix
Same as RectangularMatrix::operator*(U) const. Same as RectangularMatrix::operator*(T) const.
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> operator*(
template<std::size_t cols, std::size_t rows, class T, class U> inline RectangularMatrix<cols, rows, T> operator*(U number, const RectangularMatrix<cols, rows, T>& matrix) { #ifdef DOXYGEN_GENERATING_OUTPUT
#else T
template<std::size_t cols, std::size_t rows, class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>>::type operator*(U number, const RectangularMatrix<cols, rows, T>& matrix) { #else
#endif typename std::common_type<T>::type
#endif
number, const RectangularMatrix<cols, rows, T>& matrix)
{
return matrix*number; return matrix*number;
} }
@ -401,13 +389,16 @@ template<std::size_t cols, std::size_t rows, class T, class U> inline typename s
The computation is done column-wise. @f[ The computation is done column-wise. @f[
\boldsymbol B_j = \frac a {\boldsymbol A_j} \boldsymbol B_j = \frac a {\boldsymbol A_j}
@f] @f]
@see RectangularMatrix::operator/(U) const @see RectangularMatrix::operator/(T) const
*/ */
#ifdef DOXYGEN_GENERATING_OUTPUT template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> operator/(
template<std::size_t cols, std::size_t rows, class T, class U> inline RectangularMatrix<cols, rows, T> operator/(U number, const RectangularMatrix<cols, rows, T>& matrix) { #ifdef DOXYGEN_GENERATING_OUTPUT
#else T
template<std::size_t cols, std::size_t rows, class T, class U> inline typename std::enable_if<std::is_arithmetic<U>::value, RectangularMatrix<cols, rows, T>>::type operator/(U number, const RectangularMatrix<cols, rows, T>& matrix) { #else
#endif typename std::common_type<T>::type
#endif
number, const RectangularMatrix<cols, rows, T>& matrix)
{
RectangularMatrix<cols, rows, T> out; RectangularMatrix<cols, rows, T> out;
for(std::size_t i = 0; i != cols; ++i) for(std::size_t i = 0; i != cols; ++i)
@ -502,20 +493,42 @@ extern template Corrade::Utility::Debug MAGNUM_EXPORT operator<<(Corrade::Utilit
__VA_ARGS__ operator-(const Math::RectangularMatrix<cols, rows, T>& other) const { \ __VA_ARGS__ operator-(const Math::RectangularMatrix<cols, rows, T>& other) const { \
return Math::RectangularMatrix<cols, rows, T>::operator-(other); \ return Math::RectangularMatrix<cols, rows, T>::operator-(other); \
} \ } \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__&>::type operator*=(U number) { \ __VA_ARGS__& operator*=(T number) { \
Math::RectangularMatrix<cols, rows, T>::operator*=(number); \ Math::RectangularMatrix<cols, rows, T>::operator*=(number); \
return *this; \ return *this; \
} \ } \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__>::type operator*(U number) const { \ __VA_ARGS__ operator*(T number) const { \
return Math::RectangularMatrix<cols, rows, T>::operator*(number); \ return Math::RectangularMatrix<cols, rows, T>::operator*(number); \
} \ } \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__&>::type operator/=(U number) { \ __VA_ARGS__& operator/=(T number) { \
Math::RectangularMatrix<cols, rows, T>::operator/=(number); \ Math::RectangularMatrix<cols, rows, T>::operator/=(number); \
return *this; \ return *this; \
} \ } \
template<class U> typename std::enable_if<std::is_arithmetic<U>::value, __VA_ARGS__>::type operator/(U number) const { \ __VA_ARGS__ operator/(T number) const { \
return Math::RectangularMatrix<cols, rows, T>::operator/(number); \ return Math::RectangularMatrix<cols, rows, T>::operator/(number); \
} }
#define MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(...) \
template<std::size_t size, class T> inline __VA_ARGS__ operator*(typename std::common_type<T>::type number, const __VA_ARGS__& matrix) { \
return number*static_cast<const Math::RectangularMatrix<size, size, T>&>(matrix); \
} \
template<std::size_t size, class T> inline __VA_ARGS__ operator/(typename std::common_type<T>::type number, const __VA_ARGS__& matrix) { \
return number/static_cast<const Math::RectangularMatrix<size, size, T>&>(matrix); \
} \
template<std::size_t size, class T> inline __VA_ARGS__ operator*(const Vector<size, T>& vector, const RectangularMatrix<size, 1, T>& matrix) { \
return Math::RectangularMatrix<1, size, T>(vector)*matrix; \
}
#define MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(size, Type) \
template<class T> inline Type<T> operator*(typename std::common_type<T>::type number, const Type<T>& matrix) { \
return number*static_cast<const Math::RectangularMatrix<size, size, T>&>(matrix); \
} \
template<class T> inline Type<T> operator/(typename std::common_type<T>::type number, const Type<T>& matrix) { \
return number/static_cast<const Math::RectangularMatrix<size, size, T>&>(matrix); \
} \
template<class T> inline Type<T> operator*(const Vector<size, T>& vector, const RectangularMatrix<size, 1, T>& matrix) { \
return Math::RectangularMatrix<1, size, T>(vector)*matrix; \
}
#endif #endif
template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> RectangularMatrix<cols, rows, T>::fromDiagonal(const Vector<DiagonalSize, T>& diagonal) { template<std::size_t cols, std::size_t rows, class T> inline RectangularMatrix<cols, rows, T> RectangularMatrix<cols, rows, T>::fromDiagonal(const Vector<DiagonalSize, T>& diagonal) {

117
src/Math/Test/RectangularMatrixTest.cpp

@ -80,6 +80,9 @@ class RectangularMatrixTest: public Corrade::TestSuite::Tester {
void vector(); void vector();
void subclassTypes();
void subclass();
void debug(); void debug();
void configuration(); void configuration();
}; };
@ -117,6 +120,9 @@ RectangularMatrixTest::RectangularMatrixTest() {
&RectangularMatrixTest::vector, &RectangularMatrixTest::vector,
&RectangularMatrixTest::subclassTypes,
&RectangularMatrixTest::subclass,
&RectangularMatrixTest::debug, &RectangularMatrixTest::debug,
&RectangularMatrixTest::configuration}); &RectangularMatrixTest::configuration});
} }
@ -308,19 +314,12 @@ void RectangularMatrixTest::multiplyDivide() {
CORRADE_COMPARE(-1.5f*matrix, multiplied); CORRADE_COMPARE(-1.5f*matrix, multiplied);
CORRADE_COMPARE(multiplied/-1.5f, matrix); CORRADE_COMPARE(multiplied/-1.5f, matrix);
Math::RectangularMatrix<1, 1, Byte> matrixChar(32);
Math::RectangularMatrix<1, 1, Byte> multipliedChar(-48);
CORRADE_COMPARE(matrixChar*-1.5f, multipliedChar);
CORRADE_COMPARE(multipliedChar/-1.5f, matrixChar);
CORRADE_COMPARE(-1.5f*matrixChar, multipliedChar);
/* Divide vector with number and inverse */ /* Divide vector with number and inverse */
Matrix2 divisor(Vector2( 1.0f, 2.0f), Matrix2 divisor(Vector2( 1.0f, 2.0f),
Vector2(-4.0f, 8.0f)); Vector2(-4.0f, 8.0f));
Matrix2 result(Vector2( 1.0f, 0.5f), Matrix2 result(Vector2( 1.0f, 0.5f),
Vector2(-0.25f, 0.125f)); Vector2(-0.25f, 0.125f));
CORRADE_COMPARE(1.0f/divisor, result); CORRADE_COMPARE(1.0f/divisor, result);
CORRADE_COMPARE(-1550.0f/multipliedChar, matrixChar);
} }
void RectangularMatrixTest::multiply() { void RectangularMatrixTest::multiply() {
@ -394,6 +393,110 @@ void RectangularMatrixTest::vector() {
CORRADE_COMPARE(Matrix4x3i::fromVector(b), a); CORRADE_COMPARE(Matrix4x3i::fromVector(b), a);
} }
template<std::size_t size, class T> class BasicMat: public Math::RectangularMatrix<size, size, T> {
public:
template<class ...U> BasicMat(U&&... args): Math::RectangularMatrix<size, size, T>{std::forward<U>(args)...} {}
MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(size, size, BasicMat<size, T>)
};
MAGNUM_MATRIX_OPERATOR_IMPLEMENTATION(BasicMat<size, T>)
template<class T> class BasicMat2x2: public BasicMat<2, T> {
public:
template<class ...U> BasicMat2x2(U&&... args): BasicMat<2, T>{std::forward<U>(args)...} {}
MAGNUM_RECTANGULARMATRIX_SUBCLASS_IMPLEMENTATION(2, 2, BasicMat2x2<T>)
};
MAGNUM_MATRIXn_OPERATOR_IMPLEMENTATION(2, BasicMat2x2)
typedef BasicMat2x2<Float> Mat2x2;
void RectangularMatrixTest::subclassTypes() {
Float* const data = nullptr;
const Float* const cdata = nullptr;
CORRADE_VERIFY((std::is_same<decltype(Mat2x2::from(data)), Mat2x2&>::value));
CORRADE_VERIFY((std::is_same<decltype(Mat2x2::from(cdata)), const Mat2x2&>::value));
/* Const operators */
const Mat2x2 c;
CORRADE_VERIFY((std::is_same<decltype(-c), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(c + c), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(c*1.0f), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(1.0f*c), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(c/1.0f), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(1.0f/c), Mat2x2>::value));
CORRADE_VERIFY((std::is_same<decltype(Vector2()*Math::RectangularMatrix<2, 1, Float>()), Mat2x2>::value));
/* Assignment operators */
Mat2x2 a;
CORRADE_VERIFY((std::is_same<decltype(a = c), Mat2x2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a += c), Mat2x2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a -= c), Mat2x2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a *= 1.0f), Mat2x2&>::value));
CORRADE_VERIFY((std::is_same<decltype(a /= 1.0f), Mat2x2&>::value));
/* Operators on variable-sized matrix */
const BasicMat<3, Float> c2;
CORRADE_VERIFY((std::is_same<decltype(1.0f*c2), BasicMat<3, Float>>::value));
CORRADE_VERIFY((std::is_same<decltype(1.0f/c2), BasicMat<3, Float>>::value));
CORRADE_VERIFY((std::is_same<decltype(Vector3()*Math::RectangularMatrix<3, 1, Float>()), BasicMat<3, Float>>::value));
}
void RectangularMatrixTest::subclass() {
Float data[] = {1.0f, -2.0f, 3.0f, -4.5f};
CORRADE_COMPARE(Mat2x2::from(data), Mat2x2(Vector2(1.0f, -2.0f),
Vector2(3.0f, -4.5f)));
const Float cdata[] = {1.0f, -2.0f, 3.0f, -4.5f};
CORRADE_COMPARE(Mat2x2::from(cdata), Mat2x2(Vector2(1.0f, -2.0f),
Vector2(3.0f, -4.5f)));
const Mat2x2 a(Vector2(1.0f, -3.0f),
Vector2(-3.0f, 1.0f));
CORRADE_COMPARE(-a, Mat2x2(Vector2(-1.0f, 3.0f),
Vector2(3.0f, -1.0f)));
Mat2x2 b(Vector2(-2.0f, 5.0f),
Vector2(5.0f, -2.0f));
const Mat2x2 bExpected(Vector2(-1.0f, 2.0f),
Vector2(2.0f, -1.0f));
CORRADE_COMPARE(b + a, bExpected);
Mat2x2 c(Vector2(-2.0f, 5.0f),
Vector2(5.0f, -2.0f));
const Mat2x2 cExpected(Vector2(-3.0f, 8.0f),
Vector2(8.0f, -3.0f));
CORRADE_COMPARE(c - a, cExpected);
Mat2x2 d(Vector2(-2.0f, 5.0f),
Vector2(5.0f, -2.0f));
const Mat2x2 dExpected(Vector2(-4.0f, 10.0f),
Vector2(10.0f, -4.0f));
CORRADE_COMPARE(d*2.0f, dExpected);
CORRADE_COMPARE(2.0f*d, dExpected);
Mat2x2 e(Vector2(-2.0f, 5.0f),
Vector2(5.0f, -2.0f));
CORRADE_COMPARE(e/0.5f, dExpected);
CORRADE_COMPARE(2.0f/e, Mat2x2(Vector2(-1.0f, 0.4f),
Vector2(0.4f, -1.0f)));
const Vector2 f(2.0f, 5.0f);
const Math::RectangularMatrix<2, 1, Float> g(3.0f, -1.0f);
CORRADE_COMPARE(f*g, Mat2x2(Vector2(6.0f, 15.0f),
Vector2(-2.0f, -5.0f)));
/* Operators on variable-sized matrix */
const BasicMat<1, Float> h(-2.0f);
CORRADE_COMPARE(2.0f*h, (BasicMat<1, Float>(-4.0f)));
CORRADE_COMPARE(2.0f/h, (BasicMat<1, Float>(-1.0f)));
const Math::Vector<1, Float> i(2.0f);
const Math::RectangularMatrix<1, 1, Float> j(3.0f);
CORRADE_COMPARE(i*j, (BasicMat<1, Float>(6.0f)));
}
void RectangularMatrixTest::debug() { void RectangularMatrixTest::debug() {
Matrix3x4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f), Matrix3x4 m(Vector4(3.0f, 5.0f, 8.0f, 4.0f),
Vector4(4.0f, 4.0f, 7.0f, 3.0f), Vector4(4.0f, 4.0f, 7.0f, 3.0f),

Loading…
Cancel
Save