616 lines
21 KiB
C++
616 lines
21 KiB
C++
// Copyright (C) 2002-2006 Nikolaus Gebhardt
|
|
// This file is part of the "Irrlicht Engine".
|
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
|
|
|
#pragma once
|
|
|
|
#include "irrMath.h"
|
|
#include "..\\..\\include\\matrix4.h"
|
|
|
|
#include "Vector3D.h"
|
|
|
|
namespace Irrlicht
|
|
{
|
|
namespace Core
|
|
{
|
|
|
|
/// <summary>
|
|
/// 4x4 matrix. Mostly used as transformation matrix for 3d calculations.
|
|
/// Matrix4 is mainly used by the Irrlicht engine for doing transformations.
|
|
/// The matrix is a D3D style matrix, row major with translations in the 4th row.
|
|
/// This class has been ported directly from the native C++ Irrlicht Engine, so it may not
|
|
/// be 100% complete yet and the design may not be 100% .NET like.
|
|
/// </summary>
|
|
public __value struct Matrix4
|
|
{
|
|
public:
|
|
|
|
/// <summary> Constructor </summary>
|
|
Matrix4()
|
|
{
|
|
//Members = new float __gc[16];
|
|
MakeIdentity();
|
|
}
|
|
|
|
/// <summary> Set matrix to identity. </summary>
|
|
void MakeIdentity()
|
|
{
|
|
for (int i=0; i<16; ++i)
|
|
Members[i] = 0.0f;
|
|
|
|
Members[0] = Members[5] = Members[10] = Members[15] = 1;
|
|
}
|
|
|
|
/// <summary> Direct accessing every row and colum of the matrix values </summary>
|
|
__property inline float get_M(int row, int col)
|
|
{
|
|
if (row < 0 || row >= 4 ||
|
|
col < 0 || col >= 4)
|
|
throw new System::Exception(new System::String("Invalid index for accessing matrix members"));
|
|
|
|
return Members[col * 4 + row];
|
|
}
|
|
|
|
/// <summary> Direct accessing every row and colum of the matrix values </summary>
|
|
inline void set_M(int row, int col, float v)
|
|
{
|
|
if (row < 0 || row >= 4 ||
|
|
col < 0 || col >= 4)
|
|
throw new System::Exception(new System::String("Invalid index for accessing matrix members"));
|
|
|
|
Members[col * 4 + row] = v;
|
|
}
|
|
|
|
/*
|
|
/// <summary> Sets this matrix equal to the other matrix.</summary>
|
|
matrix4& operator=(const matrix4 &other);
|
|
|
|
/// <summary> Returns true if other matrix is equal to this matrix.</summary>
|
|
bool operator==(const matrix4 &other) const;
|
|
|
|
/// <summary> Returns true if other matrix is not equal to this matrix.</summary>
|
|
bool operator!=(const matrix4 &other) const;
|
|
|
|
/// <summary> Multiply by another matrix.</summary>
|
|
matrix4& operator*=(const matrix4& other);
|
|
*/
|
|
|
|
/// <summary> Multiply by another matrix. </summary>
|
|
static Matrix4 op_Multiply(Matrix4 a, Matrix4 b)
|
|
{
|
|
Matrix4 tmtrx;
|
|
|
|
#define m1 a.Members
|
|
#define m2 b.Members
|
|
#define m3 tmtrx.Members
|
|
|
|
m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
|
|
m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
|
|
m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
|
|
m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
|
|
|
|
m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
|
|
m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
|
|
m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
|
|
m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
|
|
|
|
m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
|
|
m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
|
|
m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
|
|
m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
|
|
|
|
m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
|
|
m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
|
|
m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
|
|
m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
|
|
|
|
#undef m1
|
|
#undef m2
|
|
#undef m3
|
|
|
|
return tmtrx;
|
|
}
|
|
|
|
/// <summary> Returns true if the matrix is the identity matrix. </summary>
|
|
inline bool IsIdentity()
|
|
{
|
|
for (int i=0; i<4; ++i)
|
|
for (int j=0; j<4; ++j)
|
|
if (j != i)
|
|
{
|
|
if (get_M(i,j) < -0.0000001f ||
|
|
get_M(i,j) > 0.0000001f)
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (get_M(i,j) < 0.9999999f ||
|
|
get_M(i,j) > 1.0000001f)
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary> Set the translation of the current matrix. Will erase any previous values.</summary>
|
|
void SetTranslation( const Vector3D translation )
|
|
{
|
|
Members[12] = translation.X;
|
|
Members[13] = translation.Y;
|
|
Members[14] = translation.Z;
|
|
}
|
|
|
|
/// <summary> Gets the current translation</summary>
|
|
Vector3D GetTranslation()
|
|
{
|
|
return Vector3D(Members[12], Members[13], Members[14]);
|
|
}
|
|
|
|
/// <summary> Set the inverse translation of the current matrix.
|
|
/// Will erase any previous values.</summary>
|
|
void SetInverseTranslation( const Vector3D translation )
|
|
{
|
|
Members[12] = -translation.X;
|
|
Members[13] = -translation.Y;
|
|
Members[14] = -translation.Z;
|
|
}
|
|
|
|
/// <summary> Make a rotation matrix from Euler angles.
|
|
/// The 4th row and column are unmodified.</summary>
|
|
void SetRotationRadians( const Vector3D rotation )
|
|
{
|
|
double cr = Math::Cos( rotation.X );
|
|
double sr = Math::Sin( rotation.X );
|
|
double cp = Math::Cos( rotation.Y );
|
|
double sp = Math::Sin( rotation.Y );
|
|
double cy = Math::Cos( rotation.Z );
|
|
double sy = Math::Sin( rotation.Z );
|
|
|
|
Members[0] = (float)( cp*cy );
|
|
Members[1] = (float)( cp*sy );
|
|
Members[2] = (float)( -sp );
|
|
|
|
double srsp = sr*sp;
|
|
double crsp = cr*sp;
|
|
|
|
Members[4] = (float)( srsp*cy-cr*sy );
|
|
Members[5] = (float)( srsp*sy+cr*cy );
|
|
Members[6] = (float)( sr*cp );
|
|
|
|
Members[8] = (float)( crsp*cy+sr*sy );
|
|
Members[9] = (float)( crsp*sy-sr*cy );
|
|
Members[10] = (float)( cr*cp );
|
|
}
|
|
|
|
|
|
/// <summary> Make a rotation matrix from Euler angles.
|
|
/// The 4th row and column are unmodified.</summary>
|
|
void SetRotationDegrees( const Vector3D rotation )
|
|
{
|
|
SetRotationRadians( rotation * (float)(3.1415926535897932384626433832795 / 180.0) );
|
|
}
|
|
|
|
/// <summary> Returns the rotation, as set by setRotation().
|
|
/// This code was orginally written by by Chev.</summary>
|
|
Vector3D GetRotationDegrees()
|
|
{
|
|
Matrix4 &mat = *this;
|
|
|
|
double Y = -asin(mat.get_M(2,0));
|
|
double D = Y;
|
|
double C = cos(Y);
|
|
Y *= GRAD_PI;
|
|
|
|
double rotx, roty, X, Z;
|
|
|
|
if (fabs(C) > 0.0005f)
|
|
{
|
|
rotx = mat.get_M(2,2) / C;
|
|
roty = mat.get_M(2,1) / C;
|
|
|
|
X = atan2( roty, rotx ) * GRAD_PI;
|
|
|
|
rotx = mat.get_M(0,0) / C;
|
|
roty = mat.get_M(1,0) / C;
|
|
Z = atan2( roty, rotx ) * GRAD_PI;
|
|
}
|
|
else
|
|
{
|
|
X = 0.0f;
|
|
rotx = mat.get_M(1,1);
|
|
roty = -mat.get_M(0,1);
|
|
Z = atan2( roty, rotx ) * GRAD_PI;
|
|
}
|
|
|
|
// fix values that get below zero
|
|
// before it would set (!) values to 360
|
|
// that where above 360:
|
|
if (X < 0.00) X += 360.00;
|
|
if (Y < 0.00) Y += 360.00;
|
|
if (Z < 0.00) Z += 360.00;
|
|
|
|
return Vector3D((float)X, (float)Y, (float)Z);
|
|
}
|
|
/*
|
|
/// <summary> Make an inverted rotation matrix from Euler angles. The 4th row and column are unmodified.</summary>
|
|
void setInverseRotationRadians( const Vector3D& rotation );
|
|
|
|
/// <summary> Make an inverted rotation matrix from Euler angles. The 4th row and column are unmodified.</summary>
|
|
void setInverseRotationDegrees( const Vector3D& rotation );
|
|
*/
|
|
/// <summary> Set Scale </summary>
|
|
void SetScale( Vector3D scale )
|
|
{
|
|
Members[0] = scale.X;
|
|
Members[5] = scale.Y;
|
|
Members[10] = scale.Z;
|
|
}
|
|
|
|
/*
|
|
/// <summary> Translate a vector by the inverse of the translation part of this matrix.</summary>
|
|
void inverseTranslateVect( Vector3D& vect ) const;
|
|
|
|
/// <summary> Rotate a vector by the inverse of the rotation part of this matrix.</summary>
|
|
void inverseRotateVect( Vector3D& vect ) const;
|
|
|
|
/// <summary> Rotate a vector by the rotation part of this matrix.</summary>
|
|
void rotateVect( Vector3D& vect ) const;
|
|
*/
|
|
/// <summary> Transforms the vector by this matrix </summary>
|
|
void TransformVect( Vector3D& vect)
|
|
{
|
|
float vector[3];
|
|
|
|
vector[0] = vect.X*Members[0] + vect.Y*Members[4] + vect.Z*Members[8] + Members[12];
|
|
vector[1] = vect.X*Members[1] + vect.Y*Members[5] + vect.Z*Members[9] + Members[13];
|
|
vector[2] = vect.X*Members[2] + vect.Y*Members[6] + vect.Z*Members[10] + Members[14];
|
|
|
|
vect.X = vector[0];
|
|
vect.Y = vector[1];
|
|
vect.Z = vector[2];
|
|
}
|
|
|
|
/// <summary> Transforms input vector by this matrix and stores result in output vector </summary>
|
|
void TransformVect( const Vector3D& in, Vector3D& out)
|
|
{
|
|
out.X = in.X*Members[0] + in.Y*Members[4] + in.Z*Members[8] + Members[12];
|
|
out.Y = in.X*Members[1] + in.Y*Members[5] + in.Z*Members[9] + Members[13];
|
|
out.Z = in.X*Members[2] + in.Y*Members[6] + in.Z*Members[10] + Members[14];
|
|
}
|
|
|
|
/// <summary> Translate a vector by the translation part of this matrix.</summary>
|
|
void TranslateVect( Vector3D& vect )
|
|
{
|
|
vect.X = vect.X+Members[12];
|
|
vect.Y = vect.Y+Members[13];
|
|
vect.Z = vect.Z+Members[14];
|
|
}
|
|
/*
|
|
/// <summary> Transforms a plane by this matrix </summary>
|
|
void transformPlane( core::plane3d<float> &plane) const
|
|
|
|
/// <summary> Transforms a plane by this matrix</summary>
|
|
void transformPlane( const core::plane3d<float> &in, core::plane3d<float> &out) const;
|
|
|
|
/// <summary> Transforms a axis aligned bounding box</summary>
|
|
void transformBox( core::aabbox3d<float> &box) const;
|
|
|
|
/// <summary> Multiplies this matrix by a 1x4 matrix</summary>
|
|
void multiplyWith1x4Matrix(float* matrix) const;
|
|
*/
|
|
/// <summary> Calculates inverse of matrix. Slow.</summary>
|
|
/// <returns> Returns false if there is no inverse matrix.</returns>
|
|
bool MakeInverse()
|
|
{
|
|
Matrix4 temp;
|
|
|
|
if (GetInverse(temp))
|
|
{
|
|
*this = temp;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary> returns the inversed matrix of this one</summary>
|
|
/// <param name="Target"> where result matrix is written to.</param>
|
|
/// <returns>Returns false if there is no inverse matrix.</returns>
|
|
bool GetInverse(Matrix4& out)
|
|
{
|
|
/// Calculates the inverse of this Matrix
|
|
/// The inverse is calculated using Cramers rule.
|
|
/// If no inverse exists then 'false' is returned.
|
|
|
|
#define m getMInsecure
|
|
#define out out.setMInsecure
|
|
|
|
float d = (m(0, 0) * m(1, 1) - m(1, 0) * m(0, 1)) * (m(2, 2) * m(3, 3) - m(3, 2) * m(2, 3)) - (m(0, 0) * m(2, 1) - m(2, 0) * m(0, 1)) * (m(1, 2) * m(3, 3) - m(3, 2) * m(1, 3))
|
|
+ (m(0, 0) * m(3, 1) - m(3, 0) * m(0, 1)) * (m(1, 2) * m(2, 3) - m(2, 2) * m(1, 3)) + (m(1, 0) * m(2, 1) - m(2, 0) * m(1, 1)) * (m(0, 2) * m(3, 3) - m(3, 2) * m(0, 3))
|
|
- (m(1, 0) * m(3, 1) - m(3, 0) * m(1, 1)) * (m(0, 2) * m(2, 3) - m(2, 2) * m(0, 3)) + (m(2, 0) * m(3, 1) - m(3, 0) * m(2, 1)) * (m(0, 2) * m(1, 3) - m(1, 2) * m(0, 3));
|
|
|
|
if (d == 0.f)
|
|
return false;
|
|
|
|
d = 1.f / d;
|
|
|
|
out(0, 0, d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(3, 2) * m(2, 3)) + m(2, 1) * (m(3, 2) * m(1, 3) - m(1, 2) * m(3, 3)) + m(3, 1) * (m(1, 2) * m(2, 3) - m(2, 2) * m(1, 3))));
|
|
out(1, 0, d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(3, 0) * m(2, 3)) + m(2, 2) * (m(3, 0) * m(1, 3) - m(1, 0) * m(3, 3)) + m(3, 2) * (m(1, 0) * m(2, 3) - m(2, 0) * m(1, 3))));
|
|
out(2, 0, d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(3, 0) * m(2, 1)) + m(2, 3) * (m(3, 0) * m(1, 1) - m(1, 0) * m(3, 1)) + m(3, 3) * (m(1, 0) * m(2, 1) - m(2, 0) * m(1, 1))));
|
|
out(3, 0, d * (m(1, 0) * (m(3, 1) * m(2, 2) - m(2, 1) * m(3, 2)) + m(2, 0) * (m(1, 1) * m(3, 2) - m(3, 1) * m(1, 2)) + m(3, 0) * (m(2, 1) * m(1, 2) - m(1, 1) * m(2, 2))));
|
|
out(0, 1, d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(3, 2) * m(0, 3)) + m(3, 1) * (m(2, 2) * m(0, 3) - m(0, 2) * m(2, 3)) + m(0, 1) * (m(3, 2) * m(2, 3) - m(2, 2) * m(3, 3))));
|
|
out(1, 1, d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(3, 0) * m(0, 3)) + m(3, 2) * (m(2, 0) * m(0, 3) - m(0, 0) * m(2, 3)) + m(0, 2) * (m(3, 0) * m(2, 3) - m(2, 0) * m(3, 3))));
|
|
out(2, 1, d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(3, 0) * m(0, 1)) + m(3, 3) * (m(2, 0) * m(0, 1) - m(0, 0) * m(2, 1)) + m(0, 3) * (m(3, 0) * m(2, 1) - m(2, 0) * m(3, 1))));
|
|
out(3, 1, d * (m(2, 0) * (m(3, 1) * m(0, 2) - m(0, 1) * m(3, 2)) + m(3, 0) * (m(0, 1) * m(2, 2) - m(2, 1) * m(0, 2)) + m(0, 0) * (m(2, 1) * m(3, 2) - m(3, 1) * m(2, 2))));
|
|
out(0, 2, d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(1, 2) * m(0, 3)) + m(0, 1) * (m(1, 2) * m(3, 3) - m(3, 2) * m(1, 3)) + m(1, 1) * (m(3, 2) * m(0, 3) - m(0, 2) * m(3, 3))));
|
|
out(1, 2, d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(1, 0) * m(0, 3)) + m(0, 2) * (m(1, 0) * m(3, 3) - m(3, 0) * m(1, 3)) + m(1, 2) * (m(3, 0) * m(0, 3) - m(0, 0) * m(3, 3))));
|
|
out(2, 2, d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(1, 0) * m(0, 1)) + m(0, 3) * (m(1, 0) * m(3, 1) - m(3, 0) * m(1, 1)) + m(1, 3) * (m(3, 0) * m(0, 1) - m(0, 0) * m(3, 1))));
|
|
out(3, 2, d * (m(3, 0) * (m(1, 1) * m(0, 2) - m(0, 1) * m(1, 2)) + m(0, 0) * (m(3, 1) * m(1, 2) - m(1, 1) * m(3, 2)) + m(1, 0) * (m(0, 1) * m(3, 2) - m(3, 1) * m(0, 2))));
|
|
out(0, 3, d * (m(0, 1) * (m(2, 2) * m(1, 3) - m(1, 2) * m(2, 3)) + m(1, 1) * (m(0, 2) * m(2, 3) - m(2, 2) * m(0, 3)) + m(2, 1) * (m(1, 2) * m(0, 3) - m(0, 2) * m(1, 3))));
|
|
out(1, 3, d * (m(0, 2) * (m(2, 0) * m(1, 3) - m(1, 0) * m(2, 3)) + m(1, 2) * (m(0, 0) * m(2, 3) - m(2, 0) * m(0, 3)) + m(2, 2) * (m(1, 0) * m(0, 3) - m(0, 0) * m(1, 3))));
|
|
out(2, 3, d * (m(0, 3) * (m(2, 0) * m(1, 1) - m(1, 0) * m(2, 1)) + m(1, 3) * (m(0, 0) * m(2, 1) - m(2, 0) * m(0, 1)) + m(2, 3) * (m(1, 0) * m(0, 1) - m(0, 0) * m(1, 1))));
|
|
out(3, 3, d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(2, 1) * m(1, 2)) + m(1, 0) * (m(2, 1) * m(0, 2) - m(0, 1) * m(2, 2)) + m(2, 0) * (m(0, 1) * m(1, 2) - m(1, 1) * m(0, 2))));
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary> Builds a right-handed perspective projection matrix based on a field of view</summary>
|
|
void buildProjectionMatrixPerspectiveFovRH(float fieldOfViewRadians, float aspectRatio, float zNear, float zFar)
|
|
{
|
|
float h = (float)(Math::Cos(fieldOfViewRadians/2) / Math::Sin(fieldOfViewRadians/2));
|
|
float w = h / aspectRatio;
|
|
|
|
setMInsecure(0,0,2*zNear/w);
|
|
setMInsecure(1,0,0);
|
|
setMInsecure(2,0,0);
|
|
setMInsecure(3,0,0);
|
|
|
|
setMInsecure(0,1,0);
|
|
setMInsecure(1,1,2*zNear/h);
|
|
setMInsecure(2,1,0);
|
|
setMInsecure(3,1,0);
|
|
|
|
setMInsecure(0,2,0);
|
|
setMInsecure(1,2,0);
|
|
setMInsecure(2,2,zFar/(zFar-zNear));
|
|
setMInsecure(3,2,-1);
|
|
|
|
setMInsecure(0,3,0);
|
|
setMInsecure(1,3,0);
|
|
setMInsecure(2,3,zNear*zFar/(zNear-zFar));
|
|
setMInsecure(3,3,0);
|
|
}
|
|
|
|
/// <summary> Builds a left-handed perspective projection matrix based on a field of view</summary>
|
|
void buildProjectionMatrixPerspectiveFovLH(float fieldOfViewRadians, float aspectRatio, float zNear, float zFar)
|
|
{
|
|
float h = (float)(Math::Cos(fieldOfViewRadians/2) / Math::Sin(fieldOfViewRadians/2));
|
|
float w = h / aspectRatio;
|
|
|
|
setMInsecure(0,0,2*zNear/w);
|
|
setMInsecure(1,0,0);
|
|
setMInsecure(2,0,0);
|
|
setMInsecure(3,0,0);
|
|
|
|
setMInsecure(0,1,0);
|
|
setMInsecure(1,1,2*zNear/h);
|
|
setMInsecure(2,1,0);
|
|
setMInsecure(3,1,0);
|
|
|
|
setMInsecure(0,2,0);
|
|
setMInsecure(1,2,0);
|
|
setMInsecure(2,2,zFar/(zFar-zNear));
|
|
setMInsecure(3,2,1);
|
|
|
|
setMInsecure(0,3,0);
|
|
setMInsecure(1,3,0);
|
|
setMInsecure(2,3,zNear*zFar/(zNear-zFar));
|
|
setMInsecure(3,3,0);
|
|
}
|
|
|
|
/// <summary> Builds a right-handed perspective projection matrix.</summary>
|
|
void buildProjectionMatrixPerspectiveRH(float widthOfViewVolume, float heightOfViewVolume, float zNear, float zFar)
|
|
{
|
|
setMInsecure(0,0,2*zNear/widthOfViewVolume);
|
|
setMInsecure(1,0,0);
|
|
setMInsecure(2,0,0);
|
|
setMInsecure(3,0,0);
|
|
|
|
setMInsecure(0,1,0);
|
|
setMInsecure(1,1,2*zNear/heightOfViewVolume);
|
|
setMInsecure(2,1,0);
|
|
setMInsecure(3,1,0);
|
|
|
|
setMInsecure(0,2,0);
|
|
setMInsecure(1,2,0);
|
|
setMInsecure(2,2,zFar/(zNear-zFar));
|
|
setMInsecure(3,2,-1);
|
|
|
|
setMInsecure(0,3,0);
|
|
setMInsecure(1,3,0);
|
|
setMInsecure(2,3,zNear*zFar/(zNear-zFar));
|
|
setMInsecure(3,3,0);
|
|
}
|
|
|
|
/// <summary> Builds a left-handed perspective projection matrix.</summary>
|
|
void buildProjectionMatrixPerspectiveLH(float widthOfViewVolume, float heightOfViewVolume, float zNear, float zFar)
|
|
{
|
|
setMInsecure(0,0,2*zNear/widthOfViewVolume);
|
|
setMInsecure(1,0,0);
|
|
setMInsecure(2,0,0);
|
|
setMInsecure(3,0,0);
|
|
|
|
setMInsecure(0,1,0);
|
|
setMInsecure(1,1,2*zNear/heightOfViewVolume);
|
|
setMInsecure(2,1,0);
|
|
setMInsecure(3,1,0);
|
|
|
|
setMInsecure(0,2,0);
|
|
setMInsecure(1,2,0);
|
|
setMInsecure(2,2,zFar/(zNear-zFar));
|
|
setMInsecure(3,2,1);
|
|
|
|
setMInsecure(0,3,0);
|
|
setMInsecure(1,3,0);
|
|
setMInsecure(2,3,zNear*zFar/(zNear-zFar));
|
|
setMInsecure(3,3,0);
|
|
}
|
|
|
|
/// <summary> Builds a left-handed orthogonal projection matrix.</summary>
|
|
void buildProjectionMatrixOrthoLH(float widthOfViewVolume, float heightOfViewVolume, float zNear, float zFar)
|
|
{
|
|
setMInsecure(0,0,2/widthOfViewVolume);
|
|
setMInsecure(1,0,0);
|
|
setMInsecure(2,0,0);
|
|
setMInsecure(3,0,0);
|
|
|
|
setMInsecure(0,1,0);
|
|
setMInsecure(1,1,2/heightOfViewVolume);
|
|
setMInsecure(2,1,0);
|
|
setMInsecure(3,1,0);
|
|
|
|
setMInsecure(0,2,0);
|
|
setMInsecure(1,2,0);
|
|
setMInsecure(2,2,1/(zNear-zFar));
|
|
setMInsecure(3,2,0);
|
|
|
|
setMInsecure(0,3,0);
|
|
setMInsecure(1,3,0);
|
|
setMInsecure(2,3,zNear/(zNear-zFar));
|
|
setMInsecure(3,3,1);
|
|
}
|
|
|
|
/// <summary> Builds a right-handed orthogonal projection matrix.</summary>
|
|
void buildProjectionMatrixOrthoRH(float widthOfViewVolume, float heightOfViewVolume, float zNear, float zFar)
|
|
{
|
|
setMInsecure(0,0,2/widthOfViewVolume);
|
|
setMInsecure(1,0,0);
|
|
setMInsecure(2,0,0);
|
|
setMInsecure(3,0,0);
|
|
|
|
setMInsecure(0,1,0);
|
|
setMInsecure(1,1,2/heightOfViewVolume);
|
|
setMInsecure(2,1,0);
|
|
setMInsecure(3,1,0);
|
|
|
|
setMInsecure(0,2,0);
|
|
setMInsecure(1,2,0);
|
|
setMInsecure(2,2,1/(zNear-zFar));
|
|
setMInsecure(3,2,0);
|
|
|
|
setMInsecure(0,3,0);
|
|
setMInsecure(1,3,0);
|
|
setMInsecure(2,3,zNear/(zNear-zFar));
|
|
setMInsecure(3,3,-1);
|
|
}
|
|
|
|
/// <summary> Builds a left-handed look-at matrix.</summary>
|
|
void buildCameraLookAtMatrixLH(Vector3D position, Vector3D target, Vector3D upVector)
|
|
{
|
|
Vector3D zaxis = target - position;
|
|
zaxis.Normalize();
|
|
|
|
Vector3D xaxis = upVector.CrossProduct(zaxis);
|
|
xaxis.Normalize();
|
|
|
|
Vector3D yaxis = zaxis.CrossProduct(xaxis);
|
|
|
|
setMInsecure(0,0,xaxis.X);
|
|
setMInsecure(1,0,yaxis.X);
|
|
setMInsecure(2,0,zaxis.X);
|
|
setMInsecure(3,0,0);
|
|
|
|
setMInsecure(0,1,xaxis.Y);
|
|
setMInsecure(1,1,yaxis.Y);
|
|
setMInsecure(2,1,zaxis.Y);
|
|
setMInsecure(3,1,0);
|
|
|
|
setMInsecure(0,2,xaxis.Z);
|
|
setMInsecure(1,2,yaxis.Z);
|
|
setMInsecure(2,2,zaxis.Z);
|
|
setMInsecure(3,2,0);
|
|
|
|
setMInsecure(0,3,-xaxis.DotProduct(position));
|
|
setMInsecure(1,3,-yaxis.DotProduct(position));
|
|
setMInsecure(2,3,-zaxis.DotProduct(position));
|
|
setMInsecure(3,3,1.0f);
|
|
}
|
|
|
|
/// <summary> Builds a right-handed look-at matrix.</summary>
|
|
void buildCameraLookAtMatrixRH(Vector3D position, Vector3D target, Vector3D upVector)
|
|
{
|
|
Vector3D zaxis = position - target;
|
|
zaxis.Normalize();
|
|
|
|
Vector3D xaxis = upVector.CrossProduct(zaxis);
|
|
xaxis.Normalize();
|
|
|
|
Vector3D yaxis = zaxis.CrossProduct(xaxis);
|
|
|
|
setMInsecure(0,0,xaxis.X);
|
|
setMInsecure(1,0,yaxis.X);
|
|
setMInsecure(2,0,zaxis.X);
|
|
setMInsecure(3,0,0);
|
|
|
|
setMInsecure(0,1,xaxis.Y);
|
|
setMInsecure(1,1,yaxis.Y);
|
|
setMInsecure(2,1,zaxis.Y);
|
|
setMInsecure(3,1,0);
|
|
|
|
setMInsecure(0,2,xaxis.Z);
|
|
setMInsecure(1,2,yaxis.Z);
|
|
setMInsecure(2,2,zaxis.Z);
|
|
setMInsecure(3,2,0);
|
|
|
|
setMInsecure(0,3,-xaxis.DotProduct(position));
|
|
setMInsecure(1,3,-yaxis.DotProduct(position));
|
|
setMInsecure(2,3,-zaxis.DotProduct(position));
|
|
setMInsecure(3,3,1.0f);
|
|
}
|
|
|
|
/// <summary> Returns the transposed matrix. </summary>
|
|
Matrix4 GetTransposed()
|
|
{
|
|
Matrix4 t;
|
|
|
|
for (int r=0; r<4; ++r)
|
|
for (int c=0; c<4; ++c)
|
|
t.set_M(r, c, this->get_M( c, r ));
|
|
|
|
return t;
|
|
}
|
|
|
|
/// <summary> Returns array of floats representing the matrix </summary>
|
|
float GetFloats() __gc[]
|
|
{
|
|
float f __gc[] = new float __gc [16];
|
|
for (int i=0; i<16; ++i)
|
|
f[i] = Members[i];
|
|
return f;
|
|
}
|
|
|
|
|
|
/// <summary> Matrix data, stored in column-major order </summary>
|
|
float Members __nogc [16];
|
|
//float Members __gc [];
|
|
|
|
private:
|
|
|
|
/// <summary>
|
|
/// Direct accessing every row and colum of the matrix values without boundary checking
|
|
/// </summary>
|
|
inline float getMInsecure(int row, int col)
|
|
{
|
|
return Members[col * 4 + row];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Direct accessing every row and colum of the matrix values without boundary checking
|
|
/// </summary>
|
|
inline void setMInsecure(int row, int col, float v)
|
|
{
|
|
Members[col * 4 + row] = v;
|
|
}
|
|
};
|
|
}
|
|
} |