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_Matrix34.h

1463 lines
44 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_MATRIX34_H
#define CRYINCLUDE_CRYCOMMON_CRY_MATRIX34_H
#pragma once
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// struct Matrix34_tpl
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
template <typename F>
struct Matrix34_tpl
{
F m00, m01, m02, m03;
F m10, m11, m12, m13;
F m20, m21, m22, m23;
//default constructor
#if defined(_DEBUG)
ILINE Matrix34_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;
}
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;
}
}
#else
ILINE Matrix34_tpl(){};
#endif
//set matrix to Identity
ILINE Matrix34_tpl(type_identity)
{
m00 = 1;
m01 = 0;
m02 = 0;
m03 = 0;
m10 = 0;
m11 = 1;
m12 = 0;
m13 = 0;
m20 = 0;
m21 = 0;
m22 = 1;
m23 = 0;
}
//set matrix to Zero
ILINE Matrix34_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;
}
//ASSIGNMENT OPERATOR of identical Matrix33 types.
//The assignment operator has precedence over assignment constructor
//Matrix34 m; m=m34;
ILINE Matrix34_tpl<F>& operator = (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;
return *this;
}
//--------------------------------------------------------------------
//---- implementation of the constructors ---
//--------------------------------------------------------------------
//CONSTRUCTOR for identical float-types. It initialises a matrix34 with 12 floats.
ILINE Matrix34_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)
{
m00 = v00;
m01 = v01;
m02 = v02;
m03 = v03;
m10 = v10;
m11 = v11;
m12 = v12;
m13 = v13;
m20 = v20;
m21 = v21;
m22 = v22;
m23 = v23;
}
//CONSTRUCTOR for different float-types. It initialises a matrix34 with 12 floats.
template<class F1>
ILINE Matrix34_tpl<F>(F1 v00, F1 v01, F1 v02, F1 v03, F1 v10, F1 v11, F1 v12, F1 v13, F1 v20, F1 v21, F1 v22, F1 v23)
{
m00 = F(v00);
m01 = F(v01);
m02 = F(v02);
m03 = F(v03);
m10 = F(v10);
m11 = F(v11);
m12 = F(v12);
m13 = F(v13);
m20 = F(v20);
m21 = F(v21);
m22 = F(v22);
m23 = F(v23);
}
//CONSTRUCTOR for identical float-types. It converts a Matrix33 into a Matrix34.
//Matrix34(m33);
ILINE Matrix34_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;
}
//CONSTRUCTOR for different float-types. It converts a Matrix33 into a Matrix34 and also converts between double/float.
//Matrix34(Matrix33);
template<class F1>
ILINE Matrix34_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;
}
//CONSTRUCTOR for identical float-types. It converts a Matrix33 with a translation-vector into a Matrix34.
//Matrix34(m33,Vec3(1,2,3));
ILINE Matrix34_tpl<F>(const Matrix33_tpl<F>&m, const Vec3_tpl<F>&t)
{
assert(m.IsValid());
assert(t.IsValid());
m00 = m.m00;
m01 = m.m01;
m02 = m.m02;
m03 = t.x;
m10 = m.m10;
m11 = m.m11;
m12 = m.m12;
m13 = t.y;
m20 = m.m20;
m21 = m.m21;
m22 = m.m22;
m23 = t.z;
}
//CONSTRUCTOR for different float-types. It converts a Matrix33 with a translation-vector into a Matrix34 and also converts between double/float.
//Matrix34(Matrix33r,Vec3d(1,2,3));
template<class F1>
ILINE Matrix34_tpl<F>(const Matrix33_tpl<F1>&m, const Vec3_tpl<F1>&t)
{
assert(m.IsValid());
assert(t.IsValid());
m00 = F(m.m00);
m01 = F(m.m01);
m02 = F(m.m02);
m03 = F(t.x);
m10 = F(m.m10);
m11 = F(m.m11);
m12 = F(m.m12);
m13 = F(t.y);
m20 = F(m.m20);
m21 = F(m.m21);
m22 = F(m.m22);
m23 = F(t.z);
}
//CONSTRUCTOR for identical float types
//Matrix34 m=m34;
ILINE Matrix34_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;
}
//CONSTRUCTOR for different float-types.
//Matrix34 m=m34d;
template<class F1>
ILINE Matrix34_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);
}
//CONSTRUCTOR for identical float-types. It converts a Matrix44 into a Matrix34.
//Needs to be 'explicit' because we loose the translation vector in the conversion process
//Matrix34(m44);
ILINE explicit Matrix34_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;
}
//CONSTRUCTOR for different float types. It converts a Matrix44 into a Matrix34 and converts between double/float.
//Needs to be 'explicit' because we loose the translation vector in the conversion process
//Matrix34(m44r);
template<class F1>
ILINE explicit Matrix34_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);
}
//CONSTRUCTOR for identical float-types. It converts a Quat into a Matrix34.
//Needs to be 'explicit' because we loose float-precision in the conversion process
//Matrix34(QuatT);
explicit ILINE Matrix34_tpl<F>(const Quat_tpl<F>&q)
{
*this = Matrix33_tpl<F>(q);
}
//CONSTRUCTOR for different float-types. It converts a Quat into a Matrix34.
//Needs to be 'explicit' because we loose float-precision in the conversion process
//Matrix34(QuatTd);
template<class F1>
explicit ILINE Matrix34_tpl<F>(const Quat_tpl<F1>&q)
{
*this = Matrix33_tpl<F>(q);
}
//CONSTRUCTOR for identical float-types. It converts a QuatT into a Matrix34.
//Needs to be 'explicit' because we loose float-precision in the conversion process
//Matrix34(QuatT);
explicit ILINE Matrix34_tpl<F>(const QuatT_tpl<F> &q)
{
*this = Matrix34_tpl<F>(Matrix33_tpl<F>(q.q), q.t);
}
//CONSTRUCTOR for different float-types. It converts a QuatT into a Matrix34.
//Needs to be 'explicit' because we loose float-precision in the conversion process
//Matrix34(QuatT);
template<class F1>
ILINE explicit Matrix34_tpl(const QuatT_tpl<F1> q)
{
*this = Matrix34_tpl<F>(Matrix33_tpl<F1>(q.q), q.t);
}
//CONSTRUCTOR for identical float-types. It converts a QuatTS into a Matrix34.
//Needs to be 'explicit' because we loose float-precision in the conversion process
//Matrix34(QuatT);
explicit ILINE Matrix34_tpl<F>(const QuatTS_tpl<F> &q)
{
assert(q.q.IsValid());
Vec3_tpl<F> v2 = q.q.v + q.q.v;
F xx = 1 - v2.x * q.q.v.x;
F yy = v2.y * q.q.v.y;
F xw = v2.x * q.q.w;
F xy = v2.y * q.q.v.x;
F yz = v2.z * q.q.v.y;
F yw = v2.y * q.q.w;
F xz = v2.z * q.q.v.x;
F zz = v2.z * q.q.v.z;
F zw = v2.z * q.q.w;
m00 = (1 - yy - zz) * q.s;
m01 = (xy - zw) * q.s;
m02 = (xz + yw) * q.s;
m03 = q.t.x;
m10 = (xy + zw) * q.s;
m11 = (xx - zz) * q.s;
m12 = (yz - xw) * q.s;
m13 = q.t.y;
m20 = (xz - yw) * q.s;
m21 = (yz + xw) * q.s;
m22 = (xx - yy) * q.s;
m23 = q.t.z;
}
//CONSTRUCTOR for different float-types. It converts a QuatTS into a Matrix34.
//Needs to be 'explicit' because we loose float-precision in the conversion process
//Matrix34(QuatT);
template<class F1>
ILINE explicit Matrix34_tpl<F>(const QuatTS_tpl<F1> &q)
{
assert(q.q.IsValid());
Vec3_tpl<F1> v2 = q.q.v + q.q.v;
F1 xx = 1 - v2.x * q.q.v.x;
F1 yy = v2.y * q.q.v.y;
F1 xw = v2.x * q.q.w;
F1 xy = v2.y * q.q.v.x;
F1 yz = v2.z * q.q.v.y;
F1 yw = v2.y * q.q.w;
F1 xz = v2.z * q.q.v.x;
F1 zz = v2.z * q.q.v.z;
F1 zw = v2.z * q.q.w;
m00 = F((1 - yy - zz) * q.s);
m01 = F((xy - zw) * q.s);
m02 = F((xz + yw) * q.s);
m03 = F(q.t.x);
m10 = F((xy + zw) * q.s);
m11 = F((xx - zz) * q.s);
m12 = F((yz - xw) * q.s);
m13 = F(q.t.y);
m20 = F((xz - yw) * q.s);
m21 = F((yz + xw) * q.s);
m22 = F((xx - yy) * q.s);
m23 = F(q.t.z);
}
//CONSTRUCTOR for identical float-types. It converts a QuatTNS into a Matrix34.
//Needs to be 'explicit' because we loose float-precision in the conversion process
//Matrix34(QuatT);
explicit ILINE Matrix34_tpl<F>(const QuatTNS_tpl<F> &q)
{
assert(q.q.IsValid());
Vec3_tpl<F> v2 = q.q.v + q.q.v;
F xx = 1 - v2.x * q.q.v.x;
F yy = v2.y * q.q.v.y;
F xw = v2.x * q.q.w;
F xy = v2.y * q.q.v.x;
F yz = v2.z * q.q.v.y;
F yw = v2.y * q.q.w;
F xz = v2.z * q.q.v.x;
F zz = v2.z * q.q.v.z;
F zw = v2.z * q.q.w;
m00 = (1 - yy - zz) * q.s.x;
m01 = (xy - zw) * q.s.y;
m02 = (xz + yw) * q.s.z;
m03 = q.t.x;
m10 = (xy + zw) * q.s.x;
m11 = (xx - zz) * q.s.y;
m12 = (yz - xw) * q.s.z;
m13 = q.t.y;
m20 = (xz - yw) * q.s.x;
m21 = (yz + xw) * q.s.y;
m22 = (xx - yy) * q.s.z;
m23 = q.t.z;
}
//CONSTRUCTOR for different float-types. It converts a QuatTNS into a Matrix34.
//Needs to be 'explicit' because we loose float-precision in the conversion process
//Matrix34(QuatT);
template<class F1>
ILINE explicit Matrix34_tpl<F>(const QuatTNS_tpl<F1> &q)
{
assert(q.q.IsValid());
Vec3_tpl<F1> v2 = q.q.v + q.q.v;
F1 xx = 1 - v2.x * q.q.v.x;
F1 yy = v2.y * q.q.v.y;
F1 xw = v2.x * q.q.w;
F1 xy = v2.y * q.q.v.x;
F1 yz = v2.z * q.q.v.y;
F1 yw = v2.y * q.q.w;
F1 xz = v2.z * q.q.v.x;
F1 zz = v2.z * q.q.v.z;
F1 zw = v2.z * q.q.w;
m00 = F((1 - yy - zz) * q.s.x);
m01 = F((xy - zw) * q.s.y);
m02 = F((xz + yw) * q.s.z);
m03 = F(q.t.x);
m10 = F((xy + zw) * q.s.x);
m11 = F((xx - zz) * q.s.y);
m12 = F((yz - xw) * q.s.z);
m13 = F(q.t.y);
m20 = F((xz - yw) * q.s.x);
m21 = F((yz + xw) * q.s.y);
m22 = F((xx - yy) * q.s.z);
m23 = F(q.t.z);
}
//CONSTRUCTOR for identical float-types. It converts a DualQuat into a Matrix34.
//Needs to be 'explicit' because we loose float-precision in the conversion process
//Matrix34(QuatT);
ILINE explicit Matrix34_tpl<F>(const DualQuat_tpl<F> &q)
{
assert((fabs_tpl(1 - (q.nq | q.nq))) < 0.01); //check if unit-quaternion
Vec3_tpl<F> t = (q.nq.w * q.dq.v - q.dq.w * q.nq.v + q.nq.v % q.dq.v); //perfect for HLSL
Vec3_tpl<F> v2 = q.nq.v + q.nq.v;
F xx = 1 - v2.x * q.nq.v.x;
F yy = v2.y * q.nq.v.y;
F xw = v2.x * q.nq.w;
F xy = v2.y * q.nq.v.x;
F yz = v2.z * q.nq.v.y;
F yw = v2.y * q.nq.w;
F xz = v2.z * q.nq.v.x;
F zz = v2.z * q.nq.v.z;
F zw = v2.z * q.nq.w;
m00 = 1 - yy - zz;
m01 = xy - zw;
m02 = xz + yw;
m03 = t.x + t.x;
m10 = xy + zw;
m11 = xx - zz;
m12 = yz - xw;
m13 = t.y + t.y;
m20 = xz - yw;
m21 = yz + xw;
m22 = xx - yy;
m23 = t.z + t.z;
}
//CONSTRUCTOR for different float-types. It converts a DualQuat into a Matrix34.
//Needs to be 'explicit' because we loose float-precision in the conversion process
//Matrix34(QuatT);
template<class F1>
ILINE explicit Matrix34_tpl<F>(const DualQuat_tpl<F1> &q)
{
assert((fabs_tpl(1 - (q.nq | q.nq))) < 0.01); //check if unit-quaternion
Vec3_tpl<F1> t = (q.nq.w * q.dq.v - q.dq.w * q.nq.v + q.nq.v % q.dq.v); //perfect for HLSL
Vec3_tpl<F1> v2 = q.nq.v + q.nq.v;
F1 xx = 1 - v2.x * q.nq.v.x;
F1 yy = v2.y * q.nq.v.y;
F1 xw = v2.x * q.nq.w;
F1 xy = v2.y * q.nq.v.x;
F1 yz = v2.z * q.nq.v.y;
F1 yw = v2.y * q.nq.w;
F1 xz = v2.z * q.nq.v.x;
F1 zz = v2.z * q.nq.v.z;
F1 zw = v2.z * q.nq.w;
m00 = F(1 - yy - zz);
m01 = F(xy - zw);
m02 = F(xz + yw);
m03 = F(t.x + t.x);
m10 = F(xy + zw);
m11 = F(xx - zz);
m12 = F(yz - xw);
m13 = F(t.y + t.y);
m20 = F(xz - yw);
m21 = F(yz + xw);
m22 = F(xx - yy);
m23 = F(t.z + t.z);
}
//apply scaling to the columns of the matrix.
ILINE void ScaleColumn(const Vec3_tpl<F>& s)
{
m00 *= s.x;
m01 *= s.y;
m02 *= s.z;
m10 *= s.x;
m11 *= s.y;
m12 *= s.z;
m20 *= s.x;
m21 *= s.y;
m22 *= s.z;
}
/*!
*
* Initializes the Matrix34 with the identity.
*
*/
void SetIdentity(void)
{
m00 = 1.0f;
m01 = 0.0f;
m02 = 0.0f;
m03 = 0.0f;
m10 = 0.0f;
m11 = 1.0f;
m12 = 0.0f;
m13 = 0.0f;
m20 = 0.0f;
m21 = 0.0f;
m22 = 1.0f;
m23 = 0.0f;
}
ILINE static Matrix34_tpl<F> CreateIdentity(void)
{
Matrix34_tpl<F> m;
m.SetIdentity();
return m;
}
ILINE bool IsIdentity() const
{
return 0 == (fabs_tpl((F)1 - m00) + fabs_tpl(m01) + fabs_tpl(m02) + fabs_tpl(m03) + fabs_tpl(m10) + fabs_tpl((F)1 - m11) + fabs_tpl(m12) + fabs_tpl(m13) + fabs_tpl(m20) + fabs_tpl(m21) + fabs_tpl((F)1 - m22)) + fabs_tpl(m23);
}
ILINE int IsZero() const
{
return 0 == (fabs_tpl(m00) + fabs_tpl(m01) + fabs_tpl(m02) + fabs_tpl(m03) + fabs_tpl(m10) + fabs_tpl(m11) + fabs_tpl(m12) + fabs_tpl(m13) + fabs_tpl(m20) + fabs_tpl(m21) + fabs_tpl(m22)) + fabs_tpl(m23);
}
/*!
* Create a rotation matrix around an arbitrary axis (Eulers Theorem).
* The axis is specified as an normalized Vec3. The angle is assumed to be in radians.
* This function also assumes a translation-vector and stores it in the right column.
*
* Example:
* Matrix34 m34;
* Vec3 axis=GetNormalized( Vec3(-1.0f,-0.3f,0.0f) );
* m34.SetRotationAA( 3.14314f, axis, Vec3(5,5,5) );
*/
ILINE void SetRotationAA(const F rad, const Vec3_tpl<F>& axis, const Vec3_tpl<F>& t = Vec3(ZERO))
{
*this = Matrix33_tpl<F>::CreateRotationAA(rad, axis);
this->SetTranslation(t);
}
ILINE static Matrix34_tpl<F> CreateRotationAA(const F rad, const Vec3_tpl<F>& axis, const Vec3_tpl<F>& t = Vec3(ZERO))
{
Matrix34_tpl<F> m34;
m34.SetRotationAA(rad, axis, t);
return m34;
}
ILINE void SetRotationAA(const Vec3_tpl<F>& rot, const Vec3_tpl<F>& t = Vec3(ZERO))
{
*this = Matrix33_tpl<F>::CreateRotationAA(rot);
this->SetTranslation(t);
}
ILINE static Matrix34_tpl<F> CreateRotationAA(const Vec3_tpl<F>& rot, const Vec3_tpl<F>& t = Vec3(ZERO))
{
Matrix34_tpl<F> m34;
m34.SetRotationAA(rot, t);
return m34;
}
/*!
* Create rotation-matrix about X axis using an angle.
* The angle is assumed to be in radians.
* The translation-vector is set to zero.
*
* Example:
* Matrix34 m34;
* m34.SetRotationX(0.5f);
*/
ILINE void SetRotationX(const f32 rad, const Vec3_tpl<F>& t = Vec3(ZERO))
{
*this = Matrix33_tpl<F>::CreateRotationX(rad);
this->SetTranslation(t);
}
ILINE static Matrix34_tpl<F> CreateRotationX(const f32 rad, const Vec3_tpl<F>& t = Vec3(ZERO))
{
Matrix34_tpl<F> m34;
m34.SetRotationX(rad, t);
return m34;
}
/*!
* Create rotation-matrix about Y axis using an angle.
* The angle is assumed to be in radians.
* The translation-vector is set to zero.
*
* Example:
* Matrix34 m34;
* m34.SetRotationY(0.5f);
*/
ILINE void SetRotationY(const f32 rad, const Vec3_tpl<F>& t = Vec3(ZERO))
{
*this = Matrix33_tpl<F>::CreateRotationY(rad);
this->SetTranslation(t);
}
ILINE static Matrix34_tpl<F> CreateRotationY(const f32 rad, const Vec3_tpl<F>& t = Vec3(ZERO))
{
Matrix34_tpl<F> m34;
m34.SetRotationY(rad, t);
return m34;
}
/*!
* Create rotation-matrix about Z axis using an angle.
* The angle is assumed to be in radians.
* The translation-vector is set to zero.
*
* Example:
* Matrix34 m34;
* m34.SetRotationZ(0.5f);
*/
ILINE void SetRotationZ(const f32 rad, const Vec3_tpl<F>& t = Vec3(ZERO))
{
*this = Matrix33_tpl<F>::CreateRotationZ(rad);
this->SetTranslation(t);
}
ILINE static Matrix34_tpl<F> CreateRotationZ(const f32 rad, const Vec3_tpl<F>& t = Vec3(ZERO))
{
Matrix34_tpl<F> m34;
m34.SetRotationZ(rad, t);
return m34;
}
/*!
*
* Convert three Euler angle to mat33 (rotation order:XYZ)
* The Euler angles are assumed to be in radians.
* The translation-vector is set to zero.
*
* Example 1:
* Matrix34 m34;
* m34.SetRotationXYZ( Ang3(0.5f,0.2f,0.9f), translation );
*
* Example 2:
* Matrix34 m34=Matrix34::CreateRotationXYZ( Ang3(0.5f,0.2f,0.9f), translation );
*/
ILINE void SetRotationXYZ(const Ang3_tpl<F>& rad, const Vec3_tpl<F>& t = Vec3(ZERO))
{
assert(rad.IsValid());
assert(t.IsValid());
*this = Matrix33_tpl<F>::CreateRotationXYZ(rad);
this->SetTranslation(t);
}
ILINE static Matrix34_tpl<F> CreateRotationXYZ(const Ang3_tpl<F>& rad, const Vec3_tpl<F>& t = Vec3(ZERO))
{
assert(rad.IsValid());
assert(t.IsValid());
Matrix34_tpl<F> m34;
m34.SetRotationXYZ(rad, t);
return m34;
}
ILINE void SetRotationAA(F c, F s, Vec3_tpl<F> axis, const Vec3_tpl<F>& t = Vec3(ZERO))
{
assert(axis.IsValid());
assert(t.IsValid());
*this = Matrix33_tpl<F>::CreateRotationAA(c, s, axis);
m03 = t.x;
m13 = t.y;
m23 = t.z;
}
ILINE static Matrix34_tpl<F> CreateRotationAA(F c, F s, Vec3_tpl<F> axis, const Vec3_tpl<F>& t = Vec3(ZERO))
{
Matrix34_tpl<F> m34;
m34.SetRotationAA(c, s, axis, t);
return m34;
}
ILINE void SetTranslationMat(const Vec3_tpl<F>& v)
{
m00 = 1.0f;
m01 = 0.0f;
m02 = 0.0f;
m03 = v.x;
m10 = 0.0f;
m11 = 1.0f;
m12 = 0.0f;
m13 = v.y;
m20 = 0.0f;
m21 = 0.0f;
m22 = 1.0f;
m23 = v.z;
}
ILINE static Matrix34_tpl<F> CreateTranslationMat(const Vec3_tpl<F>& v)
{
Matrix34_tpl<F> m34;
m34.SetTranslationMat(v);
return m34;
}
//NOTE: all vectors are stored in columns
ILINE void SetFromVectors(const Vec3& vx, const Vec3& vy, const Vec3& vz, const Vec3& pos)
{
m00 = vx.x;
m01 = vy.x;
m02 = vz.x;
m03 = pos.x;
m10 = vx.y;
m11 = vy.y;
m12 = vz.y;
m13 = pos.y;
m20 = vx.z;
m21 = vy.z;
m22 = vz.z;
m23 = pos.z;
}
ILINE static Matrix34_tpl<F> CreateFromVectors(const Vec3_tpl<F>& vx, const Vec3_tpl<F>& vy, const Vec3_tpl<F>& vz, const Vec3_tpl<F>& pos)
{
Matrix34_tpl<F> m;
m.SetFromVectors(vx, vy, vz, pos);
return m;
}
void InvertFast()
{ // in-place transposition
assert(IsOrthonormal());
F t;
Vec3 v(m03, m13, m23);
t = m01;
m01 = m10;
m10 = t;
m03 = -v.x * m00 - v.y * m01 - v.z * m20;
t = m02;
m02 = m20;
m20 = t;
m13 = -v.x * m10 - v.y * m11 - v.z * m21;
t = m12;
m12 = m21;
m21 = t;
m23 = -v.x * m20 - v.y * m21 - v.z * m22;
}
Matrix34_tpl<F> GetInvertedFast() const
{
assert(IsOrthonormal());
Matrix34_tpl<F> dst;
dst.m00 = m00;
dst.m01 = m10;
dst.m02 = m20;
dst.m03 = -m03 * m00 - m13 * m10 - m23 * m20;
dst.m10 = m01;
dst.m11 = m11;
dst.m12 = m21;
dst.m13 = -m03 * m01 - m13 * m11 - m23 * m21;
dst.m20 = m02;
dst.m21 = m12;
dst.m22 = m22;
dst.m23 = -m03 * m02 - m13 * m12 - m23 * m22;
return dst;
}
//! transforms a vector. the translation is not beeing considered
ILINE Vec3_tpl<F> TransformVector(const Vec3_tpl<F>& v) const
{
assert(v.IsValid());
return Vec3_tpl<F>(m00 * v.x + m01 * v.y + m02 * v.z, m10 * v.x + m11 * v.y + m12 * v.z, m20 * v.x + m21 * v.y + m22 * v.z);
}
//! transforms a point and add translation vector
ILINE Vec3_tpl<F> TransformPoint(const Vec3_tpl<F>& p) const
{
assert(p.IsValid());
return Vec3_tpl<F>(m00 * p.x + m01 * p.y + m02 * p.z + m03, m10 * p.x + m11 * p.y + m12 * p.z + m13, m20 * p.x + m21 * p.y + m22 * p.z + m23);
}
//! Remove scale from matrix.
void OrthonormalizeFast()
{
Vec3_tpl<F> x(m00, m10, m20);
Vec3_tpl<F> y(m01, m11, m21);
Vec3_tpl<F> z;
x = x.GetNormalized();
z = (x % y).GetNormalized();
y = (z % x).GetNormalized();
m00 = x.x;
m10 = x.y;
m20 = x.z;
m01 = y.x;
m11 = y.y;
m21 = y.z;
m02 = z.x;
m12 = z.y;
m22 = z.z;
}
//determinant is ambiguous: only the upper-left-submatrix's determinant is calculated
ILINE f32 Determinant() const
{
return (m00 * m11 * m22) + (m01 * m12 * m20) + (m02 * m10 * m21) - (m02 * m11 * m20) - (m00 * m12 * m21) - (m01 * m10 * m22);
}
//--------------------------------------------------------------------------------
//---- helper functions to access matrix-members ------------
//--------------------------------------------------------------------------------
F* GetData() { return &m00; }
const F* GetData() const { return &m00; }
ILINE F operator () (uint32 i, uint32 j) const { assert ((i < 3) && (j < 4)); F* p_data = (F*)(&m00); return p_data[i * 4 + j]; }
ILINE F& operator () (uint32 i, uint32 j) { assert ((i < 3) && (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 < 3); F* p = (F*)(&m00); p[0 + 4 * i] = v.x; p[1 + 4 * i] = v.y; p[2 + 4 * i] = v.z; }
ILINE const Vec3_tpl<F>& GetRow(int i) const { assert(i < 3); return *(const Vec3_tpl<F>*)(&m00 + 4 * i); }
ILINE const Vec4_tpl<F>& GetRow4(int i) const { assert(i < 3); return *(const Vec4_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 Vec3_tpl<F> GetColumn0() const { return Vec3_tpl<F>(m00, m10, m20); }
ILINE Vec3_tpl<F> GetColumn1() const { return Vec3_tpl<F>(m01, m11, m21); }
ILINE Vec3_tpl<F> GetColumn2() const { return Vec3_tpl<F>(m02, m12, m22); }
ILINE Vec3_tpl<F> GetColumn3() const { return Vec3_tpl<F>(m03, m13, m23); }
ILINE void SetTranslation(const Vec3_tpl<F>& t) { m03 = t.x; m13 = t.y; m23 = t.z; }
ILINE Vec3_tpl<F> GetTranslation() const { return Vec3_tpl<F>(m03, m13, m23); }
ILINE void ScaleTranslation (F s) { m03 *= s; m13 *= s; m23 *= s; }
ILINE Matrix34_tpl<F> AddTranslation(const Vec3_tpl<F>& t) { m03 += t.x; m13 += t.y; m23 += t.z; return *this; }
ILINE void SetRotation33(const Matrix33_tpl<F>& m33)
{
m00 = m33.m00;
m01 = m33.m01;
m02 = m33.m02;
m10 = m33.m10;
m11 = m33.m11;
m12 = m33.m12;
m20 = m33.m20;
m21 = m33.m21;
m22 = m33.m22;
}
ILINE void GetRotation33(Matrix33_tpl<F>& m33) const
{
m33.m00 = m00;
m33.m01 = m01;
m33.m02 = m02;
m33.m10 = m10;
m33.m11 = m11;
m33.m12 = m12;
m33.m20 = m20;
m33.m21 = m21;
m33.m22 = m22;
}
//check if we have an orthonormal-base (general case, works even with reflection matrices)
int IsOrthonormal(F threshold = 0.001) const
{
f32 d0 = fabs_tpl(GetColumn0() | GetColumn1());
if (d0 > threshold)
{
return 0;
}
f32 d1 = fabs_tpl(GetColumn0() | GetColumn2());
if (d1 > threshold)
{
return 0;
}
f32 d2 = fabs_tpl(GetColumn1() | GetColumn2());
if (d2 > threshold)
{
return 0;
}
int a = (fabs_tpl(1 - (GetColumn0() | GetColumn0()))) < threshold;
int b = (fabs_tpl(1 - (GetColumn1() | GetColumn1()))) < threshold;
int c = (fabs_tpl(1 - (GetColumn2() | GetColumn2()))) < threshold;
return a & b & c;
}
//check if we have an orthonormal-base (assuming we are using a right-handed coordinate system)
int IsOrthonormalRH(F threshold = 0.001) const
{
int a = Vec3_tpl<F>::IsEquivalent(GetColumn0(), GetColumn1() % GetColumn2(), threshold);
int b = Vec3_tpl<F>::IsEquivalent(GetColumn1(), GetColumn2() % GetColumn0(), threshold);
int c = Vec3_tpl<F>::IsEquivalent(GetColumn2(), GetColumn0() % GetColumn1(), threshold);
return a & b & c;
}
bool static IsEquivalent(const Matrix34_tpl<F>& m0, const Matrix34_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)
);
}
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;
}
return true;
}
bool IsDegenerate(float epsilon = FLT_EPSILON) const
{
//check the basis vectors for 0 vector
return GetColumn0().len2() < epsilon
|| GetColumn1().len2() < epsilon
|| GetColumn2().len2() < epsilon;
}
/*!
* Create a matrix with SCALING, ROTATION and TRANSLATION (in this order).
*
* Example 1:
* Matrix m34;
* m34.SetMatrix( Vec3(1,2,3), quat, Vec3(11,22,33) );
*/
ILINE void Set(const Vec3_tpl<F>& s, const Quat_tpl<F>& q, const Vec3_tpl<F>& t = Vec3(ZERO))
{
assert(s.IsValid());
assert(q.IsUnit(0.1f));
assert(t.IsValid());
F vxvx = q.v.x * q.v.x;
F vzvz = q.v.z * q.v.z;
F vyvy = q.v.y * q.v.y;
F vxvy = q.v.x * q.v.y;
F vxvz = q.v.x * q.v.z;
F vyvz = q.v.y * q.v.z;
F svx = q.w * q.v.x;
F svy = q.w * q.v.y;
F svz = q.w * q.v.z;
m00 = (1 - (vyvy + vzvz) * 2) * s.x;
m01 = (vxvy - svz) * 2 * s.y;
m02 = (vxvz + svy) * 2 * s.z;
m03 = t.x;
m10 = (vxvy + svz) * 2 * s.x;
m11 = (1 - (vxvx + vzvz) * 2) * s.y;
m12 = (vyvz - svx) * 2 * s.z;
m13 = t.y;
m20 = (vxvz - svy) * 2 * s.x;
m21 = (vyvz + svx) * 2 * s.y;
m22 = (1 - (vxvx + vyvy) * 2) * s.z;
m23 = t.z;
}
ILINE static Matrix34_tpl<F> Create(const Vec3_tpl<F>& s, const Quat_tpl<F>& q, const Vec3_tpl<F>& t = Vec3(ZERO))
{
Matrix34_tpl<F> m34;
m34.Set(s, q, t);
return m34;
}
Matrix34_tpl(const Vec3_tpl<F>& s, const Quat_tpl<F>& q, const Vec3_tpl<F>& t = Vec3(ZERO))
{
Set(s, q, t);
}
/*!
* Create scaling-matrix.
* The translation-vector is set to zero.
*
* Example 1:
* Matrix m34;
* m34.SetScale( Vec3(0.5f, 1.0f, 2.0f) );
* Example 2:
* Matrix34 m34 = Matrix34::CreateScale( Vec3(0.5f, 1.0f, 2.0f) );
*/
ILINE void SetScale(const Vec3_tpl<F>& s, const Vec3_tpl<F>& t = Vec3(ZERO))
{
*this = Matrix33::CreateScale(s);
this->SetTranslation(t);
}
ILINE static Matrix34_tpl<F> CreateScale(const Vec3_tpl<F>& s, const Vec3_tpl<F>& t = Vec3(ZERO))
{
Matrix34_tpl<F> m34;
m34.SetScale(s, t);
return m34;
}
ILINE Matrix44_tpl<F> GetTransposed() const
{
Matrix44_tpl<F> tmp;
tmp.m00 = m00;
tmp.m01 = m10;
tmp.m02 = m20;
tmp.m03 = 0;
tmp.m10 = m01;
tmp.m11 = m11;
tmp.m12 = m21;
tmp.m13 = 0;
tmp.m20 = m02;
tmp.m21 = m12;
tmp.m22 = m22;
tmp.m23 = 0;
tmp.m30 = m03;
tmp.m31 = m13;
tmp.m32 = m23;
tmp.m33 = 1;
return tmp;
}
/*!
* calculate a real inversion of a Matrix34
* an inverse-matrix is an UnDo-matrix for all kind of transformations
*
* Example 1:
* Matrix34 im34; im34.Invert();
*
* Example 2:
* Matrix34 im34 = m34.GetInverted();
*/
void Invert(void)
{
//rescue members
Matrix34_tpl<F> m = *this;
// calculate 12 cofactors
m00 = m.m22 * m.m11 - m.m12 * m.m21;
m10 = m.m12 * m.m20 - m.m22 * m.m10;
m20 = m.m10 * m.m21 - m.m20 * m.m11;
m01 = m.m02 * m.m21 - m.m22 * m.m01;
m11 = m.m22 * m.m00 - m.m02 * m.m20;
m21 = m.m20 * m.m01 - m.m00 * m.m21;
m02 = m.m12 * m.m01 - m.m02 * m.m11;
m12 = m.m02 * m.m10 - m.m12 * m.m00;
m22 = m.m00 * m.m11 - m.m10 * m.m01;
m03 = (m.m22 * m.m13 * m.m01 + m.m02 * m.m23 * m.m11 + m.m12 * m.m03 * m.m21) - (m.m12 * m.m23 * m.m01 + m.m22 * m.m03 * m.m11 + m.m02 * m.m13 * m.m21);
m13 = (m.m12 * m.m23 * m.m00 + m.m22 * m.m03 * m.m10 + m.m02 * m.m13 * m.m20) - (m.m22 * m.m13 * m.m00 + m.m02 * m.m23 * m.m10 + m.m12 * m.m03 * m.m20);
m23 = (m.m20 * m.m11 * m.m03 + m.m00 * m.m21 * m.m13 + m.m10 * m.m01 * m.m23) - (m.m10 * m.m21 * m.m03 + m.m20 * m.m01 * m.m13 + m.m00 * m.m11 * m.m23);
// calculate determinant
F det = m.m00 * m00 + m.m10 * m01 + m.m20 * m02;
assert(fabs_tpl(det) > (F)0.00000001);
F rcpDet = 1.0f / det;
// calculate matrix inverse/
m00 *= rcpDet;
m01 *= rcpDet;
m02 *= rcpDet;
m03 *= rcpDet;
m10 *= rcpDet;
m11 *= rcpDet;
m12 *= rcpDet;
m13 *= rcpDet;
m20 *= rcpDet;
m21 *= rcpDet;
m22 *= rcpDet;
m23 *= rcpDet;
}
ILINE Matrix34_tpl<F> GetInverted() const
{
Matrix34_tpl<F> dst = *this;
dst.Invert();
return dst;
}
/*!
* Name: ReflectMat34
* Description: reflect a rotation matrix with respect to a plane.
*
* Example:
* Vec3 normal( 0.0f,-1.0f, 0.0f);
* Vec3 pos(0,1000,0);
* Matrix34 m34=CreateReflectionMat( pos, normal );
*/
ILINE static Matrix34_tpl<F> CreateReflectionMat (const Vec3_tpl<F>& p, const Vec3_tpl<F>& n)
{
Matrix34_tpl<F> m;
F vxy = -2.0f * n.x * n.y;
F vxz = -2.0f * n.x * n.z;
F vyz = -2.0f * n.y * n.z;
F pdotn = 2.0f * (p | n);
m.m00 = 1.0f - 2.0f * n.x * n.x;
m.m01 = vxy;
m.m02 = vxz;
m.m03 = pdotn * n.x;
m.m10 = vxy;
m.m11 = 1.0f - 2.0f * n.y * n.y;
m.m12 = vyz;
m.m13 = pdotn * n.y;
m.m20 = vxz;
m.m21 = vyz;
m.m22 = 1.0f - 2.0f * n.z * n.z;
m.m23 = pdotn * n.z;
return m;
}
AUTO_STRUCT_INFO
};
///////////////////////////////////////////////////////////////////////////////
// Typedefs //
///////////////////////////////////////////////////////////////////////////////
typedef Matrix34_tpl<f32> Matrix34; //always 32 bit
typedef Matrix34_tpl<f64> Matrix34d;//always 64 bit
typedef Matrix34_tpl<real> Matrix34r;//variable float precision. depending on the target system it can be between 32, 64 or bit
typedef _MS_ALIGN(16) Matrix34_tpl<f32> _ALIGN (16) Matrix34A;
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//------------- implementation of Matrix34 ------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//! multiply all matrix's values by f and return the matrix
template<class F>
ILINE Matrix34_tpl<F> operator * (const Matrix34_tpl<F>& m, const f32 f)
{
assert(m.IsValid());
Matrix34_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;
return r;
}
/*!
* multiplication of Matrix34 by a (column) Vec3.
* This function transforms the given input Vec3
* into the coordinate system defined by this matrix.
*
* Example:
* Matrix34 m34;
* Vec3 vector(44,55,66);
* Vec3 result = m34*vector;
*/
template<class F>
ILINE Vec3_tpl<F> operator * (const Matrix34_tpl<F>& m, const Vec3_tpl<F>& p)
{
assert(m.IsValid());
assert(p.IsValid());
Vec3_tpl<F> tp;
tp.x = m.m00 * p.x + m.m01 * p.y + m.m02 * p.z + m.m03;
tp.y = m.m10 * p.x + m.m11 * p.y + m.m12 * p.z + m.m13;
tp.z = m.m20 * p.x + m.m21 * p.y + m.m22 * p.z + m.m23;
return tp;
}
template<class F1, class F2>
ILINE Matrix34_tpl<F1> operator*(const Matrix34_tpl<F1>& l, const Diag33_tpl<F2>& r)
{
assert(l.IsValid());
assert(r.IsValid());
Matrix34_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;
return m;
}
template<class F1, class F2>
ILINE Matrix34_tpl<F1>& operator *= (Matrix34_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;
return l;
}
template<class F1, class F2>
ILINE Matrix34_tpl<F1> operator + (const Matrix34_tpl<F1>& l, const Matrix34_tpl<F2>& r)
{
assert(l.IsValid());
assert(r.IsValid());
Matrix34_tpl<F1> m;
m.m00 = l.m00 + r.m00;
m.m01 = l.m01 + r.m01;
m.m02 = l.m02 + r.m02;
m.m03 = l.m03 + r.m03;
m.m10 = l.m10 + r.m10;
m.m11 = l.m11 + r.m11;
m.m12 = l.m12 + r.m12;
m.m13 = l.m13 + r.m13;
m.m20 = l.m20 + r.m20;
m.m21 = l.m21 + r.m21;
m.m22 = l.m22 + r.m22;
m.m23 = l.m23 + r.m23;
return m;
}
template<class F1, class F2>
ILINE Matrix34_tpl<F1>& operator += (Matrix34_tpl<F1>& l, const Matrix34_tpl<F2>& r)
{
assert(l.IsValid());
assert(r.IsValid());
l.m00 += r.m00;
l.m01 += r.m01;
l.m02 += r.m02;
l.m03 += r.m03;
l.m10 += r.m10;
l.m11 += r.m11;
l.m12 += r.m12;
l.m13 += r.m13;
l.m20 += r.m20;
l.m21 += r.m21;
l.m22 += r.m22;
l.m23 += r.m23;
return l;
}
/*!
* Implements the multiplication operator: Matrix34=Matrix34*Matrix33
*
* Matrix33 and Matrix44 are specified in collumn order for a right-handed coordinate-system.
* AxB = operation B followed by operation A.
* A multiplication takes 27 muls and 24 adds.
*
* Example:
* Matrix34 m34=Matrix33::CreateRotationX(1.94192f);;
* Matrix33 m33=Matrix34::CreateRotationZ(3.14192f);
* Matrix34 result=m34*m33;
*/
template<class F>
ILINE Matrix34_tpl<F> operator * (const Matrix34_tpl<F>& l, const Matrix33_tpl<F>& r)
{
assert(l.IsValid());
assert(r.IsValid());
Matrix34_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.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.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.m03 = l.m03;
m.m13 = l.m13;
m.m23 = l.m23;
return m;
}
/*!
* Implements the multiplication operator: Matrix34=Matrix34*Matrix34
*
* Matrix34 is specified in collumn order.
* AxB = rotation B followed by rotation A.
* This operation takes 36 mults and 27 adds.
*
* Example:
* Matrix34 m34=Matrix34::CreateRotationX(1.94192f, Vec3(11,22,33));;
* Matrix34 m34=Matrix33::CreateRotationZ(3.14192f);
* Matrix34 result=m34*m34;
*/
template<class F>
ILINE Matrix34_tpl<F> operator * (const Matrix34_tpl<F>& l, const Matrix34_tpl<F>& r)
{
assert(l.IsValid());
assert(r.IsValid());
Matrix34_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.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.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.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;
return m;
}
/*!
* Implements the multiplication operator: Matrix44=Matrix34*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:
* Matrix34 m34=Matrix33::CreateRotationX(1.94192f);;
* Matrix44 m44=Matrix33::CreateRotationZ(3.14192f);
* Matrix44 result=m34*m44;
*/
template<class F>
ILINE Matrix44_tpl<F> operator * (const Matrix34_tpl<F>& l, const Matrix44_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 + l.m03 * r.m30;
m.m10 = l.m10 * r.m00 + l.m11 * r.m10 + l.m12 * r.m20 + l.m13 * r.m30;
m.m20 = l.m20 * r.m00 + l.m21 * r.m10 + l.m22 * r.m20 + l.m23 * r.m30;
m.m30 = r.m30;
m.m01 = l.m00 * r.m01 + l.m01 * r.m11 + l.m02 * r.m21 + l.m03 * r.m31;
m.m11 = l.m10 * r.m01 + l.m11 * r.m11 + l.m12 * r.m21 + l.m13 * r.m31;
m.m21 = l.m20 * r.m01 + l.m21 * r.m11 + l.m22 * r.m21 + l.m23 * r.m31;
m.m31 = r.m31;
m.m02 = l.m00 * r.m02 + l.m01 * r.m12 + l.m02 * r.m22 + l.m03 * r.m32;
m.m12 = l.m10 * r.m02 + l.m11 * r.m12 + l.m12 * r.m22 + l.m13 * r.m32;
m.m22 = l.m20 * r.m02 + l.m21 * r.m12 + l.m22 * r.m22 + l.m23 * r.m32;
m.m32 = r.m32;
m.m03 = l.m00 * r.m03 + l.m01 * r.m13 + l.m02 * r.m23 + l.m03 * r.m33;
m.m13 = l.m10 * r.m03 + l.m11 * r.m13 + l.m12 * r.m23 + l.m13 * r.m33;
m.m23 = l.m20 * r.m03 + l.m21 * r.m13 + l.m22 * r.m23 + l.m23 * r.m33;
m.m33 = r.m33;
return m;
}
#endif // CRYINCLUDE_CRYCOMMON_CRY_MATRIX34_H