|
|
@@ -25,10 +25,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
THE SOFTWARE.
|
|
|
-----------------------------------------------------------------------------
|
|
|
*/
|
|
|
-#ifndef __Matrix4__
|
|
|
-#define __Matrix4__
|
|
|
+#pragma once
|
|
|
|
|
|
-// Precompiler options
|
|
|
#include "CmPrerequisitesUtil.h"
|
|
|
|
|
|
#include "CmVector3.h"
|
|
|
@@ -38,66 +36,24 @@ THE SOFTWARE.
|
|
|
|
|
|
namespace CamelotFramework
|
|
|
{
|
|
|
- /** \addtogroup Core
|
|
|
- * @{
|
|
|
- */
|
|
|
- /** \addtogroup Math
|
|
|
- * @{
|
|
|
- */
|
|
|
- /** Class encapsulating a standard 4x4 homogeneous matrix.
|
|
|
- @remarks
|
|
|
- We use column vectors when applying matrix multiplications,
|
|
|
- This means a vector is represented as a single column, 4-row
|
|
|
- matrix. This has the effect that the transformations implemented
|
|
|
- by the matrices happens right-to-left e.g. if vector V is to be
|
|
|
- transformed by M1 then M2 then M3, the calculation would be
|
|
|
- M3 * M2 * M1 * V. The order that matrices are concatenated is
|
|
|
- vital since matrix multiplication is not commutative, i.e. you
|
|
|
- can get a different result if you concatenate in the wrong order.
|
|
|
- @par
|
|
|
- The use of column vectors and right-to-left ordering is the
|
|
|
- standard in most mathematical texts, and is the same as used in
|
|
|
- OpenGL. It is, however, the opposite of Direct3D, which has
|
|
|
- inexplicably chosen to differ from the accepted standard and uses
|
|
|
- row vectors and left-to-right matrix multiplication.
|
|
|
- @par
|
|
|
- We deal with the differences between D3D and OpenGL etc.
|
|
|
- internally when operating through different render systems.
|
|
|
- Users only need to conform to standard maths conventions, i.e.
|
|
|
- right-to-left matrix multiplication, (Engine transposes matrices it
|
|
|
- passes to D3D to compensate).
|
|
|
- @par
|
|
|
- The generic form M * V which shows the layout of the matrix
|
|
|
- entries is shown below:
|
|
|
- <pre>
|
|
|
- [ m[0][0] m[0][1] m[0][2] m[0][3] ] {x}
|
|
|
- | m[1][0] m[1][1] m[1][2] m[1][3] | * {y}
|
|
|
- | m[2][0] m[2][1] m[2][2] m[2][3] | {z}
|
|
|
- [ m[3][0] m[3][1] m[3][2] m[3][3] ] {1}
|
|
|
- </pre>
|
|
|
- */
|
|
|
class CM_UTILITY_EXPORT Matrix4
|
|
|
{
|
|
|
- protected:
|
|
|
- /// The matrix entries, indexed by [row][col].
|
|
|
- union {
|
|
|
+ private:
|
|
|
+ union
|
|
|
+ {
|
|
|
float m[4][4];
|
|
|
float _m[16];
|
|
|
};
|
|
|
+
|
|
|
public:
|
|
|
- /** Default constructor.
|
|
|
- @note
|
|
|
- It does <b>NOT</b> initialize the matrix for efficiency.
|
|
|
- */
|
|
|
- inline Matrix4()
|
|
|
- {
|
|
|
- }
|
|
|
+ Matrix4()
|
|
|
+ { }
|
|
|
|
|
|
- inline Matrix4(
|
|
|
+ Matrix4(
|
|
|
float m00, float m01, float m02, float m03,
|
|
|
float m10, float m11, float m12, float m13,
|
|
|
float m20, float m21, float m22, float m23,
|
|
|
- float m30, float m31, float m32, float m33 )
|
|
|
+ float m30, float m31, float m32, float m33)
|
|
|
{
|
|
|
m[0][0] = m00;
|
|
|
m[0][1] = m01;
|
|
|
@@ -117,30 +73,31 @@ namespace CamelotFramework
|
|
|
m[3][3] = m33;
|
|
|
}
|
|
|
|
|
|
- /** Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling 3x3 matrix.
|
|
|
- */
|
|
|
+ Matrix4(const Matrix4& mat)
|
|
|
+ {
|
|
|
+ memcpy(_m, mat._m, 16*sizeof(float));
|
|
|
+ }
|
|
|
|
|
|
- inline Matrix4(const Matrix3& m3x3)
|
|
|
+ /**
|
|
|
+ * @brief Creates a 4x4 transformation matrix with a zero translation part from a rotation/scaling 3x3 matrix.
|
|
|
+ */
|
|
|
+ Matrix4(const Matrix3& mat3)
|
|
|
{
|
|
|
- operator=(IDENTITY);
|
|
|
- operator=(m3x3);
|
|
|
+ m[0][0] = mat3.m[0][0]; m[0][1] = mat3.m[0][1]; m[0][2] = mat3.m[0][2]; m[0][3] = 0.0f;
|
|
|
+ m[1][0] = mat3.m[1][0]; m[1][1] = mat3.m[1][1]; m[1][2] = mat3.m[1][2]; m[1][3] = 0.0f;
|
|
|
+ m[2][0] = mat3.m[2][0]; m[2][1] = mat3.m[2][1]; m[2][2] = mat3.m[2][2]; m[2][3] = 0.0f;
|
|
|
+ m[3][0] = 0.0f; m[3][1] = 0.0f; m[3][2] = 0.0f; m[3][3] = 1.0f;
|
|
|
}
|
|
|
|
|
|
- /** Creates a standard 4x4 transformation matrix with a zero translation part from a rotation/scaling Quaternion.
|
|
|
+ /**
|
|
|
+ * @brief Creates a 4x4 transformation matrix with translation, rotation and scale.
|
|
|
*/
|
|
|
-
|
|
|
- inline Matrix4(const Quaternion& rot)
|
|
|
+ Matrix4(const Vector3& translation, const Quaternion& rot, const Vector3& scale)
|
|
|
{
|
|
|
- Matrix3 m3x3;
|
|
|
- rot.toRotationMatrix(m3x3);
|
|
|
- operator=(IDENTITY);
|
|
|
- operator=(m3x3);
|
|
|
+ setTRS(translation, rot, scale);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- /** Exchange the contents of this matrix with another.
|
|
|
- */
|
|
|
- inline void swap(Matrix4& other)
|
|
|
+ void swap(Matrix4& other)
|
|
|
{
|
|
|
std::swap(m[0][0], other.m[0][0]);
|
|
|
std::swap(m[0][1], other.m[0][1]);
|
|
|
@@ -160,189 +117,126 @@ namespace CamelotFramework
|
|
|
std::swap(m[3][3], other.m[3][3]);
|
|
|
}
|
|
|
|
|
|
- inline float* operator [] ( size_t iRow )
|
|
|
+ float* operator[] (size_t row)
|
|
|
{
|
|
|
- assert( iRow < 4 );
|
|
|
- return m[iRow];
|
|
|
- }
|
|
|
+ assert(row < 4);
|
|
|
|
|
|
- inline const float *operator [] ( size_t iRow ) const
|
|
|
- {
|
|
|
- assert( iRow < 4 );
|
|
|
- return m[iRow];
|
|
|
+ return m[row];
|
|
|
}
|
|
|
|
|
|
- inline Matrix4 concatenate(const Matrix4 &m2) const
|
|
|
+ const float *operator[] (size_t row) const
|
|
|
{
|
|
|
- Matrix4 r;
|
|
|
- r.m[0][0] = m[0][0] * m2.m[0][0] + m[0][1] * m2.m[1][0] + m[0][2] * m2.m[2][0] + m[0][3] * m2.m[3][0];
|
|
|
- r.m[0][1] = m[0][0] * m2.m[0][1] + m[0][1] * m2.m[1][1] + m[0][2] * m2.m[2][1] + m[0][3] * m2.m[3][1];
|
|
|
- r.m[0][2] = m[0][0] * m2.m[0][2] + m[0][1] * m2.m[1][2] + m[0][2] * m2.m[2][2] + m[0][3] * m2.m[3][2];
|
|
|
- r.m[0][3] = m[0][0] * m2.m[0][3] + m[0][1] * m2.m[1][3] + m[0][2] * m2.m[2][3] + m[0][3] * m2.m[3][3];
|
|
|
-
|
|
|
- r.m[1][0] = m[1][0] * m2.m[0][0] + m[1][1] * m2.m[1][0] + m[1][2] * m2.m[2][0] + m[1][3] * m2.m[3][0];
|
|
|
- r.m[1][1] = m[1][0] * m2.m[0][1] + m[1][1] * m2.m[1][1] + m[1][2] * m2.m[2][1] + m[1][3] * m2.m[3][1];
|
|
|
- r.m[1][2] = m[1][0] * m2.m[0][2] + m[1][1] * m2.m[1][2] + m[1][2] * m2.m[2][2] + m[1][3] * m2.m[3][2];
|
|
|
- r.m[1][3] = m[1][0] * m2.m[0][3] + m[1][1] * m2.m[1][3] + m[1][2] * m2.m[2][3] + m[1][3] * m2.m[3][3];
|
|
|
-
|
|
|
- r.m[2][0] = m[2][0] * m2.m[0][0] + m[2][1] * m2.m[1][0] + m[2][2] * m2.m[2][0] + m[2][3] * m2.m[3][0];
|
|
|
- r.m[2][1] = m[2][0] * m2.m[0][1] + m[2][1] * m2.m[1][1] + m[2][2] * m2.m[2][1] + m[2][3] * m2.m[3][1];
|
|
|
- r.m[2][2] = m[2][0] * m2.m[0][2] + m[2][1] * m2.m[1][2] + m[2][2] * m2.m[2][2] + m[2][3] * m2.m[3][2];
|
|
|
- r.m[2][3] = m[2][0] * m2.m[0][3] + m[2][1] * m2.m[1][3] + m[2][2] * m2.m[2][3] + m[2][3] * m2.m[3][3];
|
|
|
-
|
|
|
- r.m[3][0] = m[3][0] * m2.m[0][0] + m[3][1] * m2.m[1][0] + m[3][2] * m2.m[2][0] + m[3][3] * m2.m[3][0];
|
|
|
- r.m[3][1] = m[3][0] * m2.m[0][1] + m[3][1] * m2.m[1][1] + m[3][2] * m2.m[2][1] + m[3][3] * m2.m[3][1];
|
|
|
- r.m[3][2] = m[3][0] * m2.m[0][2] + m[3][1] * m2.m[1][2] + m[3][2] * m2.m[2][2] + m[3][3] * m2.m[3][2];
|
|
|
- r.m[3][3] = m[3][0] * m2.m[0][3] + m[3][1] * m2.m[1][3] + m[3][2] * m2.m[2][3] + m[3][3] * m2.m[3][3];
|
|
|
+ assert(row < 4);
|
|
|
|
|
|
- return r;
|
|
|
+ return m[row];
|
|
|
}
|
|
|
|
|
|
- /** Matrix concatenation using '*'.
|
|
|
- */
|
|
|
- inline Matrix4 operator * ( const Matrix4 &m2 ) const
|
|
|
+ Matrix4 operator* (const Matrix4 &rhs) const
|
|
|
{
|
|
|
- return concatenate( m2 );
|
|
|
- }
|
|
|
+ Matrix4 r;
|
|
|
|
|
|
- /** Vector transformation using '*'.
|
|
|
- @remarks
|
|
|
- Transforms the given 3-D vector by the matrix, projecting the
|
|
|
- result back into <i>w</i> = 1.
|
|
|
- @note
|
|
|
- This means that the initial <i>w</i> is considered to be 1.0,
|
|
|
- and then all the tree elements of the resulting 3-D vector are
|
|
|
- divided by the resulting <i>w</i>.
|
|
|
- */
|
|
|
- inline Vector3 operator * ( const Vector3 &v ) const
|
|
|
- {
|
|
|
- Vector3 r;
|
|
|
+ r.m[0][0] = m[0][0] * rhs.m[0][0] + m[0][1] * rhs.m[1][0] + m[0][2] * rhs.m[2][0] + m[0][3] * rhs.m[3][0];
|
|
|
+ r.m[0][1] = m[0][0] * rhs.m[0][1] + m[0][1] * rhs.m[1][1] + m[0][2] * rhs.m[2][1] + m[0][3] * rhs.m[3][1];
|
|
|
+ r.m[0][2] = m[0][0] * rhs.m[0][2] + m[0][1] * rhs.m[1][2] + m[0][2] * rhs.m[2][2] + m[0][3] * rhs.m[3][2];
|
|
|
+ r.m[0][3] = m[0][0] * rhs.m[0][3] + m[0][1] * rhs.m[1][3] + m[0][2] * rhs.m[2][3] + m[0][3] * rhs.m[3][3];
|
|
|
|
|
|
- float fInvW = 1.0f / ( m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] );
|
|
|
+ r.m[1][0] = m[1][0] * rhs.m[0][0] + m[1][1] * rhs.m[1][0] + m[1][2] * rhs.m[2][0] + m[1][3] * rhs.m[3][0];
|
|
|
+ r.m[1][1] = m[1][0] * rhs.m[0][1] + m[1][1] * rhs.m[1][1] + m[1][2] * rhs.m[2][1] + m[1][3] * rhs.m[3][1];
|
|
|
+ r.m[1][2] = m[1][0] * rhs.m[0][2] + m[1][1] * rhs.m[1][2] + m[1][2] * rhs.m[2][2] + m[1][3] * rhs.m[3][2];
|
|
|
+ r.m[1][3] = m[1][0] * rhs.m[0][3] + m[1][1] * rhs.m[1][3] + m[1][2] * rhs.m[2][3] + m[1][3] * rhs.m[3][3];
|
|
|
|
|
|
- r.x = ( m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] ) * fInvW;
|
|
|
- r.y = ( m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] ) * fInvW;
|
|
|
- r.z = ( m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] ) * fInvW;
|
|
|
+ r.m[2][0] = m[2][0] * rhs.m[0][0] + m[2][1] * rhs.m[1][0] + m[2][2] * rhs.m[2][0] + m[2][3] * rhs.m[3][0];
|
|
|
+ r.m[2][1] = m[2][0] * rhs.m[0][1] + m[2][1] * rhs.m[1][1] + m[2][2] * rhs.m[2][1] + m[2][3] * rhs.m[3][1];
|
|
|
+ r.m[2][2] = m[2][0] * rhs.m[0][2] + m[2][1] * rhs.m[1][2] + m[2][2] * rhs.m[2][2] + m[2][3] * rhs.m[3][2];
|
|
|
+ r.m[2][3] = m[2][0] * rhs.m[0][3] + m[2][1] * rhs.m[1][3] + m[2][2] * rhs.m[2][3] + m[2][3] * rhs.m[3][3];
|
|
|
|
|
|
- return r;
|
|
|
- }
|
|
|
- inline Vector4 operator * (const Vector4& v) const
|
|
|
- {
|
|
|
- return Vector4(
|
|
|
- m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
|
|
|
- m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
|
|
|
- m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
|
|
|
- m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w
|
|
|
- );
|
|
|
- }
|
|
|
- inline Plane operator * (const Plane& p) const
|
|
|
- {
|
|
|
- Plane ret;
|
|
|
- Matrix4 invTrans = inverse().transpose();
|
|
|
- Vector4 v4( p.normal.x, p.normal.y, p.normal.z, p.d );
|
|
|
- v4 = invTrans * v4;
|
|
|
- ret.normal.x = v4.x;
|
|
|
- ret.normal.y = v4.y;
|
|
|
- ret.normal.z = v4.z;
|
|
|
- ret.d = v4.w / ret.normal.normalize();
|
|
|
-
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ r.m[3][0] = m[3][0] * rhs.m[0][0] + m[3][1] * rhs.m[1][0] + m[3][2] * rhs.m[2][0] + m[3][3] * rhs.m[3][0];
|
|
|
+ r.m[3][1] = m[3][0] * rhs.m[0][1] + m[3][1] * rhs.m[1][1] + m[3][2] * rhs.m[2][1] + m[3][3] * rhs.m[3][1];
|
|
|
+ r.m[3][2] = m[3][0] * rhs.m[0][2] + m[3][1] * rhs.m[1][2] + m[3][2] * rhs.m[2][2] + m[3][3] * rhs.m[3][2];
|
|
|
+ r.m[3][3] = m[3][0] * rhs.m[0][3] + m[3][1] * rhs.m[1][3] + m[3][2] * rhs.m[2][3] + m[3][3] * rhs.m[3][3];
|
|
|
|
|
|
+ return r;
|
|
|
+ }
|
|
|
|
|
|
- /** Matrix addition.
|
|
|
- */
|
|
|
- inline Matrix4 operator + ( const Matrix4 &m2 ) const
|
|
|
+ Matrix4 operator+ (const Matrix4 &rhs) const
|
|
|
{
|
|
|
Matrix4 r;
|
|
|
|
|
|
- r.m[0][0] = m[0][0] + m2.m[0][0];
|
|
|
- r.m[0][1] = m[0][1] + m2.m[0][1];
|
|
|
- r.m[0][2] = m[0][2] + m2.m[0][2];
|
|
|
- r.m[0][3] = m[0][3] + m2.m[0][3];
|
|
|
+ r.m[0][0] = m[0][0] + rhs.m[0][0];
|
|
|
+ r.m[0][1] = m[0][1] + rhs.m[0][1];
|
|
|
+ r.m[0][2] = m[0][2] + rhs.m[0][2];
|
|
|
+ r.m[0][3] = m[0][3] + rhs.m[0][3];
|
|
|
|
|
|
- r.m[1][0] = m[1][0] + m2.m[1][0];
|
|
|
- r.m[1][1] = m[1][1] + m2.m[1][1];
|
|
|
- r.m[1][2] = m[1][2] + m2.m[1][2];
|
|
|
- r.m[1][3] = m[1][3] + m2.m[1][3];
|
|
|
+ r.m[1][0] = m[1][0] + rhs.m[1][0];
|
|
|
+ r.m[1][1] = m[1][1] + rhs.m[1][1];
|
|
|
+ r.m[1][2] = m[1][2] + rhs.m[1][2];
|
|
|
+ r.m[1][3] = m[1][3] + rhs.m[1][3];
|
|
|
|
|
|
- r.m[2][0] = m[2][0] + m2.m[2][0];
|
|
|
- r.m[2][1] = m[2][1] + m2.m[2][1];
|
|
|
- r.m[2][2] = m[2][2] + m2.m[2][2];
|
|
|
- r.m[2][3] = m[2][3] + m2.m[2][3];
|
|
|
+ r.m[2][0] = m[2][0] + rhs.m[2][0];
|
|
|
+ r.m[2][1] = m[2][1] + rhs.m[2][1];
|
|
|
+ r.m[2][2] = m[2][2] + rhs.m[2][2];
|
|
|
+ r.m[2][3] = m[2][3] + rhs.m[2][3];
|
|
|
|
|
|
- r.m[3][0] = m[3][0] + m2.m[3][0];
|
|
|
- r.m[3][1] = m[3][1] + m2.m[3][1];
|
|
|
- r.m[3][2] = m[3][2] + m2.m[3][2];
|
|
|
- r.m[3][3] = m[3][3] + m2.m[3][3];
|
|
|
+ r.m[3][0] = m[3][0] + rhs.m[3][0];
|
|
|
+ r.m[3][1] = m[3][1] + rhs.m[3][1];
|
|
|
+ r.m[3][2] = m[3][2] + rhs.m[3][2];
|
|
|
+ r.m[3][3] = m[3][3] + rhs.m[3][3];
|
|
|
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
- /** Matrix subtraction.
|
|
|
- */
|
|
|
- inline Matrix4 operator - ( const Matrix4 &m2 ) const
|
|
|
+ Matrix4 operator- (const Matrix4 &rhs) const
|
|
|
{
|
|
|
Matrix4 r;
|
|
|
- r.m[0][0] = m[0][0] - m2.m[0][0];
|
|
|
- r.m[0][1] = m[0][1] - m2.m[0][1];
|
|
|
- r.m[0][2] = m[0][2] - m2.m[0][2];
|
|
|
- r.m[0][3] = m[0][3] - m2.m[0][3];
|
|
|
-
|
|
|
- r.m[1][0] = m[1][0] - m2.m[1][0];
|
|
|
- r.m[1][1] = m[1][1] - m2.m[1][1];
|
|
|
- r.m[1][2] = m[1][2] - m2.m[1][2];
|
|
|
- r.m[1][3] = m[1][3] - m2.m[1][3];
|
|
|
-
|
|
|
- r.m[2][0] = m[2][0] - m2.m[2][0];
|
|
|
- r.m[2][1] = m[2][1] - m2.m[2][1];
|
|
|
- r.m[2][2] = m[2][2] - m2.m[2][2];
|
|
|
- r.m[2][3] = m[2][3] - m2.m[2][3];
|
|
|
-
|
|
|
- r.m[3][0] = m[3][0] - m2.m[3][0];
|
|
|
- r.m[3][1] = m[3][1] - m2.m[3][1];
|
|
|
- r.m[3][2] = m[3][2] - m2.m[3][2];
|
|
|
- r.m[3][3] = m[3][3] - m2.m[3][3];
|
|
|
+ r.m[0][0] = m[0][0] - rhs.m[0][0];
|
|
|
+ r.m[0][1] = m[0][1] - rhs.m[0][1];
|
|
|
+ r.m[0][2] = m[0][2] - rhs.m[0][2];
|
|
|
+ r.m[0][3] = m[0][3] - rhs.m[0][3];
|
|
|
+
|
|
|
+ r.m[1][0] = m[1][0] - rhs.m[1][0];
|
|
|
+ r.m[1][1] = m[1][1] - rhs.m[1][1];
|
|
|
+ r.m[1][2] = m[1][2] - rhs.m[1][2];
|
|
|
+ r.m[1][3] = m[1][3] - rhs.m[1][3];
|
|
|
+
|
|
|
+ r.m[2][0] = m[2][0] - rhs.m[2][0];
|
|
|
+ r.m[2][1] = m[2][1] - rhs.m[2][1];
|
|
|
+ r.m[2][2] = m[2][2] - rhs.m[2][2];
|
|
|
+ r.m[2][3] = m[2][3] - rhs.m[2][3];
|
|
|
+
|
|
|
+ r.m[3][0] = m[3][0] - rhs.m[3][0];
|
|
|
+ r.m[3][1] = m[3][1] - rhs.m[3][1];
|
|
|
+ r.m[3][2] = m[3][2] - rhs.m[3][2];
|
|
|
+ r.m[3][3] = m[3][3] - rhs.m[3][3];
|
|
|
|
|
|
return r;
|
|
|
}
|
|
|
|
|
|
- /** Tests 2 matrices for equality.
|
|
|
- */
|
|
|
- inline bool operator == ( const Matrix4& m2 ) const
|
|
|
+ inline bool operator== (const Matrix4& rhs ) const
|
|
|
{
|
|
|
if(
|
|
|
- m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] ||
|
|
|
- m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] ||
|
|
|
- m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] ||
|
|
|
- m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3] )
|
|
|
+ m[0][0] != rhs.m[0][0] || m[0][1] != rhs.m[0][1] || m[0][2] != rhs.m[0][2] || m[0][3] != rhs.m[0][3] ||
|
|
|
+ m[1][0] != rhs.m[1][0] || m[1][1] != rhs.m[1][1] || m[1][2] != rhs.m[1][2] || m[1][3] != rhs.m[1][3] ||
|
|
|
+ m[2][0] != rhs.m[2][0] || m[2][1] != rhs.m[2][1] || m[2][2] != rhs.m[2][2] || m[2][3] != rhs.m[2][3] ||
|
|
|
+ m[3][0] != rhs.m[3][0] || m[3][1] != rhs.m[3][1] || m[3][2] != rhs.m[3][2] || m[3][3] != rhs.m[3][3] )
|
|
|
return false;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- /** Tests 2 matrices for inequality.
|
|
|
- */
|
|
|
- inline bool operator != ( const Matrix4& m2 ) const
|
|
|
+ inline bool operator!= (const Matrix4& rhs) const
|
|
|
{
|
|
|
- if(
|
|
|
- m[0][0] != m2.m[0][0] || m[0][1] != m2.m[0][1] || m[0][2] != m2.m[0][2] || m[0][3] != m2.m[0][3] ||
|
|
|
- m[1][0] != m2.m[1][0] || m[1][1] != m2.m[1][1] || m[1][2] != m2.m[1][2] || m[1][3] != m2.m[1][3] ||
|
|
|
- m[2][0] != m2.m[2][0] || m[2][1] != m2.m[2][1] || m[2][2] != m2.m[2][2] || m[2][3] != m2.m[2][3] ||
|
|
|
- m[3][0] != m2.m[3][0] || m[3][1] != m2.m[3][1] || m[3][2] != m2.m[3][2] || m[3][3] != m2.m[3][3] )
|
|
|
- return true;
|
|
|
- return false;
|
|
|
+ return !operator==(rhs);
|
|
|
}
|
|
|
|
|
|
- /** Assignment from 3x3 matrix.
|
|
|
- */
|
|
|
- inline void operator = ( const Matrix3& mat3 )
|
|
|
- {
|
|
|
- m[0][0] = mat3.m[0][0]; m[0][1] = mat3.m[0][1]; m[0][2] = mat3.m[0][2];
|
|
|
- m[1][0] = mat3.m[1][0]; m[1][1] = mat3.m[1][1]; m[1][2] = mat3.m[1][2];
|
|
|
- m[2][0] = mat3.m[2][0]; m[2][1] = mat3.m[2][1]; m[2][2] = mat3.m[2][2];
|
|
|
- }
|
|
|
+ Matrix4 operator*(float rhs) const
|
|
|
+ {
|
|
|
+ return Matrix4(
|
|
|
+ rhs*m[0][0], rhs*m[0][1], rhs*m[0][2], rhs*m[0][3],
|
|
|
+ rhs*m[1][0], rhs*m[1][1], rhs*m[1][2], rhs*m[1][3],
|
|
|
+ rhs*m[2][0], rhs*m[2][1], rhs*m[2][2], rhs*m[2][3],
|
|
|
+ rhs*m[3][0], rhs*m[3][1], rhs*m[3][2], rhs*m[3][3]);
|
|
|
+ }
|
|
|
|
|
|
- inline Matrix4 transpose(void) const
|
|
|
+ Matrix4 transpose() const
|
|
|
{
|
|
|
return Matrix4(m[0][0], m[1][0], m[2][0], m[3][0],
|
|
|
m[0][1], m[1][1], m[2][1], m[3][1],
|
|
|
@@ -350,118 +244,10 @@ namespace CamelotFramework
|
|
|
m[0][3], m[1][3], m[2][3], m[3][3]);
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- -----------------------------------------------------------------------
|
|
|
- Translation Transformation
|
|
|
- -----------------------------------------------------------------------
|
|
|
- */
|
|
|
- /** Sets the translation transformation part of the matrix.
|
|
|
- */
|
|
|
- inline void setTrans( const Vector3& v )
|
|
|
- {
|
|
|
- m[0][3] = v.x;
|
|
|
- m[1][3] = v.y;
|
|
|
- m[2][3] = v.z;
|
|
|
- }
|
|
|
-
|
|
|
- /** Extracts the translation transformation part of the matrix.
|
|
|
+ /**
|
|
|
+ * @brief Extracts the rotation/scaling part of the Matrix as a 3x3 matrix.
|
|
|
*/
|
|
|
- inline Vector3 getTrans() const
|
|
|
- {
|
|
|
- return Vector3(m[0][3], m[1][3], m[2][3]);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /** Builds a translation matrix
|
|
|
- */
|
|
|
- inline void makeTrans( const Vector3& v )
|
|
|
- {
|
|
|
- m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = v.x;
|
|
|
- m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = v.y;
|
|
|
- m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = v.z;
|
|
|
- m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 1.0;
|
|
|
- }
|
|
|
-
|
|
|
- inline void makeTrans( float tx, float ty, float tz )
|
|
|
- {
|
|
|
- m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = tx;
|
|
|
- m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = ty;
|
|
|
- m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = tz;
|
|
|
- m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 1.0;
|
|
|
- }
|
|
|
-
|
|
|
- /** Gets a translation matrix.
|
|
|
- */
|
|
|
- inline static Matrix4 getTrans( const Vector3& v )
|
|
|
- {
|
|
|
- Matrix4 r;
|
|
|
-
|
|
|
- r.m[0][0] = 1.0; r.m[0][1] = 0.0; r.m[0][2] = 0.0; r.m[0][3] = v.x;
|
|
|
- r.m[1][0] = 0.0; r.m[1][1] = 1.0; r.m[1][2] = 0.0; r.m[1][3] = v.y;
|
|
|
- r.m[2][0] = 0.0; r.m[2][1] = 0.0; r.m[2][2] = 1.0; r.m[2][3] = v.z;
|
|
|
- r.m[3][0] = 0.0; r.m[3][1] = 0.0; r.m[3][2] = 0.0; r.m[3][3] = 1.0;
|
|
|
-
|
|
|
- return r;
|
|
|
- }
|
|
|
-
|
|
|
- /** Gets a translation matrix - variation for not using a vector.
|
|
|
- */
|
|
|
- inline static Matrix4 getTrans( float t_x, float t_y, float t_z )
|
|
|
- {
|
|
|
- Matrix4 r;
|
|
|
-
|
|
|
- r.m[0][0] = 1.0; r.m[0][1] = 0.0; r.m[0][2] = 0.0; r.m[0][3] = t_x;
|
|
|
- r.m[1][0] = 0.0; r.m[1][1] = 1.0; r.m[1][2] = 0.0; r.m[1][3] = t_y;
|
|
|
- r.m[2][0] = 0.0; r.m[2][1] = 0.0; r.m[2][2] = 1.0; r.m[2][3] = t_z;
|
|
|
- r.m[3][0] = 0.0; r.m[3][1] = 0.0; r.m[3][2] = 0.0; r.m[3][3] = 1.0;
|
|
|
-
|
|
|
- return r;
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- -----------------------------------------------------------------------
|
|
|
- Scale Transformation
|
|
|
- -----------------------------------------------------------------------
|
|
|
- */
|
|
|
- /** Sets the scale part of the matrix.
|
|
|
- */
|
|
|
- inline void setScale( const Vector3& v )
|
|
|
- {
|
|
|
- m[0][0] = v.x;
|
|
|
- m[1][1] = v.y;
|
|
|
- m[2][2] = v.z;
|
|
|
- }
|
|
|
-
|
|
|
- /** Gets a scale matrix.
|
|
|
- */
|
|
|
- inline static Matrix4 getScale( const Vector3& v )
|
|
|
- {
|
|
|
- Matrix4 r;
|
|
|
- r.m[0][0] = v.x; r.m[0][1] = 0.0; r.m[0][2] = 0.0; r.m[0][3] = 0.0;
|
|
|
- r.m[1][0] = 0.0; r.m[1][1] = v.y; r.m[1][2] = 0.0; r.m[1][3] = 0.0;
|
|
|
- r.m[2][0] = 0.0; r.m[2][1] = 0.0; r.m[2][2] = v.z; r.m[2][3] = 0.0;
|
|
|
- r.m[3][0] = 0.0; r.m[3][1] = 0.0; r.m[3][2] = 0.0; r.m[3][3] = 1.0;
|
|
|
-
|
|
|
- return r;
|
|
|
- }
|
|
|
-
|
|
|
- /** Gets a scale matrix - variation for not using a vector.
|
|
|
- */
|
|
|
- inline static Matrix4 getScale( float s_x, float s_y, float s_z )
|
|
|
- {
|
|
|
- Matrix4 r;
|
|
|
- r.m[0][0] = s_x; r.m[0][1] = 0.0; r.m[0][2] = 0.0; r.m[0][3] = 0.0;
|
|
|
- r.m[1][0] = 0.0; r.m[1][1] = s_y; r.m[1][2] = 0.0; r.m[1][3] = 0.0;
|
|
|
- r.m[2][0] = 0.0; r.m[2][1] = 0.0; r.m[2][2] = s_z; r.m[2][3] = 0.0;
|
|
|
- r.m[3][0] = 0.0; r.m[3][1] = 0.0; r.m[3][2] = 0.0; r.m[3][3] = 1.0;
|
|
|
-
|
|
|
- return r;
|
|
|
- }
|
|
|
-
|
|
|
- /** Extracts the rotation / scaling part of the Matrix as a 3x3 matrix.
|
|
|
- @param m3x3 Destination Matrix3
|
|
|
- */
|
|
|
- inline void extract3x3Matrix(Matrix3& m3x3) const
|
|
|
+ void extract3x3Matrix(Matrix3& m3x3) const
|
|
|
{
|
|
|
m3x3.m[0][0] = m[0][0];
|
|
|
m3x3.m[0][1] = m[0][1];
|
|
|
@@ -472,190 +258,149 @@ namespace CamelotFramework
|
|
|
m3x3.m[2][0] = m[2][0];
|
|
|
m3x3.m[2][1] = m[2][1];
|
|
|
m3x3.m[2][2] = m[2][2];
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /** Determines if this matrix involves a scaling. */
|
|
|
- inline bool hasScale() const
|
|
|
- {
|
|
|
- // check magnitude of column vectors (==local axes)
|
|
|
- float t = m[0][0] * m[0][0] + m[1][0] * m[1][0] + m[2][0] * m[2][0];
|
|
|
- if (!Math::RealEqual(t, 1.0, (float)1e-04))
|
|
|
- return true;
|
|
|
- t = m[0][1] * m[0][1] + m[1][1] * m[1][1] + m[2][1] * m[2][1];
|
|
|
- if (!Math::RealEqual(t, 1.0, (float)1e-04))
|
|
|
- return true;
|
|
|
- t = m[0][2] * m[0][2] + m[1][2] * m[1][2] + m[2][2] * m[2][2];
|
|
|
- if (!Math::RealEqual(t, 1.0, (float)1e-04))
|
|
|
- return true;
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- /** Determines if this matrix involves a negative scaling. */
|
|
|
- inline bool hasNegativeScale() const
|
|
|
- {
|
|
|
- return determinant() < 0;
|
|
|
- }
|
|
|
-
|
|
|
- /** Extracts the rotation / scaling part as a quaternion from the Matrix.
|
|
|
- */
|
|
|
- inline Quaternion extractQuaternion() const
|
|
|
- {
|
|
|
- Matrix3 m3x3;
|
|
|
- extract3x3Matrix(m3x3);
|
|
|
- return Quaternion(m3x3);
|
|
|
}
|
|
|
|
|
|
- static const Matrix4 ZERO;
|
|
|
- static const Matrix4 IDENTITY;
|
|
|
- /** Useful little matrix which takes 2D clipspace {-1, 1} to {0,1}
|
|
|
- and inverts the Y. */
|
|
|
- static const Matrix4 CLIPSPACE2DTOIMAGESPACE;
|
|
|
-
|
|
|
- inline Matrix4 operator*(float scalar) const
|
|
|
- {
|
|
|
- return Matrix4(
|
|
|
- scalar*m[0][0], scalar*m[0][1], scalar*m[0][2], scalar*m[0][3],
|
|
|
- scalar*m[1][0], scalar*m[1][1], scalar*m[1][2], scalar*m[1][3],
|
|
|
- scalar*m[2][0], scalar*m[2][1], scalar*m[2][2], scalar*m[2][3],
|
|
|
- scalar*m[3][0], scalar*m[3][1], scalar*m[3][2], scalar*m[3][3]);
|
|
|
- }
|
|
|
-
|
|
|
- /** Function for writing to a stream.
|
|
|
- */
|
|
|
- inline CM_UTILITY_EXPORT friend std::ostream& operator <<
|
|
|
- ( std::ostream& o, const Matrix4& mat )
|
|
|
- {
|
|
|
- o << "Matrix4(";
|
|
|
- for (size_t i = 0; i < 4; ++i)
|
|
|
- {
|
|
|
- o << " row" << (unsigned)i << "{";
|
|
|
- for(size_t j = 0; j < 4; ++j)
|
|
|
- {
|
|
|
- o << mat[i][j] << " ";
|
|
|
- }
|
|
|
- o << "}";
|
|
|
- }
|
|
|
- o << ")";
|
|
|
- return o;
|
|
|
- }
|
|
|
-
|
|
|
Matrix4 adjoint() const;
|
|
|
float determinant() const;
|
|
|
Matrix4 inverse() const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @brief Creates a matrix from translation, rotation and scale.
|
|
|
+ *
|
|
|
+ * @note The transformation are applied in scale->rotation->translation order.
|
|
|
+ */
|
|
|
+ void setTRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
|
|
|
|
|
|
- /** Building a Matrix4 from orientation / scale / position.
|
|
|
- @remarks
|
|
|
- Transform is performed in the order scale, rotate, translation, i.e. translation is independent
|
|
|
- of orientation axes, scale does not affect size of translation, rotation and scaling are always
|
|
|
- centered on the origin.
|
|
|
- */
|
|
|
- void makeTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation);
|
|
|
-
|
|
|
- /** Building an inverse Matrix4 from orientation / scale / position.
|
|
|
- @remarks
|
|
|
- As makeTransform except it build the inverse given the same data as makeTransform, so
|
|
|
- performing -translation, -rotate, 1/scale in that order.
|
|
|
- */
|
|
|
- void makeInverseTransform(const Vector3& position, const Vector3& scale, const Quaternion& orientation);
|
|
|
-
|
|
|
- /** Decompose a Matrix4 to orientation / scale / position.
|
|
|
- */
|
|
|
- void decomposition(Vector3& position, Vector3& scale, Quaternion& orientation) const;
|
|
|
-
|
|
|
- /** Check whether or not the matrix is affine matrix.
|
|
|
- @remarks
|
|
|
- An affine matrix is a 4x4 matrix with row 3 equal to (0, 0, 0, 1),
|
|
|
- e.g. no projective coefficients.
|
|
|
- */
|
|
|
- inline bool isAffine(void) const
|
|
|
+ /**
|
|
|
+ * @brief Creates a matrix from inverse translation, rotation and scale.
|
|
|
+ *
|
|
|
+ * @note This is cheaper than "setTRS" and then performing "inverse".
|
|
|
+ */
|
|
|
+ void setInverseTRS(const Vector3& translation, const Quaternion& rotation, const Vector3& scale);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @brief Decompose a Matrix4 to translation, rotation and scale.
|
|
|
+ *
|
|
|
+ * @note Matrix must consist only of translation, rotation and uniform scale transformations,
|
|
|
+ * otherwise accurate results are not guaranteed. Applying non-uniform scale guarantees
|
|
|
+ * results will not be accurate.
|
|
|
+ */
|
|
|
+ void decomposition(Vector3& position, Quaternion& rotation, Vector3& scale) const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @brief Check whether or not the matrix is affine matrix.
|
|
|
+ *
|
|
|
+ * @note An affine matrix is a 4x4 matrix with row 3 equal to (0, 0, 0, 1),
|
|
|
+ * i.e. no projective coefficients.
|
|
|
+ */
|
|
|
+ bool isAffine() const
|
|
|
{
|
|
|
return m[3][0] == 0 && m[3][1] == 0 && m[3][2] == 0 && m[3][3] == 1;
|
|
|
}
|
|
|
|
|
|
- /** Returns the inverse of the affine matrix.
|
|
|
- @note
|
|
|
- The matrix must be an affine matrix. @see Matrix4::isAffine.
|
|
|
- */
|
|
|
+ /**
|
|
|
+ * @brief Returns the inverse of the affine matrix.
|
|
|
+ *
|
|
|
+ * @note Matrix must be affine.
|
|
|
+ */
|
|
|
Matrix4 inverseAffine(void) const;
|
|
|
|
|
|
- /** Concatenate two affine matrices.
|
|
|
- @note
|
|
|
- The matrices must be affine matrix. @see Matrix4::isAffine.
|
|
|
- */
|
|
|
- inline Matrix4 concatenateAffine(const Matrix4 &m2) const
|
|
|
+ /**
|
|
|
+ * @brief Concatenate two affine matrices.
|
|
|
+ *
|
|
|
+ * @note Both matrices must be affine.
|
|
|
+ */
|
|
|
+ Matrix4 concatenateAffine(const Matrix4 &other) const
|
|
|
{
|
|
|
- assert(isAffine() && m2.isAffine());
|
|
|
+ assert(isAffine() && other.isAffine());
|
|
|
|
|
|
return Matrix4(
|
|
|
- m[0][0] * m2.m[0][0] + m[0][1] * m2.m[1][0] + m[0][2] * m2.m[2][0],
|
|
|
- m[0][0] * m2.m[0][1] + m[0][1] * m2.m[1][1] + m[0][2] * m2.m[2][1],
|
|
|
- m[0][0] * m2.m[0][2] + m[0][1] * m2.m[1][2] + m[0][2] * m2.m[2][2],
|
|
|
- m[0][0] * m2.m[0][3] + m[0][1] * m2.m[1][3] + m[0][2] * m2.m[2][3] + m[0][3],
|
|
|
+ m[0][0] * other.m[0][0] + m[0][1] * other.m[1][0] + m[0][2] * other.m[2][0],
|
|
|
+ m[0][0] * other.m[0][1] + m[0][1] * other.m[1][1] + m[0][2] * other.m[2][1],
|
|
|
+ m[0][0] * other.m[0][2] + m[0][1] * other.m[1][2] + m[0][2] * other.m[2][2],
|
|
|
+ m[0][0] * other.m[0][3] + m[0][1] * other.m[1][3] + m[0][2] * other.m[2][3] + m[0][3],
|
|
|
|
|
|
- m[1][0] * m2.m[0][0] + m[1][1] * m2.m[1][0] + m[1][2] * m2.m[2][0],
|
|
|
- m[1][0] * m2.m[0][1] + m[1][1] * m2.m[1][1] + m[1][2] * m2.m[2][1],
|
|
|
- m[1][0] * m2.m[0][2] + m[1][1] * m2.m[1][2] + m[1][2] * m2.m[2][2],
|
|
|
- m[1][0] * m2.m[0][3] + m[1][1] * m2.m[1][3] + m[1][2] * m2.m[2][3] + m[1][3],
|
|
|
+ m[1][0] * other.m[0][0] + m[1][1] * other.m[1][0] + m[1][2] * other.m[2][0],
|
|
|
+ m[1][0] * other.m[0][1] + m[1][1] * other.m[1][1] + m[1][2] * other.m[2][1],
|
|
|
+ m[1][0] * other.m[0][2] + m[1][1] * other.m[1][2] + m[1][2] * other.m[2][2],
|
|
|
+ m[1][0] * other.m[0][3] + m[1][1] * other.m[1][3] + m[1][2] * other.m[2][3] + m[1][3],
|
|
|
|
|
|
- m[2][0] * m2.m[0][0] + m[2][1] * m2.m[1][0] + m[2][2] * m2.m[2][0],
|
|
|
- m[2][0] * m2.m[0][1] + m[2][1] * m2.m[1][1] + m[2][2] * m2.m[2][1],
|
|
|
- m[2][0] * m2.m[0][2] + m[2][1] * m2.m[1][2] + m[2][2] * m2.m[2][2],
|
|
|
- m[2][0] * m2.m[0][3] + m[2][1] * m2.m[1][3] + m[2][2] * m2.m[2][3] + m[2][3],
|
|
|
+ m[2][0] * other.m[0][0] + m[2][1] * other.m[1][0] + m[2][2] * other.m[2][0],
|
|
|
+ m[2][0] * other.m[0][1] + m[2][1] * other.m[1][1] + m[2][2] * other.m[2][1],
|
|
|
+ m[2][0] * other.m[0][2] + m[2][1] * other.m[1][2] + m[2][2] * other.m[2][2],
|
|
|
+ m[2][0] * other.m[0][3] + m[2][1] * other.m[1][3] + m[2][2] * other.m[2][3] + m[2][3],
|
|
|
|
|
|
0, 0, 0, 1);
|
|
|
}
|
|
|
|
|
|
- /** 3-D Vector transformation specially for an affine matrix.
|
|
|
- @remarks
|
|
|
- Transforms the given 3-D vector by the matrix, projecting the
|
|
|
- result back into <i>w</i> = 1.
|
|
|
- @note
|
|
|
- The matrix must be an affine matrix. @see Matrix4::isAffine.
|
|
|
- */
|
|
|
- inline Vector3 transformAffine(const Vector3& v) const
|
|
|
+ /**
|
|
|
+ * @brief Transform a 3D vector by this matrix.
|
|
|
+ *
|
|
|
+ * @note Matrix must be affine, if it is not use "transform" method.
|
|
|
+ */
|
|
|
+ Vector3 transform3x4(const Vector3& v) const
|
|
|
{
|
|
|
- assert(isAffine());
|
|
|
-
|
|
|
return Vector3(
|
|
|
m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3],
|
|
|
m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3],
|
|
|
m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3]);
|
|
|
}
|
|
|
|
|
|
- /** 4-D Vector transformation specially for an affine matrix.
|
|
|
- @note
|
|
|
- The matrix must be an affine matrix. @see Matrix4::isAffine.
|
|
|
- */
|
|
|
- inline Vector4 transformAffine(const Vector4& v) const
|
|
|
+ /**
|
|
|
+ * @brief Transform a 4D vector by this matrix.
|
|
|
+ *
|
|
|
+ * @note Matrix must be affine, if it is not use "transform" method.
|
|
|
+ */
|
|
|
+ Vector4 transform3x4(const Vector4& v) const
|
|
|
{
|
|
|
- assert(isAffine());
|
|
|
-
|
|
|
return Vector4(
|
|
|
m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
|
|
|
m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
|
|
|
m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
|
|
|
v.w);
|
|
|
}
|
|
|
- };
|
|
|
|
|
|
- /* Removed from Vector4 and made a non-member here because otherwise
|
|
|
- CmMatrix4.h and CmVector4.h have to try to include and inline each
|
|
|
- other, which frankly doesn't work ;)
|
|
|
- */
|
|
|
- inline Vector4 operator * (const Vector4& v, const Matrix4& mat)
|
|
|
- {
|
|
|
- return Vector4(
|
|
|
- v.x*mat[0][0] + v.y*mat[1][0] + v.z*mat[2][0] + v.w*mat[3][0],
|
|
|
- v.x*mat[0][1] + v.y*mat[1][1] + v.z*mat[2][1] + v.w*mat[3][1],
|
|
|
- v.x*mat[0][2] + v.y*mat[1][2] + v.z*mat[2][2] + v.w*mat[3][2],
|
|
|
- v.x*mat[0][3] + v.y*mat[1][3] + v.z*mat[2][3] + v.w*mat[3][3]
|
|
|
- );
|
|
|
- }
|
|
|
- /** @} */
|
|
|
- /** @} */
|
|
|
+ /**
|
|
|
+ * @brief Transform a 3D vector by this matrix.
|
|
|
+ *
|
|
|
+ * @note w component of the vector is assumed to be 1. After transformation all components
|
|
|
+ * are projected back so that w remains 1.
|
|
|
+ *
|
|
|
+ * If your matrix doesn't contain projection components use "transform3x4" method as it is faster.
|
|
|
+ */
|
|
|
+ Vector3 transform(const Vector3 &v) const
|
|
|
+ {
|
|
|
+ Vector3 r;
|
|
|
+
|
|
|
+ float fInvW = 1.0f / (m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3]);
|
|
|
+
|
|
|
+ r.x = ( m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] ) * fInvW;
|
|
|
+ r.y = ( m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] ) * fInvW;
|
|
|
+ r.z = ( m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] ) * fInvW;
|
|
|
+
|
|
|
+ return r;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @brief Transform a 3D vector by this matrix.
|
|
|
+ *
|
|
|
+ * @note After transformation all components are projected back so that w remains 1.
|
|
|
+ *
|
|
|
+ * If your matrix doesn't contain projection components use "transform3x4" method as it is faster.
|
|
|
+ */
|
|
|
+ Vector4 transform(const Vector4& v) const
|
|
|
+ {
|
|
|
+ return Vector4(
|
|
|
+ m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
|
|
|
+ m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
|
|
|
+ m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
|
|
|
+ m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ static const Matrix4 ZERO;
|
|
|
+ static const Matrix4 IDENTITY;
|
|
|
+ };
|
|
|
|
|
|
CM_ALLOW_MEMCPY_SERIALIZATION(Matrix4);
|
|
|
-}
|
|
|
-#endif
|
|
|
+}
|