You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Legacy/CryCommon/Cry_Matrix44.h

875 lines
27 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
// Description : Common matrix class
#ifndef CRYINCLUDE_CRYCOMMON_CRY_MATRIX44_H
#define CRYINCLUDE_CRYCOMMON_CRY_MATRIX44_H
#pragma once
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// struct Matrix44_tpl
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
template<typename F>
struct Matrix44_tpl
{
F m00, m01, m02, m03;
F m10, m11, m12, m13;
F m20, m21, m22, m23;
F m30, m31, m32, m33;
//---------------------------------------------------------------------------------
#if defined(_DEBUG)
ILINE Matrix44_tpl()
{
if constexpr (sizeof(F) == 4)
{
uint32* p = (uint32*)&m00;
p[ 0] = F32NAN;
p[ 1] = F32NAN;
p[ 2] = F32NAN;
p[ 3] = F32NAN;
p[ 4] = F32NAN;
p[ 5] = F32NAN;
p[ 6] = F32NAN;
p[ 7] = F32NAN;
p[ 8] = F32NAN;
p[ 9] = F32NAN;
p[10] = F32NAN;
p[11] = F32NAN;
p[12] = F32NAN;
p[13] = F32NAN;
p[14] = F32NAN;
p[15] = F32NAN;
}
if constexpr (sizeof(F) == 8)
{
uint64* p = (uint64*)&m00;
p[ 0] = F64NAN;
p[ 1] = F64NAN;
p[ 2] = F64NAN;
p[ 3] = F64NAN;
p[ 4] = F64NAN;
p[ 5] = F64NAN;
p[ 6] = F64NAN;
p[ 7] = F64NAN;
p[ 8] = F64NAN;
p[ 9] = F64NAN;
p[10] = F64NAN;
p[11] = F64NAN;
p[12] = F64NAN;
p[13] = F64NAN;
p[14] = F64NAN;
p[15] = F64NAN;
}
}
#else
ILINE Matrix44_tpl(){};
#endif
//initialize with zeros
ILINE Matrix44_tpl(type_zero)
{
m00 = 0;
m01 = 0;
m02 = 0;
m03 = 0;
m10 = 0;
m11 = 0;
m12 = 0;
m13 = 0;
m20 = 0;
m21 = 0;
m22 = 0;
m23 = 0;
m30 = 0;
m31 = 0;
m32 = 0;
m33 = 0;
}
//ASSIGNMENT OPERATOR of identical Matrix44 types.
//The assignment operator has precedence over assignment constructor
//Matrix44 m; m=m44;
ILINE Matrix44_tpl<F>& operator = (const Matrix44_tpl<F>& m)
{
assert(m.IsValid());
m00 = m.m00;
m01 = m.m01;
m02 = m.m02;
m03 = m.m03;
m10 = m.m10;
m11 = m.m11;
m12 = m.m12;
m13 = m.m13;
m20 = m.m20;
m21 = m.m21;
m22 = m.m22;
m23 = m.m23;
m30 = m.m30;
m31 = m.m31;
m32 = m.m32;
m33 = m.m33;
return *this;
}
//--------------------------------------------------------------------
//---- implementation of the constructors ---
//--------------------------------------------------------------------
ILINE Matrix44_tpl<F>(F v00, F v01, F v02, F v03,
F v10, F v11, F v12, F v13,
F v20, F v21, F v22, F v23,
F v30, F v31, F v32, F v33)
{
m00 = v00;
m01 = v01;
m02 = v02;
m03 = v03;
m10 = v10;
m11 = v11;
m12 = v12;
m13 = v13;
m20 = v20;
m21 = v21;
m22 = v22;
m23 = v23;
m30 = v30;
m31 = v31;
m32 = v32;
m33 = v33;
}
//CONSTRUCTOR for different types. It converts a Matrix33 into a Matrix44.
//Matrix44(m33);
ILINE Matrix44_tpl<F>(const Matrix33_tpl<F>&m)
{
assert(m.IsValid());
m00 = m.m00;
m01 = m.m01;
m02 = m.m02;
m03 = 0;
m10 = m.m10;
m11 = m.m11;
m12 = m.m12;
m13 = 0;
m20 = m.m20;
m21 = m.m21;
m22 = m.m22;
m23 = 0;
m30 = 0;
m31 = 0;
m32 = 0;
m33 = 1;
}
//CONSTRUCTOR for different types. It converts a Matrix33 into a Matrix44 and also converts between double/float.
//Matrix44(Matrix33);
template<class F1>
ILINE Matrix44_tpl<F>(const Matrix33_tpl<F1>&m)
{
assert(m.IsValid());
m00 = F(m.m00);
m01 = F(m.m01);
m02 = F(m.m02);
m03 = 0;
m10 = F(m.m10);
m11 = F(m.m11);
m12 = F(m.m12);
m13 = 0;
m20 = F(m.m20);
m21 = F(m.m21);
m22 = F(m.m22);
m23 = 0;
m30 = 0;
m31 = 0;
m32 = 0;
m33 = 1;
}
//CONSTRUCTOR for different types. It converts a Matrix34 into a Matrix44.
//Matrix44(m34);
ILINE Matrix44_tpl<F>(const Matrix34_tpl<F>&m)
{
assert(m.IsValid());
m00 = m.m00;
m01 = m.m01;
m02 = m.m02;
m03 = m.m03;
m10 = m.m10;
m11 = m.m11;
m12 = m.m12;
m13 = m.m13;
m20 = m.m20;
m21 = m.m21;
m22 = m.m22;
m23 = m.m23;
m30 = 0;
m31 = 0;
m32 = 0;
m33 = 1;
}
//CONSTRUCTOR for different types. It converts a Matrix34 into a Matrix44 and also converts between double/float.
//Matrix44(Matrix34);
template<class F1>
ILINE Matrix44_tpl<F>(const Matrix34_tpl<F1>&m)
{
assert(m.IsValid());
m00 = F(m.m00);
m01 = F(m.m01);
m02 = F(m.m02);
m03 = F(m.m03);
m10 = F(m.m10);
m11 = F(m.m11);
m12 = F(m.m12);
m13 = F(m.m13);
m20 = F(m.m20);
m21 = F(m.m21);
m22 = F(m.m22);
m23 = F(m.m23);
m30 = 0;
m31 = 0;
m32 = 0;
m33 = 1;
}
//CONSTRUCTOR for identical types
//Matrix44 m=m44;
ILINE Matrix44_tpl<F>(const Matrix44_tpl<F>&m)
{
assert(m.IsValid());
m00 = m.m00;
m01 = m.m01;
m02 = m.m02;
m03 = m.m03;
m10 = m.m10;
m11 = m.m11;
m12 = m.m12;
m13 = m.m13;
m20 = m.m20;
m21 = m.m21;
m22 = m.m22;
m23 = m.m23;
m30 = m.m30;
m31 = m.m31;
m32 = m.m32;
m33 = m.m33;
}
//CONSTRUCTOR for identical types which converts between double/float
//Matrix44 m=m44r;
//Matrix44r m=m44;
template<class F1>
ILINE Matrix44_tpl<F>(const Matrix44_tpl<F1>&m)
{
assert(m.IsValid());
m00 = F(m.m00);
m01 = F(m.m01);
m02 = F(m.m02);
m03 = F(m.m03);
m10 = F(m.m10);
m11 = F(m.m11);
m12 = F(m.m12);
m13 = F(m.m13);
m20 = F(m.m20);
m21 = F(m.m21);
m22 = F(m.m22);
m23 = F(m.m23);
m30 = F(m.m30);
m31 = F(m.m31);
m32 = F(m.m32);
m33 = F(m.m33);
}
//---------------------------------------------------------------------
//! multiply all m1 matrix's values by f and return the matrix
friend ILINE Matrix44_tpl<F> operator * (const Matrix44_tpl<F>& m, const f32 f)
{
assert(m.IsValid());
Matrix44_tpl<F> r;
r.m00 = m.m00 * f;
r.m01 = m.m01 * f;
r.m02 = m.m02 * f;
r.m03 = m.m03 * f;
r.m10 = m.m10 * f;
r.m11 = m.m11 * f;
r.m12 = m.m12 * f;
r.m13 = m.m13 * f;
r.m20 = m.m20 * f;
r.m21 = m.m21 * f;
r.m22 = m.m22 * f;
r.m23 = m.m23 * f;
r.m30 = m.m30 * f;
r.m31 = m.m31 * f;
r.m32 = m.m32 * f;
r.m33 = m.m33 * f;
return r;
}
//! add all m matrix's values and return the matrix
friend ILINE Matrix44_tpl<F> operator + (const Matrix44_tpl<F>& mm0, const Matrix44_tpl<F>& mm1)
{
assert(mm0.IsValid());
assert(mm1.IsValid());
Matrix44_tpl<F> r;
r.m00 = mm0.m00 + mm1.m00;
r.m01 = mm0.m01 + mm1.m01;
r.m02 = mm0.m02 + mm1.m02;
r.m03 = mm0.m03 + mm1.m03;
r.m10 = mm0.m10 + mm1.m10;
r.m11 = mm0.m11 + mm1.m11;
r.m12 = mm0.m12 + mm1.m12;
r.m13 = mm0.m13 + mm1.m13;
r.m20 = mm0.m20 + mm1.m20;
r.m21 = mm0.m21 + mm1.m21;
r.m22 = mm0.m22 + mm1.m22;
r.m23 = mm0.m23 + mm1.m23;
r.m30 = mm0.m30 + mm1.m30;
r.m31 = mm0.m31 + mm1.m31;
r.m32 = mm0.m32 + mm1.m32;
r.m33 = mm0.m33 + mm1.m33;
return r;
}
ILINE void SetIdentity()
{
m00 = 1;
m01 = 0;
m02 = 0;
m03 = 0;
m10 = 0;
m11 = 1;
m12 = 0;
m13 = 0;
m20 = 0;
m21 = 0;
m22 = 1;
m23 = 0;
m30 = 0;
m31 = 0;
m32 = 0;
m33 = 1;
}
ILINE Matrix44_tpl(type_identity) { SetIdentity(); }
ILINE void Transpose()
{
Matrix44_tpl<F> tmp = *this;
m00 = tmp.m00;
m01 = tmp.m10;
m02 = tmp.m20;
m03 = tmp.m30;
m10 = tmp.m01;
m11 = tmp.m11;
m12 = tmp.m21;
m13 = tmp.m31;
m20 = tmp.m02;
m21 = tmp.m12;
m22 = tmp.m22;
m23 = tmp.m32;
m30 = tmp.m03;
m31 = tmp.m13;
m32 = tmp.m23;
m33 = tmp.m33;
}
ILINE Matrix44_tpl<F> GetTransposed() const
{
Matrix44_tpl<F> tmp;
tmp.m00 = m00;
tmp.m01 = m10;
tmp.m02 = m20;
tmp.m03 = m30;
tmp.m10 = m01;
tmp.m11 = m11;
tmp.m12 = m21;
tmp.m13 = m31;
tmp.m20 = m02;
tmp.m21 = m12;
tmp.m22 = m22;
tmp.m23 = m32;
tmp.m30 = m03;
tmp.m31 = m13;
tmp.m32 = m23;
tmp.m33 = m33;
return tmp;
}
/*!
*
* Calculate a real inversion of a Matrix44.
*
* Uses Cramer's Rule which is faster (branchless) but numerically more unstable
* than other methods like Gaussian Elimination.
*
* Example 1:
* Matrix44 im44; im44.Invert();
*
* Example 2:
* Matrix44 im44 = m33.GetInverted();
*/
void Invert(void)
{
F tmp[12];
Matrix44_tpl<F> m = *this;
// Calculate pairs for first 8 elements (cofactors)
tmp[0] = m.m22 * m.m33;
tmp[1] = m.m32 * m.m23;
tmp[2] = m.m12 * m.m33;
tmp[3] = m.m32 * m.m13;
tmp[4] = m.m12 * m.m23;
tmp[5] = m.m22 * m.m13;
tmp[6] = m.m02 * m.m33;
tmp[7] = m.m32 * m.m03;
tmp[8] = m.m02 * m.m23;
tmp[9] = m.m22 * m.m03;
tmp[10] = m.m02 * m.m13;
tmp[11] = m.m12 * m.m03;
// Calculate first 8 elements (cofactors)
m00 = tmp[0] * m.m11 + tmp[3] * m.m21 + tmp[ 4] * m.m31;
m00 -= tmp[1] * m.m11 + tmp[2] * m.m21 + tmp[ 5] * m.m31;
m01 = tmp[1] * m.m01 + tmp[6] * m.m21 + tmp[ 9] * m.m31;
m01 -= tmp[0] * m.m01 + tmp[7] * m.m21 + tmp[ 8] * m.m31;
m02 = tmp[2] * m.m01 + tmp[7] * m.m11 + tmp[10] * m.m31;
m02 -= tmp[3] * m.m01 + tmp[6] * m.m11 + tmp[11] * m.m31;
m03 = tmp[5] * m.m01 + tmp[8] * m.m11 + tmp[11] * m.m21;
m03 -= tmp[4] * m.m01 + tmp[9] * m.m11 + tmp[10] * m.m21;
m10 = tmp[1] * m.m10 + tmp[2] * m.m20 + tmp[ 5] * m.m30;
m10 -= tmp[0] * m.m10 + tmp[3] * m.m20 + tmp[ 4] * m.m30;
m11 = tmp[0] * m.m00 + tmp[7] * m.m20 + tmp[ 8] * m.m30;
m11 -= tmp[1] * m.m00 + tmp[6] * m.m20 + tmp[ 9] * m.m30;
m12 = tmp[3] * m.m00 + tmp[6] * m.m10 + tmp[11] * m.m30;
m12 -= tmp[2] * m.m00 + tmp[7] * m.m10 + tmp[10] * m.m30;
m13 = tmp[4] * m.m00 + tmp[9] * m.m10 + tmp[10] * m.m20;
m13 -= tmp[5] * m.m00 + tmp[8] * m.m10 + tmp[11] * m.m20;
// Calculate pairs for second 8 elements (cofactors)
tmp[ 0] = m.m20 * m.m31;
tmp[ 1] = m.m30 * m.m21;
tmp[ 2] = m.m10 * m.m31;
tmp[ 3] = m.m30 * m.m11;
tmp[ 4] = m.m10 * m.m21;
tmp[ 5] = m.m20 * m.m11;
tmp[ 6] = m.m00 * m.m31;
tmp[ 7] = m.m30 * m.m01;
tmp[ 8] = m.m00 * m.m21;
tmp[ 9] = m.m20 * m.m01;
tmp[10] = m.m00 * m.m11;
tmp[11] = m.m10 * m.m01;
// Calculate second 8 elements (cofactors)
m20 = tmp[ 0] * m.m13 + tmp[ 3] * m.m23 + tmp[ 4] * m.m33;
m20 -= tmp[ 1] * m.m13 + tmp[ 2] * m.m23 + tmp[ 5] * m.m33;
m21 = tmp[ 1] * m.m03 + tmp[ 6] * m.m23 + tmp[ 9] * m.m33;
m21 -= tmp[ 0] * m.m03 + tmp[ 7] * m.m23 + tmp[ 8] * m.m33;
m22 = tmp[ 2] * m.m03 + tmp[ 7] * m.m13 + tmp[10] * m.m33;
m22 -= tmp[ 3] * m.m03 + tmp[ 6] * m.m13 + tmp[11] * m.m33;
m23 = tmp[ 5] * m.m03 + tmp[ 8] * m.m13 + tmp[11] * m.m23;
m23 -= tmp[ 4] * m.m03 + tmp[ 9] * m.m13 + tmp[10] * m.m23;
m30 = tmp[ 2] * m.m22 + tmp[ 5] * m.m32 + tmp[ 1] * m.m12;
m30 -= tmp[ 4] * m.m32 + tmp[ 0] * m.m12 + tmp[ 3] * m.m22;
m31 = tmp[ 8] * m.m32 + tmp[ 0] * m.m02 + tmp[ 7] * m.m22;
m31 -= tmp[ 6] * m.m22 + tmp[ 9] * m.m32 + tmp[ 1] * m.m02;
m32 = tmp[ 6] * m.m12 + tmp[11] * m.m32 + tmp[ 3] * m.m02;
m32 -= tmp[10] * m.m32 + tmp[ 2] * m.m02 + tmp[ 7] * m.m12;
m33 = tmp[10] * m.m22 + tmp[ 4] * m.m02 + tmp[ 9] * m.m12;
m33 -= tmp[ 8] * m.m12 + tmp[11] * m.m22 + tmp[ 5] * m.m02;
// Calculate determinant
F det = (m.m00 * m00 + m.m10 * m01 + m.m20 * m02 + m.m30 * m03);
//if (fabs_tpl(det)<0.0001f) assert(0);
// Divide the cofactor-matrix by the determinant
F idet = (F)1.0 / det;
m00 *= idet;
m01 *= idet;
m02 *= idet;
m03 *= idet;
m10 *= idet;
m11 *= idet;
m12 *= idet;
m13 *= idet;
m20 *= idet;
m21 *= idet;
m22 *= idet;
m23 *= idet;
m30 *= idet;
m31 *= idet;
m32 *= idet;
m33 *= idet;
}
ILINE Matrix44_tpl<F> GetInverted() const
{
Matrix44_tpl<F> dst = *this;
dst.Invert();
return dst;
}
ILINE f32 Determinant() const
{
//determinant is ambiguous: only the upper-left-submatrix's determinant is calculated
return (m00 * m11 * m22) + (m01 * m12 * m20) + (m02 * m10 * m21) - (m02 * m11 * m20) - (m00 * m12 * m21) - (m01 * m10 * m22);
}
//! transform a vector
ILINE Vec3 TransformVector(const Vec3& b) const
{
assert(b.IsValid());
Vec3 v;
v.x = m00 * b.x + m01 * b.y + m02 * b.z;
v.y = m10 * b.x + m11 * b.y + m12 * b.z;
v.z = m20 * b.x + m21 * b.y + m22 * b.z;
return v;
}
//! transform a point
ILINE Vec3 TransformPoint(const Vec3& b) const
{
assert(b.IsValid());
Vec3 v;
v.x = m00 * b.x + m01 * b.y + m02 * b.z + m03;
v.y = m10 * b.x + m11 * b.y + m12 * b.z + m13;
v.z = m20 * b.x + m21 * b.y + m22 * b.z + m23;
return v;
}
//--------------------------------------------------------------------------------
//---- helper functions to access matrix-members ------------
//--------------------------------------------------------------------------------
ILINE F* GetData() { return &m00; }
ILINE const F* GetData() const { return &m00; }
ILINE F operator () (uint32 i, uint32 j) const { assert ((i < 4) && (j < 4)); F* p_data = (F*)(&m00); return p_data[i * 4 + j]; }
ILINE F& operator () (uint32 i, uint32 j) { assert ((i < 4) && (j < 4)); F* p_data = (F*)(&m00); return p_data[i * 4 + j]; }
ILINE void SetRow(int i, const Vec3_tpl<F>& v) { assert(i < 4); F* p = (F*)(&m00); p[0 + 4 * i] = v.x; p[1 + 4 * i] = v.y; p[2 + 4 * i] = v.z; }
ILINE void SetRow4(int i, const Vec4_tpl<F>& v) { assert(i < 4); F* p = (F*)(&m00); p[0 + 4 * i] = v.x; p[1 + 4 * i] = v.y; p[2 + 4 * i] = v.z; p[3 + 4 * i] = v.w; }
ILINE const Vec3_tpl<F>& GetRow(int i) const { assert(i < 4); return *(const Vec3_tpl<F>*)(&m00 + 4 * i); }
ILINE void SetColumn(int i, const Vec3_tpl<F>& v) { assert(i < 4); F* p = (F*)(&m00); p[i + 4 * 0] = v.x; p[i + 4 * 1] = v.y; p[i + 4 * 2] = v.z; }
ILINE Vec3_tpl<F> GetColumn(int i) const { assert(i < 4); F* p = (F*)(&m00); return Vec3(p[i + 4 * 0], p[i + 4 * 1], p[i + 4 * 2]); }
ILINE Vec4_tpl<F> GetColumn4(int i) const { assert(i < 4); F* p = (F*)(&m00); return Vec4(p[i + 4 * 0], p[i + 4 * 1], p[i + 4 * 2], p[i + 4 * 3]); }
ILINE Vec3 GetTranslation() const { return Vec3(m03, m13, m23); }
ILINE void SetTranslation(const Vec3& t) { m03 = t.x; m13 = t.y; m23 = t.z; }
bool IsValid() const
{
if (!NumberValid(m00))
{
return false;
}
if (!NumberValid(m01))
{
return false;
}
if (!NumberValid(m02))
{
return false;
}
if (!NumberValid(m03))
{
return false;
}
if (!NumberValid(m10))
{
return false;
}
if (!NumberValid(m11))
{
return false;
}
if (!NumberValid(m12))
{
return false;
}
if (!NumberValid(m13))
{
return false;
}
if (!NumberValid(m20))
{
return false;
}
if (!NumberValid(m21))
{
return false;
}
if (!NumberValid(m22))
{
return false;
}
if (!NumberValid(m23))
{
return false;
}
if (!NumberValid(m30))
{
return false;
}
if (!NumberValid(m31))
{
return false;
}
if (!NumberValid(m32))
{
return false;
}
if (!NumberValid(m33))
{
return false;
}
return true;
}
static bool IsEquivalent(const Matrix44_tpl<F>& m0, const Matrix44_tpl<F>& m1, F e = VEC_EPSILON)
{
return (
(fabs_tpl(m0.m00 - m1.m00) <= e) && (fabs_tpl(m0.m01 - m1.m01) <= e) && (fabs_tpl(m0.m02 - m1.m02) <= e) && (fabs_tpl(m0.m03 - m1.m03) <= e) &&
(fabs_tpl(m0.m10 - m1.m10) <= e) && (fabs_tpl(m0.m11 - m1.m11) <= e) && (fabs_tpl(m0.m12 - m1.m12) <= e) && (fabs_tpl(m0.m13 - m1.m13) <= e) &&
(fabs_tpl(m0.m20 - m1.m20) <= e) && (fabs_tpl(m0.m21 - m1.m21) <= e) && (fabs_tpl(m0.m22 - m1.m22) <= e) && (fabs_tpl(m0.m23 - m1.m23) <= e) &&
(fabs_tpl(m0.m30 - m1.m30) <= e) && (fabs_tpl(m0.m31 - m1.m31) <= e) && (fabs_tpl(m0.m32 - m1.m32) <= e) && (fabs_tpl(m0.m33 - m1.m33) <= e)
);
}
AUTO_STRUCT_INFO
};
///////////////////////////////////////////////////////////////////////////////
// Typedefs //
///////////////////////////////////////////////////////////////////////////////
typedef Matrix44_tpl<f32> Matrix44; //always 32 bit
typedef Matrix44_tpl<f64> Matrix44d; //always 64 bit
typedef Matrix44_tpl<real> Matrix44r; //variable float precision. depending on the target system it can be between 32, 64 or 80 bit
typedef _MS_ALIGN(16) Matrix44_tpl<f32> _ALIGN (16) Matrix44A;
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//------------- implementation of Matrix44 ------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
/*!
* Implements the multiplication operator: Matrix44=Matrix44*Matrix33diag
*
* Matrix44 and Matrix33diag are specified in collumn order.
* AxB = operation B followed by operation A.
* This operation takes 12 mults.
*
* Example:
* Matrix33diag diag(1,2,3);
* Matrix44 m44=CreateRotationZ33(3.14192f);
* Matrix44 result=m44*diag;
*/
template<class F1, class F2>
ILINE Matrix44_tpl<F1> operator * (const Matrix44_tpl<F1>& l, const Diag33_tpl<F2>& r)
{
assert(l.IsValid());
assert(r.IsValid());
Matrix44_tpl<F1> m;
m.m00 = l.m00 * r.x;
m.m01 = l.m01 * r.y;
m.m02 = l.m02 * r.z;
m.m03 = l.m03;
m.m10 = l.m10 * r.x;
m.m11 = l.m11 * r.y;
m.m12 = l.m12 * r.z;
m.m13 = l.m13;
m.m20 = l.m20 * r.x;
m.m21 = l.m21 * r.y;
m.m22 = l.m22 * r.z;
m.m23 = l.m23;
m.m30 = l.m30 * r.x;
m.m31 = l.m31 * r.y;
m.m32 = l.m32 * r.z;
m.m33 = l.m33;
return m;
}
template<class F1, class F2>
ILINE Matrix44_tpl<F1>& operator *= (Matrix44_tpl<F1>& l, const Diag33_tpl<F2>& r)
{
assert(l.IsValid());
assert(r.IsValid());
l.m00 *= r.x;
l.m01 *= r.y;
l.m02 *= r.z;
l.m10 *= r.x;
l.m11 *= r.y;
l.m12 *= r.z;
l.m20 *= r.x;
l.m21 *= r.y;
l.m22 *= r.z;
l.m30 *= r.x;
l.m31 *= r.y;
l.m32 *= r.z;
return l;
}
/*!
* Implements the multiplication operator: Matrix44=Matrix44*Matrix33
*
* Matrix44 and Matrix33 are specified in collumn order.
* AxB = rotation B followed by rotation A.
* This operation takes 48 mults and 24 adds.
*
* Example:
* Matrix33 m34=CreateRotationX33(1.94192f);;
* Matrix44 m44=CreateRotationZ33(3.14192f);
* Matrix44 result=m44*m33;
*/
template<class F1, class F2>
ILINE Matrix44_tpl<F1> operator * (const Matrix44_tpl<F1>& l, const Matrix33_tpl<F2>& r)
{
assert(l.IsValid());
assert(r.IsValid());
Matrix44_tpl<F1> m;
m.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20;
m.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20;
m.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20;
m.m30 = l.m30 * r.m00 + l.m31 * r.m10 + l.m32 * r.m20;
m.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21;
m.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21;
m.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21;
m.m31 = l.m30 * r.m01 + l.m31 * r.m11 + l.m32 * r.m21;
m.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22;
m.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22;
m.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22;
m.m32 = l.m30 * r.m02 + l.m31 * r.m12 + l.m32 * r.m22;
m.m03 = l.m03;
m.m13 = l.m13;
m.m23 = l.m23;
m.m33 = l.m33;
return m;
}
/*!
* Implements the multiplication operator: Matrix44=Matrix44*Matrix34
*
* Matrix44 and Matrix34 are specified in collumn order.
* AxB = rotation B followed by rotation A.
* This operation takes 48 mults and 36 adds.
*
* Example:
* Matrix34 m34=CreateRotationX33(1.94192f);;
* Matrix44 m44=CreateRotationZ33(3.14192f);
* Matrix44 result=m44*m34;
*/
template<class F>
ILINE Matrix44_tpl<F> operator * (const Matrix44_tpl<F>& l, const Matrix34_tpl<F>& r)
{
assert(l.IsValid());
assert(r.IsValid());
Matrix44_tpl<F> m;
m.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20;
m.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20;
m.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20;
m.m30 = l.m30 * r.m00 + l.m31 * r.m10 + l.m32 * r.m20;
m.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21;
m.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21;
m.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21;
m.m31 = l.m30 * r.m01 + l.m31 * r.m11 + l.m32 * r.m21;
m.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22;
m.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22;
m.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22;
m.m32 = l.m30 * r.m02 + l.m31 * r.m12 + l.m32 * r.m22;
m.m03 = l.m00 * r.m03 + l.m01 * r.m13 + l.m02 * r.m23 + l.m03;
m.m13 = l.m10 * r.m03 + l.m11 * r.m13 + l.m12 * r.m23 + l.m13;
m.m23 = l.m20 * r.m03 + l.m21 * r.m13 + l.m22 * r.m23 + l.m23;
m.m33 = l.m30 * r.m03 + l.m31 * r.m13 + l.m32 * r.m23 + l.m33;
return m;
}
/*!
* Implements the multiplication operator: Matrix44=Matrix44*Matrix44
*
* Matrix44 and Matrix34 are specified in collumn order.
* AxB = rotation B followed by rotation A.
* This operation takes 48 mults and 36 adds.
*
* Example:
* Matrix44 m44=CreateRotationX33(1.94192f);;
* Matrix44 m44=CreateRotationZ33(3.14192f);
* Matrix44 result=m44*m44;
*/
template<class F1, class F2>
ILINE Matrix44_tpl<F1> operator * (const Matrix44_tpl<F1>& l, const Matrix44_tpl<F2>& r)
{
assert(l.IsValid());
assert(r.IsValid());
Matrix44_tpl<F1> res;
res.m00 = l.m00 * r.m00 + l.m01 * r.m10 + l.m02 * r.m20 + l.m03 * r.m30;
res.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20 + l.m13 * r.m30;
res.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20 + l.m23 * r.m30;
res.m30 = l.m30 * r.m00 + l.m31 * r.m10 + l.m32 * r.m20 + l.m33 * r.m30;
res.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21 + l.m03 * r.m31;
res.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21 + l.m13 * r.m31;
res.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21 + l.m23 * r.m31;
res.m31 = l.m30 * r.m01 + l.m31 * r.m11 + l.m32 * r.m21 + l.m33 * r.m31;
res.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22 + l.m03 * r.m32;
res.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22 + l.m13 * r.m32;
res.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22 + l.m23 * r.m32;
res.m32 = l.m30 * r.m02 + l.m31 * r.m12 + l.m32 * r.m22 + l.m33 * r.m32;
res.m03 = l.m00 * r.m03 + l.m01 * r.m13 + l.m02 * r.m23 + l.m03 * r.m33;
res.m13 = l.m10 * r.m03 + l.m11 * r.m13 + l.m12 * r.m23 + l.m13 * r.m33;
res.m23 = l.m20 * r.m03 + l.m21 * r.m13 + l.m22 * r.m23 + l.m23 * r.m33;
res.m33 = l.m30 * r.m03 + l.m31 * r.m13 + l.m32 * r.m23 + l.m33 * r.m33;
return res;
}
//post-multiply
template<class F1, class F2>
ILINE Vec4_tpl<F1> operator*(const Matrix44_tpl<F2>& m, const Vec4_tpl<F1>& v)
{
assert(m.IsValid());
assert(v.IsValid());
return Vec4_tpl<F1>(v.x * m.m00 + v.y * m.m01 + v.z * m.m02 + v.w * m.m03,
v.x * m.m10 + v.y * m.m11 + v.z * m.m12 + v.w * m.m13,
v.x * m.m20 + v.y * m.m21 + v.z * m.m22 + v.w * m.m23,
v.x * m.m30 + v.y * m.m31 + v.z * m.m32 + v.w * m.m33);
}
//pre-multiply
template<class F1, class F2>
ILINE Vec4_tpl<F1> operator*(const Vec4_tpl<F1>& v, const Matrix44_tpl<F2>& m)
{
assert(m.IsValid());
assert(v.IsValid());
return Vec4_tpl<F1>(v.x * m.m00 + v.y * m.m10 + v.z * m.m20 + v.w * m.m30,
v.x * m.m01 + v.y * m.m11 + v.z * m.m21 + v.w * m.m31,
v.x * m.m02 + v.y * m.m12 + v.z * m.m22 + v.w * m.m32,
v.x * m.m03 + v.y * m.m13 + v.z * m.m23 + v.w * m.m33);
}
#endif // CRYINCLUDE_CRYCOMMON_CRY_MATRIX44_H