2007-05-20 11:03:49 -07:00
|
|
|
// Copyright (C) 2002-2007 Nikolaus Gebhardt
|
|
|
|
// This file is part of the "Irrlicht Engine".
|
|
|
|
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
|
|
|
|
|
|
|
#ifndef __IRR_MATRIX_H_INCLUDED__
|
|
|
|
#define __IRR_MATRIX_H_INCLUDED__
|
|
|
|
|
|
|
|
#include "irrTypes.h"
|
|
|
|
#include "vector3d.h"
|
|
|
|
#include "vector2d.h"
|
|
|
|
#include "plane3d.h"
|
|
|
|
#include "aabbox3d.h"
|
|
|
|
#include "rect.h"
|
|
|
|
#include "irrString.h"
|
|
|
|
|
|
|
|
namespace irr
|
|
|
|
{
|
|
|
|
namespace core
|
|
|
|
{
|
|
|
|
|
|
|
|
//! 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.
|
|
|
|
*/
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
class CMatrix4
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
//! Constructor Flags
|
|
|
|
enum eConstructor
|
|
|
|
{
|
|
|
|
EM4CONST_NOTHING = 0,
|
|
|
|
EM4CONST_COPY,
|
|
|
|
EM4CONST_IDENTITY,
|
|
|
|
EM4CONST_TRANSPOSED,
|
|
|
|
EM4CONST_INVERSE,
|
|
|
|
EM4CONST_INVERSE_TRANSPOSED
|
|
|
|
};
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4( eConstructor constructor = EM4CONST_IDENTITY );
|
|
|
|
CMatrix4( const CMatrix4<T>& other,eConstructor constructor = EM4CONST_COPY);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Simple operator for directly accessing every element of the matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
T& operator()(const s32 row, const s32 col) { definitelyIdentityMatrix=false; return M[ row * 4 + col ]; }
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Simple operator for directly accessing every element of the matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
const T& operator()(const s32 row, const s32 col) const { return M[row * 4 + col]; }
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Simple operator for linearly accessing every element of the matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
T& operator[](u32 index) { definitelyIdentityMatrix=false; return M[index]; }
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Simple operator for linearly accessing every element of the matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
const T& operator[](u32 index) const { return M[index]; }
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Sets this matrix equal to the other matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
inline CMatrix4<T>& operator=(const CMatrix4<T> &other);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Sets all elements of this matrix to the value.
|
2007-06-02 03:37:00 -07:00
|
|
|
inline CMatrix4<T>& operator=(const T& scalar);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Returns pointer to internal array
|
2007-06-02 03:37:00 -07:00
|
|
|
const T* pointer() const { return M; }
|
|
|
|
T* pointer() { definitelyIdentityMatrix=false; return M; }
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Returns true if other matrix is equal to this matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
bool operator==(const CMatrix4<T> &other) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Returns true if other matrix is not equal to this matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
bool operator!=(const CMatrix4<T> &other) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Add another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> operator+(const CMatrix4<T>& other) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Add another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T>& operator+=(const CMatrix4<T>& other);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Subtract another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> operator-(const CMatrix4<T>& other) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Subtract another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T>& operator-=(const CMatrix4<T>& other);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! set this matrix to the product of two matrices
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& setbyproduct(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! set this matrix to the product of two matrices, no logical optimation
|
|
|
|
//! use it if you know you never have a identity matrix
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Multiply by another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> operator*(const CMatrix4<T>& other) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Multiply by another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T>& operator*=(const CMatrix4<T>& other);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Multiply by scalar.
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> operator*(const T& scalar) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Multiply by scalar.
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T>& operator*=(const T& scalar);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Set matrix to identity.
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& makeIdentity();
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Returns true if the matrix is the identity matrix
|
|
|
|
inline bool isIdentity() const;
|
|
|
|
|
|
|
|
//! Returns true if the matrix is the identity matrix
|
|
|
|
bool isIdentity_integer_base () const;
|
|
|
|
|
|
|
|
//! Set the translation of the current matrix. Will erase any previous values.
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& setTranslation( const vector3d<T>& translation );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Gets the current translation
|
2007-07-13 11:23:09 -07:00
|
|
|
vector3d<T> getTranslation() const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Set the inverse translation of the current matrix. Will erase any previous values.
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& setInverseTranslation( const vector3d<T>& translation );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& setRotationRadians( const vector3d<T>& rotation );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Make a rotation matrix from Euler angles. The 4th row and column are unmodified.
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& setRotationDegrees( const vector3d<T>& rotation );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Returns the rotation, as set by setRotation(). This code was orginally written by by Chev.
|
2007-07-13 11:23:09 -07:00
|
|
|
core::vector3d<T> getRotationDegrees() const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Make an inverted rotation matrix from Euler angles. The 4th row and column are unmodified.
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& setInverseRotationRadians( const vector3d<T>& rotation );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Make an inverted rotation matrix from Euler angles. The 4th row and column are unmodified.
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& setInverseRotationDegrees( const vector3d<T>& rotation );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Set Scale
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& setScale( const vector3d<T>& scale );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2008-04-29 05:10:33 -07:00
|
|
|
//! Set Scale
|
|
|
|
CMatrix4<T>& setScale( const T scale ) { return setScale(core::vector3d<T>(scale,scale,scale)); }
|
|
|
|
|
2007-05-20 11:03:49 -07:00
|
|
|
//! Get Scale
|
2007-07-13 11:23:09 -07:00
|
|
|
core::vector3d<T> getScale() const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Translate a vector by the inverse of the translation part of this matrix.
|
|
|
|
void inverseTranslateVect( vector3df& vect ) const;
|
|
|
|
|
|
|
|
//! Rotate a vector by the inverse of the rotation part of this matrix.
|
|
|
|
void inverseRotateVect( vector3df& vect ) const;
|
|
|
|
|
|
|
|
//! Rotate a vector by the rotation part of this matrix.
|
|
|
|
void rotateVect( vector3df& vect ) const;
|
|
|
|
|
2007-09-12 10:46:58 -07:00
|
|
|
//! An alternate transform vector method, writing into a second vector
|
|
|
|
void rotateVect(vector3df& out,const core::vector3df& in) const;
|
|
|
|
|
|
|
|
//! An alternate transform vector method, writing into an array of 3 floats
|
|
|
|
void rotateVect(T *out,const core::vector3df &in) const;
|
|
|
|
|
2007-05-20 11:03:49 -07:00
|
|
|
//! Transforms the vector by this matrix
|
|
|
|
void transformVect( vector3df& vect) const;
|
|
|
|
|
|
|
|
//! Transforms input vector by this matrix and stores result in output vector
|
|
|
|
void transformVect( vector3df& out, const vector3df& in ) const;
|
|
|
|
|
|
|
|
//! An alternate transform vector method, writing into an array of 4 floats
|
2007-06-02 03:37:00 -07:00
|
|
|
void transformVect(T *out,const core::vector3df &in) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Translate a vector by the translation part of this matrix.
|
|
|
|
void translateVect( vector3df& vect ) const;
|
|
|
|
|
|
|
|
//! Transforms a plane by this matrix
|
|
|
|
void transformPlane( core::plane3d<f32> &plane) const;
|
|
|
|
|
|
|
|
//! Transforms a plane by this matrix ( some problems to solve..)
|
|
|
|
void transformPlane_new( core::plane3d<f32> &plane) const;
|
|
|
|
|
|
|
|
//! Transforms a plane by this matrix
|
|
|
|
void transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const;
|
|
|
|
|
|
|
|
//! Transforms a axis aligned bounding box
|
|
|
|
/** The result box of this operation may not be very accurate. For
|
|
|
|
accurate results, use transformBoxEx() */
|
|
|
|
void transformBox(core::aabbox3d<f32>& box) const;
|
|
|
|
|
|
|
|
//! Transforms a axis aligned bounding box more accurately than transformBox()
|
|
|
|
/** The result box of this operation should by quite accurate, but this operation
|
|
|
|
is slower than transformBox(). */
|
|
|
|
void transformBoxEx(core::aabbox3d<f32>& box) const;
|
|
|
|
|
|
|
|
//! Multiplies this matrix by a 1x4 matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
void multiplyWith1x4Matrix(T* matrix) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Calculates inverse of matrix. Slow.
|
|
|
|
//! \return Returns false if there is no inverse matrix.
|
|
|
|
bool makeInverse();
|
|
|
|
|
|
|
|
|
|
|
|
//! Inverts a primitive matrix which only contains a translation and a rotation
|
|
|
|
//! \param out: where result matrix is written to.
|
2007-06-02 03:37:00 -07:00
|
|
|
bool getInversePrimitive ( CMatrix4<T>& out ) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! returns the inversed matrix of this one
|
|
|
|
//! \param out: where result matrix is written to.
|
|
|
|
//! \return Returns false if there is no inverse matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
bool getInverse(CMatrix4<T>& out) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Builds a right-handed perspective projection matrix based on a field of view
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& buildProjectionMatrixPerspectiveFovRH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Builds a left-handed perspective projection matrix based on a field of view
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& buildProjectionMatrixPerspectiveFovLH(f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Builds a right-handed perspective projection matrix.
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& buildProjectionMatrixPerspectiveRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Builds a left-handed perspective projection matrix.
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& buildProjectionMatrixPerspectiveLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Builds a left-handed orthogonal projection matrix.
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& buildProjectionMatrixOrthoLH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Builds a right-handed orthogonal projection matrix.
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& buildProjectionMatrixOrthoRH(f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Builds a left-handed look-at matrix.
|
2008-04-29 04:34:54 -07:00
|
|
|
CMatrix4<T>& buildCameraLookAtMatrixLH(
|
|
|
|
const vector3df& position,
|
|
|
|
const vector3df& target,
|
|
|
|
const vector3df& upVector);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Builds a right-handed look-at matrix.
|
2008-04-29 04:34:54 -07:00
|
|
|
CMatrix4<T>& buildCameraLookAtMatrixRH(
|
|
|
|
const vector3df& position,
|
|
|
|
const vector3df& target,
|
|
|
|
const vector3df& upVector);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Builds a matrix that flattens geometry into a plane.
|
|
|
|
//! \param light: light source
|
|
|
|
//! \param plane: plane into which the geometry if flattened into
|
|
|
|
//! \param point: value between 0 and 1, describing the light source.
|
|
|
|
//! If this is 1, it is a point light, if it is 0, it is a directional light.
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point=1.0f);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! Builds a matrix which transforms a normalized Device Coordinate to Device Coordinates.
|
|
|
|
/** Used to scale <-1,-1><1,1> to viewport, for example from von <-1,-1> <1,1> to the viewport <0,0><0,640> */
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& buildNDCToDCMatrix( const core::rect<s32>& area, f32 zScale);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! creates a new matrix as interpolated matrix from two other ones.
|
|
|
|
//! \param b: other matrix to interpolate with
|
|
|
|
//! \param time: Must be a value between 0 and 1.
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> interpolate(const core::CMatrix4<T>& b, f32 time) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! returns transposed matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> getTransposed() const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! returns transposed matrix to a plain 4x4 float matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
inline void getTransposed( CMatrix4<T>& dest ) const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
/*!
|
|
|
|
construct 2D Texture transformations
|
|
|
|
rotate about center, scale, and transform.
|
|
|
|
*/
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& buildTextureTransform( f32 rotateRad,
|
2007-05-20 11:03:49 -07:00
|
|
|
const core::vector2df &rotatecenter,
|
|
|
|
const core::vector2df &translate,
|
|
|
|
const core::vector2df &scale);
|
|
|
|
|
2008-04-12 16:02:15 -07:00
|
|
|
//! set texture transformation rotation
|
|
|
|
//! rotate about z axis, recenter at (0.5,0.5)
|
|
|
|
//! doesn't clear other elements than those affected
|
|
|
|
//! \param radAngle Angle in radians
|
|
|
|
//! \return Altered matrix
|
|
|
|
CMatrix4<T>& setTextureRotationCenter( f32 radAngle );
|
|
|
|
|
|
|
|
//! set texture transformation translation
|
|
|
|
//! doesn't clear other elements than those affected
|
|
|
|
//! \param x Offset on x axis
|
|
|
|
//! \param y Offset on y axis
|
|
|
|
//! \return Altered matrix
|
|
|
|
CMatrix4<T>& setTextureTranslate( f32 x, f32 y );
|
|
|
|
|
|
|
|
//! set texture transformation translation, using a transposed representation
|
|
|
|
//! doesn't clear other elements than those affected
|
|
|
|
//! \param x Offset on x axis
|
|
|
|
//! \param y Offset on y axis
|
|
|
|
//! \return Altered matrix
|
|
|
|
CMatrix4<T>& setTextureTranslateTransposed( f32 x, f32 y );
|
|
|
|
|
|
|
|
//! set texture transformation scale
|
|
|
|
//! doesn't clear other elements than those affected
|
|
|
|
//! \param sx Scale factor on x axis
|
|
|
|
//! \param sy Scale factor on y axis
|
|
|
|
//! \return Altered matrix
|
|
|
|
CMatrix4<T>& setTextureScale( f32 sx, f32 sy );
|
|
|
|
|
|
|
|
//! set texture transformation scale, and recenter at (0.5,0.5)
|
|
|
|
//! doesn't clear other elements than those affected
|
|
|
|
//! \param sx Scale factor on x axis
|
|
|
|
//! \param sy Scale factor on y axis
|
|
|
|
//! \return Altered matrix
|
|
|
|
CMatrix4<T>& setTextureScaleCenter( f32 sx, f32 sy );
|
|
|
|
|
2007-05-20 11:03:49 -07:00
|
|
|
//! sets all matrix data members at once
|
2008-04-12 16:02:15 -07:00
|
|
|
CMatrix4<T>& setM(const T* data);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
//! sets if the matrix is definitely identity matrix
|
|
|
|
void setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix);
|
|
|
|
|
|
|
|
//! gets if the matrix is definitely identity matrix
|
2007-10-02 07:24:45 -07:00
|
|
|
bool getDefinitelyIdentityMatrix() const;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
private:
|
|
|
|
//! Matrix data, stored in row-major order
|
2007-06-02 03:37:00 -07:00
|
|
|
T M[16];
|
2007-10-02 15:20:57 -07:00
|
|
|
mutable bool definitelyIdentityMatrix;
|
2007-05-20 11:03:49 -07:00
|
|
|
};
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2007-06-03 13:44:11 -07:00
|
|
|
inline CMatrix4<T>::CMatrix4( eConstructor constructor ) : definitelyIdentityMatrix(false)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
switch ( constructor )
|
|
|
|
{
|
|
|
|
case EM4CONST_NOTHING:
|
|
|
|
case EM4CONST_COPY:
|
|
|
|
break;
|
|
|
|
case EM4CONST_IDENTITY:
|
|
|
|
case EM4CONST_INVERSE:
|
|
|
|
default:
|
|
|
|
makeIdentity();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2007-06-03 13:44:11 -07:00
|
|
|
inline CMatrix4<T>::CMatrix4( const CMatrix4<T>& other, eConstructor constructor) : definitelyIdentityMatrix(false)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
switch ( constructor )
|
|
|
|
{
|
|
|
|
case EM4CONST_IDENTITY:
|
|
|
|
makeIdentity();
|
|
|
|
break;
|
|
|
|
case EM4CONST_NOTHING:
|
|
|
|
break;
|
|
|
|
case EM4CONST_COPY:
|
|
|
|
*this = other;
|
|
|
|
break;
|
|
|
|
case EM4CONST_TRANSPOSED:
|
|
|
|
other.getTransposed(*this);
|
|
|
|
break;
|
|
|
|
case EM4CONST_INVERSE:
|
|
|
|
if (!other.getInverse(*this))
|
2007-06-02 03:37:00 -07:00
|
|
|
memset(M, 0, 16*sizeof(T));
|
2007-05-20 11:03:49 -07:00
|
|
|
break;
|
|
|
|
case EM4CONST_INVERSE_TRANSPOSED:
|
|
|
|
if (!other.getInverse(*this))
|
2007-06-02 03:37:00 -07:00
|
|
|
memset(M, 0, 16*sizeof(T));
|
2007-05-20 11:03:49 -07:00
|
|
|
else
|
|
|
|
*this=getTransposed();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Add another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T> CMatrix4<T>::operator+(const CMatrix4<T>& other) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> temp ( EM4CONST_NOTHING );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
temp[0] = M[0]+other[0];
|
|
|
|
temp[1] = M[1]+other[1];
|
|
|
|
temp[2] = M[2]+other[2];
|
|
|
|
temp[3] = M[3]+other[3];
|
|
|
|
temp[4] = M[4]+other[4];
|
|
|
|
temp[5] = M[5]+other[5];
|
|
|
|
temp[6] = M[6]+other[6];
|
|
|
|
temp[7] = M[7]+other[7];
|
|
|
|
temp[8] = M[8]+other[8];
|
|
|
|
temp[9] = M[9]+other[9];
|
|
|
|
temp[10] = M[10]+other[10];
|
|
|
|
temp[11] = M[11]+other[11];
|
|
|
|
temp[12] = M[12]+other[12];
|
|
|
|
temp[13] = M[13]+other[13];
|
|
|
|
temp[14] = M[14]+other[14];
|
|
|
|
temp[15] = M[15]+other[15];
|
|
|
|
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Add another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T>& CMatrix4<T>::operator+=(const CMatrix4<T>& other)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
M[0]+=other[0];
|
|
|
|
M[1]+=other[1];
|
|
|
|
M[2]+=other[2];
|
|
|
|
M[3]+=other[3];
|
|
|
|
M[4]+=other[4];
|
|
|
|
M[5]+=other[5];
|
|
|
|
M[6]+=other[6];
|
|
|
|
M[7]+=other[7];
|
|
|
|
M[8]+=other[8];
|
|
|
|
M[9]+=other[9];
|
|
|
|
M[10]+=other[10];
|
|
|
|
M[11]+=other[11];
|
|
|
|
M[12]+=other[12];
|
|
|
|
M[13]+=other[13];
|
|
|
|
M[14]+=other[14];
|
|
|
|
M[15]+=other[15];
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Subtract another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T> CMatrix4<T>::operator-(const CMatrix4<T>& other) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> temp ( EM4CONST_NOTHING );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
temp[0] = M[0]-other[0];
|
|
|
|
temp[1] = M[1]-other[1];
|
|
|
|
temp[2] = M[2]-other[2];
|
|
|
|
temp[3] = M[3]-other[3];
|
|
|
|
temp[4] = M[4]-other[4];
|
|
|
|
temp[5] = M[5]-other[5];
|
|
|
|
temp[6] = M[6]-other[6];
|
|
|
|
temp[7] = M[7]-other[7];
|
|
|
|
temp[8] = M[8]-other[8];
|
|
|
|
temp[9] = M[9]-other[9];
|
|
|
|
temp[10] = M[10]-other[10];
|
|
|
|
temp[11] = M[11]-other[11];
|
|
|
|
temp[12] = M[12]-other[12];
|
|
|
|
temp[13] = M[13]-other[13];
|
|
|
|
temp[14] = M[14]-other[14];
|
|
|
|
temp[15] = M[15]-other[15];
|
|
|
|
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Subtract another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T>& CMatrix4<T>::operator-=(const CMatrix4<T>& other)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
M[0]-=other[0];
|
|
|
|
M[1]-=other[1];
|
|
|
|
M[2]-=other[2];
|
|
|
|
M[3]-=other[3];
|
|
|
|
M[4]-=other[4];
|
|
|
|
M[5]-=other[5];
|
|
|
|
M[6]-=other[6];
|
|
|
|
M[7]-=other[7];
|
|
|
|
M[8]-=other[8];
|
|
|
|
M[9]-=other[9];
|
|
|
|
M[10]-=other[10];
|
|
|
|
M[11]-=other[11];
|
|
|
|
M[12]-=other[12];
|
|
|
|
M[13]-=other[13];
|
|
|
|
M[14]-=other[14];
|
|
|
|
M[15]-=other[15];
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Multiply by scalar.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T> CMatrix4<T>::operator*(const T& scalar) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> temp ( EM4CONST_NOTHING );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
temp[0] = M[0]*scalar;
|
|
|
|
temp[1] = M[1]*scalar;
|
|
|
|
temp[2] = M[2]*scalar;
|
|
|
|
temp[3] = M[3]*scalar;
|
|
|
|
temp[4] = M[4]*scalar;
|
|
|
|
temp[5] = M[5]*scalar;
|
|
|
|
temp[6] = M[6]*scalar;
|
|
|
|
temp[7] = M[7]*scalar;
|
|
|
|
temp[8] = M[8]*scalar;
|
|
|
|
temp[9] = M[9]*scalar;
|
|
|
|
temp[10] = M[10]*scalar;
|
|
|
|
temp[11] = M[11]*scalar;
|
|
|
|
temp[12] = M[12]*scalar;
|
|
|
|
temp[13] = M[13]*scalar;
|
|
|
|
temp[14] = M[14]*scalar;
|
|
|
|
temp[15] = M[15]*scalar;
|
|
|
|
|
|
|
|
return temp;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Multiply by scalar.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T>& CMatrix4<T>::operator*=(const T& scalar)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
M[0]*=scalar;
|
|
|
|
M[1]*=scalar;
|
|
|
|
M[2]*=scalar;
|
|
|
|
M[3]*=scalar;
|
|
|
|
M[4]*=scalar;
|
|
|
|
M[5]*=scalar;
|
|
|
|
M[6]*=scalar;
|
|
|
|
M[7]*=scalar;
|
|
|
|
M[8]*=scalar;
|
|
|
|
M[9]*=scalar;
|
|
|
|
M[10]*=scalar;
|
|
|
|
M[11]*=scalar;
|
|
|
|
M[12]*=scalar;
|
|
|
|
M[13]*=scalar;
|
|
|
|
M[14]*=scalar;
|
|
|
|
M[15]*=scalar;
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Multiply by another matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T>& CMatrix4<T>::operator*=(const CMatrix4<T>& other)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2008-04-12 16:02:15 -07:00
|
|
|
// do checks on your own in order to avoid copy creation
|
2007-09-12 10:46:58 -07:00
|
|
|
if ( !other.isIdentity() )
|
|
|
|
{
|
|
|
|
if ( this->isIdentity() )
|
|
|
|
{
|
2008-04-12 16:02:15 -07:00
|
|
|
return (*this = other);
|
2007-09-12 10:46:58 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CMatrix4<T> temp ( *this );
|
2008-04-12 16:02:15 -07:00
|
|
|
return setbyproduct_nocheck( temp, other );
|
2007-09-12 10:46:58 -07:00
|
|
|
}
|
|
|
|
}
|
2007-05-20 11:03:49 -07:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! multiply by another matrix
|
|
|
|
// set this matrix to the product of two other matrices
|
|
|
|
// goal is to reduce stack use and copy
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setbyproduct_nocheck(const CMatrix4<T>& other_a,const CMatrix4<T>& other_b )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
const T *m1 = other_a.M;
|
|
|
|
const T *m2 = other_b.M;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
M[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
|
|
|
|
M[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
|
|
|
|
M[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
|
|
|
|
M[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];
|
|
|
|
|
|
|
|
M[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
|
|
|
|
M[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
|
|
|
|
M[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
|
|
|
|
M[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];
|
|
|
|
|
|
|
|
M[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
|
|
|
|
M[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
|
|
|
|
M[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
|
|
|
|
M[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];
|
|
|
|
|
|
|
|
M[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
|
|
|
|
M[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
|
|
|
|
M[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
|
|
|
|
M[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
|
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! multiply by another matrix
|
|
|
|
// set this matrix to the product of two other matrices
|
|
|
|
// goal is to reduce stack use and copy
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setbyproduct(const CMatrix4<T>& other_a, const CMatrix4<T>& other_b )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
if ( other_a.isIdentity () )
|
2008-04-12 16:02:15 -07:00
|
|
|
return (*this = other_b);
|
2007-05-20 11:03:49 -07:00
|
|
|
else
|
|
|
|
if ( other_b.isIdentity () )
|
2008-04-12 16:02:15 -07:00
|
|
|
return (*this = other_a);
|
|
|
|
else
|
|
|
|
return setbyproduct_nocheck(other_a,other_b);
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//! multiply by another matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-10-02 07:24:45 -07:00
|
|
|
// Testing purpose..
|
2007-05-20 11:03:49 -07:00
|
|
|
if ( this->isIdentity() )
|
|
|
|
return m2;
|
|
|
|
if ( m2.isIdentity() )
|
|
|
|
return *this;
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> m3 ( EM4CONST_NOTHING );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
const T *m1 = M;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
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];
|
|
|
|
return m3;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2007-07-13 11:23:09 -07:00
|
|
|
inline vector3d<T> CMatrix4<T>::getTranslation() const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-07-13 11:23:09 -07:00
|
|
|
return vector3d<T>(M[12], M[13], M[14]);
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setTranslation( const vector3d<T>& translation )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
M[12] = translation.X;
|
|
|
|
M[13] = translation.Y;
|
|
|
|
M[14] = translation.Z;
|
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setInverseTranslation( const vector3d<T>& translation )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
M[12] = -translation.X;
|
|
|
|
M[13] = -translation.Y;
|
|
|
|
M[14] = -translation.Z;
|
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setScale( const vector3d<T>& scale )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
M[0] = scale.X;
|
|
|
|
M[5] = scale.Y;
|
|
|
|
M[10] = scale.Z;
|
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2007-07-13 11:23:09 -07:00
|
|
|
inline vector3d<T> CMatrix4<T>::getScale() const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-07-13 11:23:09 -07:00
|
|
|
return vector3d<T>(M[0],M[5],M[10]);
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setRotationDegrees( const vector3d<T>& rotation )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2008-04-12 16:02:15 -07:00
|
|
|
return setRotationRadians( rotation * core::DEGTORAD );
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setInverseRotationDegrees( const vector3d<T>& rotation )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2008-04-12 16:02:15 -07:00
|
|
|
return setInverseRotationRadians( rotation * core::DEGTORAD );
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setRotationRadians( const vector3d<T>& rotation )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2008-04-12 16:02:15 -07:00
|
|
|
const f64 cr = cos( rotation.X );
|
|
|
|
const f64 sr = sin( rotation.X );
|
|
|
|
const f64 cp = cos( rotation.Y );
|
|
|
|
const f64 sp = sin( rotation.Y );
|
|
|
|
const f64 cy = cos( rotation.Z );
|
|
|
|
const f64 sy = sin( rotation.Z );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)( cp*cy );
|
|
|
|
M[1] = (T)( cp*sy );
|
|
|
|
M[2] = (T)( -sp );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2008-04-12 16:02:15 -07:00
|
|
|
const f64 srsp = sr*sp;
|
|
|
|
const f64 crsp = cr*sp;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[4] = (T)( srsp*cy-cr*sy );
|
|
|
|
M[5] = (T)( srsp*sy+cr*cy );
|
|
|
|
M[6] = (T)( sr*cp );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[8] = (T)( crsp*cy+sr*sy );
|
|
|
|
M[9] = (T)( crsp*sy-sr*cy );
|
|
|
|
M[10] = (T)( cr*cp );
|
2007-05-20 11:03:49 -07:00
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! Returns the rotation, as set by setRotation(). This code was sent
|
|
|
|
//! in by Chev.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2007-07-13 11:23:09 -07:00
|
|
|
inline core::vector3d<T> CMatrix4<T>::getRotationDegrees() const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
const CMatrix4<T> &mat = *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
f64 Y = -asin(mat(0,2));
|
2008-04-12 16:02:15 -07:00
|
|
|
const f64 C = cos(Y);
|
2007-05-20 11:03:49 -07:00
|
|
|
Y *= RADTODEG64;
|
|
|
|
|
|
|
|
f64 rotx, roty, X, Z;
|
|
|
|
|
2008-04-29 05:10:33 -07:00
|
|
|
if (fabs(C)>ROUNDING_ERROR_64)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2008-04-29 15:07:21 -07:00
|
|
|
const T invC = (T)(1.0/C);
|
2008-04-12 16:02:15 -07:00
|
|
|
rotx = mat(2,2) * invC;
|
|
|
|
roty = mat(1,2) * invC;
|
2007-05-20 11:03:49 -07:00
|
|
|
X = atan2( roty, rotx ) * RADTODEG64;
|
2008-04-12 16:02:15 -07:00
|
|
|
rotx = mat(0,0) * invC;
|
|
|
|
roty = mat(0,1) * invC;
|
2007-05-20 11:03:49 -07:00
|
|
|
Z = atan2( roty, rotx ) * RADTODEG64;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
X = 0.0;
|
2007-05-20 11:03:49 -07:00
|
|
|
rotx = mat(1,1);
|
|
|
|
roty = -mat(1,0);
|
|
|
|
Z = atan2( roty, rotx ) * RADTODEG64;
|
|
|
|
}
|
|
|
|
|
|
|
|
// fix values that get below zero
|
|
|
|
// before it would set (!) values to 360
|
|
|
|
// that where above 360:
|
|
|
|
if (X < 0.0) X += 360.0;
|
|
|
|
if (Y < 0.0) Y += 360.0;
|
|
|
|
if (Z < 0.0) Z += 360.0;
|
|
|
|
|
2008-04-12 16:02:15 -07:00
|
|
|
return vector3d<T>((T)X,(T)Y,(T)Z);
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2008-04-12 16:02:15 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setInverseRotationRadians( const vector3d<T>& rotation )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
f64 cr = cos( rotation.X );
|
|
|
|
f64 sr = sin( rotation.X );
|
|
|
|
f64 cp = cos( rotation.Y );
|
|
|
|
f64 sp = sin( rotation.Y );
|
|
|
|
f64 cy = cos( rotation.Z );
|
|
|
|
f64 sy = sin( rotation.Z );
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)( cp*cy );
|
|
|
|
M[4] = (T)( cp*sy );
|
|
|
|
M[8] = (T)( -sp );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
f64 srsp = sr*sp;
|
|
|
|
f64 crsp = cr*sp;
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[1] = (T)( srsp*cy-cr*sy );
|
|
|
|
M[5] = (T)( srsp*sy+cr*cy );
|
|
|
|
M[9] = (T)( sr*cp );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[2] = (T)( crsp*cy+sr*sy );
|
|
|
|
M[6] = (T)( crsp*sy-sr*cy );
|
|
|
|
M[10] = (T)( cr*cp );
|
2007-05-20 11:03:49 -07:00
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
*/
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::makeIdentity()
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
memset(M, 0, 16*sizeof(T));
|
|
|
|
M[0] = M[5] = M[10] = M[15] = (T)1;
|
2007-05-20 11:03:49 -07:00
|
|
|
definitelyIdentityMatrix=true;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
check identity with epsilon
|
|
|
|
solve floating range problems..
|
|
|
|
*/
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline bool CMatrix4<T>::isIdentity() const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
if (definitelyIdentityMatrix)
|
|
|
|
return true;
|
2007-06-02 03:37:00 -07:00
|
|
|
if ( !equals ( M[ 0], (T)1 ) ||
|
|
|
|
!equals ( M[ 5], (T)1 ) ||
|
|
|
|
!equals ( M[10], (T)1 ) ||
|
|
|
|
!equals ( M[15], (T)1 )
|
2007-05-20 11:03:49 -07:00
|
|
|
)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (s32 i=0; i<4; ++i)
|
|
|
|
for (s32 j=0; j<4; ++j)
|
2008-04-29 04:34:54 -07:00
|
|
|
if ((j != i) && (!iszero((*this)(i,j))))
|
|
|
|
return false;
|
2007-10-02 07:24:45 -07:00
|
|
|
|
2007-10-02 15:20:57 -07:00
|
|
|
definitelyIdentityMatrix=true;
|
2007-05-20 11:03:49 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
doesn't solve floating range problems..
|
|
|
|
but takes care on +/- 0 on translation because we are changing it..
|
|
|
|
reducing floating point branches
|
2007-06-02 03:37:00 -07:00
|
|
|
but it needs the floats in memory..
|
2007-05-20 11:03:49 -07:00
|
|
|
*/
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline bool CMatrix4<T>::isIdentity_integer_base() const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
if (definitelyIdentityMatrix)
|
|
|
|
return true;
|
|
|
|
if(IR(M[0])!=F32_VALUE_1) return false;
|
|
|
|
if(IR(M[1])!=0) return false;
|
|
|
|
if(IR(M[2])!=0) return false;
|
|
|
|
if(IR(M[3])!=0) return false;
|
|
|
|
|
|
|
|
if(IR(M[4])!=0) return false;
|
|
|
|
if(IR(M[5])!=F32_VALUE_1) return false;
|
|
|
|
if(IR(M[6])!=0) return false;
|
|
|
|
if(IR(M[7])!=0) return false;
|
|
|
|
|
|
|
|
if(IR(M[8])!=0) return false;
|
|
|
|
if(IR(M[9])!=0) return false;
|
|
|
|
if(IR(M[10])!=F32_VALUE_1) return false;
|
|
|
|
if(IR(M[11])!=0) return false;
|
|
|
|
|
|
|
|
if(IR(M[12])!=0) return false;
|
|
|
|
if(IR(M[13])!=0) return false;
|
|
|
|
if(IR(M[13])!=0) return false;
|
|
|
|
if(IR(M[15])!=F32_VALUE_1) return false;
|
2007-10-02 15:20:57 -07:00
|
|
|
definitelyIdentityMatrix=true;
|
2007-05-20 11:03:49 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::rotateVect( vector3df& vect ) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
vector3df tmp = vect;
|
|
|
|
vect.X = tmp.X*M[0] + tmp.Y*M[4] + tmp.Z*M[8];
|
|
|
|
vect.Y = tmp.X*M[1] + tmp.Y*M[5] + tmp.Z*M[9];
|
|
|
|
vect.Z = tmp.X*M[2] + tmp.Y*M[6] + tmp.Z*M[10];
|
|
|
|
}
|
|
|
|
|
2007-09-12 10:46:58 -07:00
|
|
|
//! An alternate transform vector method, writing into a second vector
|
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::rotateVect(core::vector3df& out, const core::vector3df& in) const
|
|
|
|
{
|
|
|
|
out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
|
|
|
|
out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
|
|
|
|
out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
|
|
|
|
}
|
|
|
|
|
2007-05-20 11:03:49 -07:00
|
|
|
//! An alternate transform vector method, writing into an array of 3 floats
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2007-09-12 10:46:58 -07:00
|
|
|
inline void CMatrix4<T>::rotateVect(T *out, const core::vector3df& in) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8];
|
|
|
|
out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9];
|
|
|
|
out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10];
|
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::inverseRotateVect( vector3df& vect ) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
vector3df tmp = vect;
|
|
|
|
vect.X = tmp.X*M[0] + tmp.Y*M[1] + tmp.Z*M[2];
|
|
|
|
vect.Y = tmp.X*M[4] + tmp.Y*M[5] + tmp.Z*M[6];
|
|
|
|
vect.Z = tmp.X*M[8] + tmp.Y*M[9] + tmp.Z*M[10];
|
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::transformVect( vector3df& vect) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
f32 vector[3];
|
|
|
|
|
|
|
|
vector[0] = vect.X*M[0] + vect.Y*M[4] + vect.Z*M[8] + M[12];
|
|
|
|
vector[1] = vect.X*M[1] + vect.Y*M[5] + vect.Z*M[9] + M[13];
|
|
|
|
vector[2] = vect.X*M[2] + vect.Y*M[6] + vect.Z*M[10] + M[14];
|
|
|
|
|
|
|
|
vect.X = vector[0];
|
|
|
|
vect.Y = vector[1];
|
|
|
|
vect.Z = vector[2];
|
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::transformVect( vector3df& out, const vector3df& in) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
out.X = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
|
|
|
|
out.Y = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
|
|
|
|
out.Z = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::transformVect(T *out,const vector3df &in) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
out[0] = in.X*M[0] + in.Y*M[4] + in.Z*M[8] + M[12];
|
|
|
|
out[1] = in.X*M[1] + in.Y*M[5] + in.Z*M[9] + M[13];
|
|
|
|
out[2] = in.X*M[2] + in.Y*M[6] + in.Z*M[10] + M[14];
|
|
|
|
out[3] = in.X*M[3] + in.Y*M[7] + in.Z*M[11] + M[15];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! Transforms a plane by this matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::transformPlane( core::plane3d<f32> &plane) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
vector3df member;
|
|
|
|
transformVect(member, plane.getMemberPoint());
|
|
|
|
|
|
|
|
vector3df origin(0,0,0);
|
|
|
|
transformVect(plane.Normal);
|
|
|
|
transformVect(origin);
|
|
|
|
|
|
|
|
plane.Normal -= origin;
|
|
|
|
plane.D = - member.dotProduct(plane.Normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Transforms a plane by this matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::transformPlane_new( core::plane3d<f32> &plane) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
// rotate normal -> rotateVect ( plane.n );
|
|
|
|
vector3df n;
|
|
|
|
n.X = plane.Normal.X*M[0] + plane.Normal.Y*M[4] + plane.Normal.Z*M[8];
|
|
|
|
n.Y = plane.Normal.X*M[1] + plane.Normal.Y*M[5] + plane.Normal.Z*M[9];
|
|
|
|
n.Z = plane.Normal.X*M[2] + plane.Normal.Y*M[6] + plane.Normal.Z*M[10];
|
|
|
|
|
|
|
|
// compute new d. -> getTranslation(). dotproduct ( plane.n )
|
|
|
|
plane.D -= M[12] * n.X + M[13] * n.Y + M[14] * n.Z;
|
|
|
|
plane.Normal.X = n.X;
|
|
|
|
plane.Normal.Y = n.Y;
|
|
|
|
plane.Normal.Z = n.Z;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Transforms a plane by this matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::transformPlane( const core::plane3d<f32> &in, core::plane3d<f32> &out) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
out = in;
|
|
|
|
transformPlane( out );
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Transforms a axis aligned bounding box
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::transformBox(core::aabbox3d<f32>& box) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
if (isIdentity() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
transformVect(box.MinEdge);
|
|
|
|
transformVect(box.MaxEdge);
|
|
|
|
box.repair();
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Transforms a axis aligned bounding box more accurately than transformBox()
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::transformBoxEx(core::aabbox3d<f32>& box) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
f32 Amin[3];
|
|
|
|
f32 Amax[3];
|
|
|
|
f32 Bmin[3];
|
|
|
|
f32 Bmax[3];
|
2007-10-02 07:24:45 -07:00
|
|
|
|
2007-05-20 11:03:49 -07:00
|
|
|
Amin[0] = box.MinEdge.X;
|
|
|
|
Amin[1] = box.MinEdge.Y;
|
|
|
|
Amin[2] = box.MinEdge.Z;
|
|
|
|
|
|
|
|
Amax[0] = box.MaxEdge.X;
|
|
|
|
Amax[1] = box.MaxEdge.Y;
|
|
|
|
Amax[2] = box.MaxEdge.Z;
|
|
|
|
|
|
|
|
Bmin[0] = Bmax[0] = M[12];
|
|
|
|
Bmin[1] = Bmax[1] = M[13];
|
|
|
|
Bmin[2] = Bmax[2] = M[14];
|
|
|
|
|
|
|
|
u32 i, j;
|
2007-06-02 03:37:00 -07:00
|
|
|
const CMatrix4<T> &m = *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-10-02 07:24:45 -07:00
|
|
|
for (i = 0; i < 3; ++i)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-10-02 07:24:45 -07:00
|
|
|
for (j = 0; j < 3; ++j)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
f32 a = m(j,i) * Amin[j];
|
|
|
|
f32 b = m(j,i) * Amax[j];
|
|
|
|
|
|
|
|
if (a < b)
|
|
|
|
{
|
|
|
|
Bmin[i] += a;
|
|
|
|
Bmax[i] += b;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Bmin[i] += b;
|
|
|
|
Bmax[i] += a;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
box.MinEdge.X = Bmin[0];
|
|
|
|
box.MinEdge.Y = Bmin[1];
|
|
|
|
box.MinEdge.Z = Bmin[2];
|
|
|
|
|
|
|
|
box.MaxEdge.X = Bmax[0];
|
|
|
|
box.MaxEdge.Y = Bmax[1];
|
|
|
|
box.MaxEdge.Z = Bmax[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! Multiplies this matrix by a 1x4 matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::multiplyWith1x4Matrix(T* matrix) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
0 1 2 3
|
|
|
|
4 5 6 7
|
|
|
|
8 9 10 11
|
|
|
|
12 13 14 15
|
|
|
|
*/
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
T mat[4];
|
2007-05-20 11:03:49 -07:00
|
|
|
mat[0] = matrix[0];
|
|
|
|
mat[1] = matrix[1];
|
|
|
|
mat[2] = matrix[2];
|
|
|
|
mat[3] = matrix[3];
|
|
|
|
|
|
|
|
matrix[0] = M[0]*mat[0] + M[4]*mat[1] + M[8]*mat[2] + M[12]*mat[3];
|
|
|
|
matrix[1] = M[1]*mat[0] + M[5]*mat[1] + M[9]*mat[2] + M[13]*mat[3];
|
|
|
|
matrix[2] = M[2]*mat[0] + M[6]*mat[1] + M[10]*mat[2] + M[14]*mat[3];
|
|
|
|
matrix[3] = M[3]*mat[0] + M[7]*mat[1] + M[11]*mat[2] + M[15]*mat[3];
|
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::inverseTranslateVect( vector3df& vect ) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
vect.X = vect.X-M[12];
|
|
|
|
vect.Y = vect.Y-M[13];
|
|
|
|
vect.Z = vect.Z-M[14];
|
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::translateVect( vector3df& vect ) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
vect.X = vect.X+M[12];
|
|
|
|
vect.Y = vect.Y+M[13];
|
|
|
|
vect.Z = vect.Z+M[14];
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline bool CMatrix4<T>::getInverse(CMatrix4<T>& out) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
/// Calculates the inverse of this Matrix
|
|
|
|
/// The inverse is calculated using Cramers rule.
|
|
|
|
/// If no inverse exists then 'false' is returned.
|
|
|
|
|
2007-10-02 07:24:45 -07:00
|
|
|
if ( this->isIdentity() )
|
|
|
|
{
|
|
|
|
out=*this;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
const CMatrix4<T> &m = *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
f32 d = (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) -
|
|
|
|
(m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
|
|
|
|
(m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)) +
|
|
|
|
(m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) -
|
|
|
|
(m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
|
|
|
|
(m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0));
|
|
|
|
|
|
|
|
if( core::iszero ( d ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
d = core::reciprocal ( d );
|
|
|
|
|
2008-04-29 04:34:54 -07:00
|
|
|
out(0, 0) = d * (m(1, 1) * (m(2, 2) * m(3, 3) - m(2, 3) * m(3, 2)) +
|
|
|
|
m(1, 2) * (m(2, 3) * m(3, 1) - m(2, 1) * m(3, 3)) +
|
|
|
|
m(1, 3) * (m(2, 1) * m(3, 2) - m(2, 2) * m(3, 1)));
|
|
|
|
out(0, 1) = d * (m(2, 1) * (m(0, 2) * m(3, 3) - m(0, 3) * m(3, 2)) +
|
|
|
|
m(2, 2) * (m(0, 3) * m(3, 1) - m(0, 1) * m(3, 3)) +
|
|
|
|
m(2, 3) * (m(0, 1) * m(3, 2) - m(0, 2) * m(3, 1)));
|
|
|
|
out(0, 2) = d * (m(3, 1) * (m(0, 2) * m(1, 3) - m(0, 3) * m(1, 2)) +
|
|
|
|
m(3, 2) * (m(0, 3) * m(1, 1) - m(0, 1) * m(1, 3)) +
|
|
|
|
m(3, 3) * (m(0, 1) * m(1, 2) - m(0, 2) * m(1, 1)));
|
|
|
|
out(0, 3) = d * (m(0, 1) * (m(1, 3) * m(2, 2) - m(1, 2) * m(2, 3)) +
|
|
|
|
m(0, 2) * (m(1, 1) * m(2, 3) - m(1, 3) * m(2, 1)) +
|
|
|
|
m(0, 3) * (m(1, 2) * m(2, 1) - m(1, 1) * m(2, 2)));
|
|
|
|
out(1, 0) = d * (m(1, 2) * (m(2, 0) * m(3, 3) - m(2, 3) * m(3, 0)) +
|
|
|
|
m(1, 3) * (m(2, 2) * m(3, 0) - m(2, 0) * m(3, 2)) +
|
|
|
|
m(1, 0) * (m(2, 3) * m(3, 2) - m(2, 2) * m(3, 3)));
|
|
|
|
out(1, 1) = d * (m(2, 2) * (m(0, 0) * m(3, 3) - m(0, 3) * m(3, 0)) +
|
|
|
|
m(2, 3) * (m(0, 2) * m(3, 0) - m(0, 0) * m(3, 2)) +
|
|
|
|
m(2, 0) * (m(0, 3) * m(3, 2) - m(0, 2) * m(3, 3)));
|
|
|
|
out(1, 2) = d * (m(3, 2) * (m(0, 0) * m(1, 3) - m(0, 3) * m(1, 0)) +
|
|
|
|
m(3, 3) * (m(0, 2) * m(1, 0) - m(0, 0) * m(1, 2)) +
|
|
|
|
m(3, 0) * (m(0, 3) * m(1, 2) - m(0, 2) * m(1, 3)));
|
|
|
|
out(1, 3) = d * (m(0, 2) * (m(1, 3) * m(2, 0) - m(1, 0) * m(2, 3)) +
|
|
|
|
m(0, 3) * (m(1, 0) * m(2, 2) - m(1, 2) * m(2, 0)) +
|
|
|
|
m(0, 0) * (m(1, 2) * m(2, 3) - m(1, 3) * m(2, 2)));
|
|
|
|
out(2, 0) = d * (m(1, 3) * (m(2, 0) * m(3, 1) - m(2, 1) * m(3, 0)) +
|
|
|
|
m(1, 0) * (m(2, 1) * m(3, 3) - m(2, 3) * m(3, 1)) +
|
|
|
|
m(1, 1) * (m(2, 3) * m(3, 0) - m(2, 0) * m(3, 3)));
|
|
|
|
out(2, 1) = d * (m(2, 3) * (m(0, 0) * m(3, 1) - m(0, 1) * m(3, 0)) +
|
|
|
|
m(2, 0) * (m(0, 1) * m(3, 3) - m(0, 3) * m(3, 1)) +
|
|
|
|
m(2, 1) * (m(0, 3) * m(3, 0) - m(0, 0) * m(3, 3)));
|
|
|
|
out(2, 2) = d * (m(3, 3) * (m(0, 0) * m(1, 1) - m(0, 1) * m(1, 0)) +
|
|
|
|
m(3, 0) * (m(0, 1) * m(1, 3) - m(0, 3) * m(1, 1)) +
|
|
|
|
m(3, 1) * (m(0, 3) * m(1, 0) - m(0, 0) * m(1, 3)));
|
|
|
|
out(2, 3) = d * (m(0, 3) * (m(1, 1) * m(2, 0) - m(1, 0) * m(2, 1)) +
|
|
|
|
m(0, 0) * (m(1, 3) * m(2, 1) - m(1, 1) * m(2, 3)) +
|
|
|
|
m(0, 1) * (m(1, 0) * m(2, 3) - m(1, 3) * m(2, 0)));
|
|
|
|
out(3, 0) = d * (m(1, 0) * (m(2, 2) * m(3, 1) - m(2, 1) * m(3, 2)) +
|
|
|
|
m(1, 1) * (m(2, 0) * m(3, 2) - m(2, 2) * m(3, 0)) +
|
|
|
|
m(1, 2) * (m(2, 1) * m(3, 0) - m(2, 0) * m(3, 1)));
|
|
|
|
out(3, 1) = d * (m(2, 0) * (m(0, 2) * m(3, 1) - m(0, 1) * m(3, 2)) +
|
|
|
|
m(2, 1) * (m(0, 0) * m(3, 2) - m(0, 2) * m(3, 0)) +
|
|
|
|
m(2, 2) * (m(0, 1) * m(3, 0) - m(0, 0) * m(3, 1)));
|
|
|
|
out(3, 2) = d * (m(3, 0) * (m(0, 2) * m(1, 1) - m(0, 1) * m(1, 2)) +
|
|
|
|
m(3, 1) * (m(0, 0) * m(1, 2) - m(0, 2) * m(1, 0)) +
|
|
|
|
m(3, 2) * (m(0, 1) * m(1, 0) - m(0, 0) * m(1, 1)));
|
|
|
|
out(3, 3) = d * (m(0, 0) * (m(1, 1) * m(2, 2) - m(1, 2) * m(2, 1)) +
|
|
|
|
m(0, 1) * (m(1, 2) * m(2, 0) - m(1, 0) * m(2, 2)) +
|
|
|
|
m(0, 2) * (m(1, 0) * m(2, 1) - m(1, 1) * m(2, 0)));
|
2007-05-20 11:03:49 -07:00
|
|
|
out.definitelyIdentityMatrix = definitelyIdentityMatrix;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! Inverts a primitive matrix which only contains a translation and a rotation
|
|
|
|
//! \param out: where result matrix is written to.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline bool CMatrix4<T>::getInversePrimitive ( CMatrix4<T>& out ) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
out.M[0 ] = M[0];
|
|
|
|
out.M[1 ] = M[4];
|
|
|
|
out.M[2 ] = M[8];
|
2007-06-02 03:37:00 -07:00
|
|
|
out.M[3 ] = 0;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
out.M[4 ] = M[1];
|
|
|
|
out.M[5 ] = M[5];
|
|
|
|
out.M[6 ] = M[9];
|
2007-06-02 03:37:00 -07:00
|
|
|
out.M[7 ] = 0;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
out.M[8 ] = M[2];
|
|
|
|
out.M[9 ] = M[6];
|
|
|
|
out.M[10] = M[10];
|
2007-06-02 03:37:00 -07:00
|
|
|
out.M[11] = 0;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
out.M[12] = (T)-(M[12]*M[0] + M[13]*M[1] + M[14]*M[2]);
|
|
|
|
out.M[13] = (T)-(M[12]*M[4] + M[13]*M[5] + M[14]*M[6]);
|
|
|
|
out.M[14] = (T)-(M[12]*M[8] + M[13]*M[9] + M[14]*M[10]);
|
|
|
|
out.M[15] = 1;
|
2007-05-20 11:03:49 -07:00
|
|
|
out.definitelyIdentityMatrix = definitelyIdentityMatrix;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
*/
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline bool CMatrix4<T>::makeInverse()
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-10-02 15:20:57 -07:00
|
|
|
if (definitelyIdentityMatrix)
|
|
|
|
return true;
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> temp ( EM4CONST_NOTHING );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
if (getInverse(temp))
|
|
|
|
{
|
|
|
|
*this = temp;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T>& CMatrix4<T>::operator=(const CMatrix4<T> &other)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
if (this==&other)
|
|
|
|
return *this;
|
2007-06-02 03:37:00 -07:00
|
|
|
memcpy(M, other.M, 16*sizeof(T));
|
2007-05-20 11:03:49 -07:00
|
|
|
definitelyIdentityMatrix=other.definitelyIdentityMatrix;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T>& CMatrix4<T>::operator=(const T& scalar)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
for (s32 i = 0; i < 16; ++i)
|
|
|
|
M[i]=scalar;
|
|
|
|
definitelyIdentityMatrix=false;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline bool CMatrix4<T>::operator==(const CMatrix4<T> &other) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
if (definitelyIdentityMatrix && other.definitelyIdentityMatrix)
|
|
|
|
return true;
|
|
|
|
for (s32 i = 0; i < 16; ++i)
|
|
|
|
if (M[i] != other.M[i])
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline bool CMatrix4<T>::operator!=(const CMatrix4<T> &other) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
return !(*this == other);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Builds a right-handed perspective projection matrix based on a field of view
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-29 04:34:54 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovRH(
|
|
|
|
f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2008-04-12 16:02:15 -07:00
|
|
|
const f64 h = 1.0/tan(fieldOfViewRadians/2.0);
|
|
|
|
const T w = h / aspectRatio;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
M[0] = w;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[1] = 0;
|
|
|
|
M[2] = 0;
|
|
|
|
M[3] = 0;
|
|
|
|
|
|
|
|
M[4] = 0;
|
|
|
|
M[5] = (T)h;
|
|
|
|
M[6] = 0;
|
|
|
|
M[7] = 0;
|
|
|
|
|
|
|
|
M[8] = 0;
|
|
|
|
M[9] = 0;
|
|
|
|
M[10] = (T)(zFar/(zNear-zFar)); // DirectX version
|
|
|
|
// M[10] = (T)(zFar+zNear/(zNear-zFar)); // OpenGL version
|
|
|
|
M[11] = -1;
|
|
|
|
|
|
|
|
M[12] = 0;
|
|
|
|
M[13] = 0;
|
|
|
|
M[14] = (T)(zNear*zFar/(zNear-zFar)); // DirectX version
|
|
|
|
// M[14] = (T)(2.0f*zNear*zFar/(zNear-zFar)); // OpenGL version
|
|
|
|
M[15] = 0;
|
2007-05-20 11:03:49 -07:00
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Builds a left-handed perspective projection matrix based on a field of view
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-29 04:34:54 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveFovLH(
|
|
|
|
f32 fieldOfViewRadians, f32 aspectRatio, f32 zNear, f32 zFar)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2008-04-12 16:02:15 -07:00
|
|
|
const f64 h = 1.0/tan(fieldOfViewRadians/2.0);
|
|
|
|
const T w = (T)(h / aspectRatio);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
M[0] = w;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[1] = 0;
|
|
|
|
M[2] = 0;
|
|
|
|
M[3] = 0;
|
|
|
|
|
|
|
|
M[4] = 0;
|
|
|
|
M[5] = (T)h;
|
|
|
|
M[6] = 0;
|
|
|
|
M[7] = 0;
|
|
|
|
|
|
|
|
M[8] = 0;
|
|
|
|
M[9] = 0;
|
|
|
|
M[10] = (T)(zFar/(zFar-zNear));
|
|
|
|
M[11] = 1;
|
|
|
|
|
|
|
|
M[12] = 0;
|
|
|
|
M[13] = 0;
|
|
|
|
M[14] = (T)(-zNear*zFar/(zFar-zNear));
|
|
|
|
M[15] = 0;
|
2007-05-20 11:03:49 -07:00
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! Builds a left-handed orthogonal projection matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-29 04:34:54 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoLH(
|
|
|
|
f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)(2/widthOfViewVolume);
|
2007-05-20 11:03:49 -07:00
|
|
|
M[1] = 0;
|
|
|
|
M[2] = 0;
|
|
|
|
M[3] = 0;
|
|
|
|
|
|
|
|
M[4] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[5] = (T)(2/heightOfViewVolume);
|
2007-05-20 11:03:49 -07:00
|
|
|
M[6] = 0;
|
|
|
|
M[7] = 0;
|
|
|
|
|
|
|
|
M[8] = 0;
|
|
|
|
M[9] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[10] = (T)(1/(zFar-zNear));
|
2007-05-20 11:03:49 -07:00
|
|
|
M[11] = 0;
|
|
|
|
|
|
|
|
M[12] = 0;
|
|
|
|
M[13] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[14] = (T)(zNear/(zNear-zFar));
|
2007-05-20 11:03:49 -07:00
|
|
|
M[15] = 1;
|
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Builds a right-handed orthogonal projection matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-29 04:34:54 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixOrthoRH(
|
|
|
|
f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)(2/widthOfViewVolume);
|
2007-05-20 11:03:49 -07:00
|
|
|
M[1] = 0;
|
|
|
|
M[2] = 0;
|
|
|
|
M[3] = 0;
|
|
|
|
|
|
|
|
M[4] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[5] = (T)(2/heightOfViewVolume);
|
2007-05-20 11:03:49 -07:00
|
|
|
M[6] = 0;
|
|
|
|
M[7] = 0;
|
|
|
|
|
|
|
|
M[8] = 0;
|
|
|
|
M[9] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[10] = (T)(1/(zNear-zFar));
|
2007-05-20 11:03:49 -07:00
|
|
|
M[11] = 0;
|
|
|
|
|
|
|
|
M[12] = 0;
|
|
|
|
M[13] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[14] = (T)(zNear/(zNear-zFar));
|
2007-05-20 11:03:49 -07:00
|
|
|
M[15] = -1;
|
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! Builds a right-handed perspective projection matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-29 04:34:54 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveRH(
|
|
|
|
f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)(2*zNear/widthOfViewVolume);
|
2007-05-20 11:03:49 -07:00
|
|
|
M[1] = 0;
|
|
|
|
M[2] = 0;
|
|
|
|
M[3] = 0;
|
|
|
|
|
|
|
|
M[4] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[5] = (T)(2*zNear/heightOfViewVolume);
|
2007-05-20 11:03:49 -07:00
|
|
|
M[6] = 0;
|
|
|
|
M[7] = 0;
|
|
|
|
|
|
|
|
M[8] = 0;
|
|
|
|
M[9] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[10] = (T)(zFar/(zNear-zFar));
|
2007-05-20 11:03:49 -07:00
|
|
|
M[11] = -1;
|
|
|
|
|
|
|
|
M[12] = 0;
|
|
|
|
M[13] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[14] = (T)(zNear*zFar/(zNear-zFar));
|
2007-05-20 11:03:49 -07:00
|
|
|
M[15] = 0;
|
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! Builds a left-handed perspective projection matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-29 04:34:54 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildProjectionMatrixPerspectiveLH(
|
|
|
|
f32 widthOfViewVolume, f32 heightOfViewVolume, f32 zNear, f32 zFar)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)(2*zNear/widthOfViewVolume);
|
2007-05-20 11:03:49 -07:00
|
|
|
M[1] = 0;
|
|
|
|
M[2] = 0;
|
|
|
|
M[3] = 0;
|
|
|
|
|
|
|
|
M[4] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[5] = (T)(2*zNear/heightOfViewVolume);
|
2007-05-20 11:03:49 -07:00
|
|
|
M[6] = 0;
|
|
|
|
M[7] = 0;
|
|
|
|
|
|
|
|
M[8] = 0;
|
|
|
|
M[9] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[10] = (T)(zFar/(zFar-zNear));
|
2007-05-20 11:03:49 -07:00
|
|
|
M[11] = 1;
|
|
|
|
|
|
|
|
M[12] = 0;
|
|
|
|
M[13] = 0;
|
2007-06-02 03:37:00 -07:00
|
|
|
M[14] = (T)(zNear*zFar/(zNear-zFar));
|
2007-05-20 11:03:49 -07:00
|
|
|
M[15] = 0;
|
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//! Builds a matrix that flattens geometry into a plane.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildShadowMatrix(const core::vector3df& light, core::plane3df plane, f32 point)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
plane.Normal.normalize();
|
2008-04-12 16:02:15 -07:00
|
|
|
const f32 d = plane.Normal.dotProduct(light);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[ 0] = (T)(-plane.Normal.X * light.X + d);
|
|
|
|
M[ 1] = (T)(-plane.Normal.X * light.Y);
|
|
|
|
M[ 2] = (T)(-plane.Normal.X * light.Z);
|
|
|
|
M[ 3] = (T)(-plane.Normal.X * point);
|
|
|
|
|
|
|
|
M[ 4] = (T)(-plane.Normal.Y * light.X);
|
|
|
|
M[ 5] = (T)(-plane.Normal.Y * light.Y + d);
|
|
|
|
M[ 6] = (T)(-plane.Normal.Y * light.Z);
|
|
|
|
M[ 7] = (T)(-plane.Normal.Y * point);
|
|
|
|
|
|
|
|
M[ 8] = (T)(-plane.Normal.Z * light.X);
|
|
|
|
M[ 9] = (T)(-plane.Normal.Z * light.Y);
|
|
|
|
M[10] = (T)(-plane.Normal.Z * light.Z + d);
|
|
|
|
M[11] = (T)(-plane.Normal.Z * point);
|
|
|
|
|
|
|
|
M[12] = (T)(-plane.D * light.X);
|
|
|
|
M[13] = (T)(-plane.D * light.Y);
|
|
|
|
M[14] = (T)(-plane.D * light.Z);
|
2007-10-02 07:24:45 -07:00
|
|
|
M[15] = (T)(-plane.D * point + d);
|
2007-05-20 11:03:49 -07:00
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//! Builds a left-handed look-at matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixLH(
|
2007-05-20 11:03:49 -07:00
|
|
|
const vector3df& position,
|
|
|
|
const vector3df& target,
|
|
|
|
const vector3df& upVector)
|
|
|
|
{
|
|
|
|
vector3df zaxis = target - position;
|
|
|
|
zaxis.normalize();
|
|
|
|
|
|
|
|
vector3df xaxis = upVector.crossProduct(zaxis);
|
|
|
|
xaxis.normalize();
|
|
|
|
|
|
|
|
vector3df yaxis = zaxis.crossProduct(xaxis);
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)xaxis.X;
|
|
|
|
M[1] = (T)yaxis.X;
|
|
|
|
M[2] = (T)zaxis.X;
|
2007-05-20 11:03:49 -07:00
|
|
|
M[3] = 0;
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[4] = (T)xaxis.Y;
|
|
|
|
M[5] = (T)yaxis.Y;
|
|
|
|
M[6] = (T)zaxis.Y;
|
2007-05-20 11:03:49 -07:00
|
|
|
M[7] = 0;
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[8] = (T)xaxis.Z;
|
|
|
|
M[9] = (T)yaxis.Z;
|
|
|
|
M[10] = (T)zaxis.Z;
|
2007-05-20 11:03:49 -07:00
|
|
|
M[11] = 0;
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[12] = (T)-xaxis.dotProduct(position);
|
|
|
|
M[13] = (T)-yaxis.dotProduct(position);
|
|
|
|
M[14] = (T)-zaxis.dotProduct(position);
|
|
|
|
M[15] = 1;
|
2007-05-20 11:03:49 -07:00
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//! Builds a right-handed look-at matrix.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildCameraLookAtMatrixRH(
|
2007-05-20 11:03:49 -07:00
|
|
|
const vector3df& position,
|
|
|
|
const vector3df& target,
|
|
|
|
const vector3df& upVector)
|
|
|
|
{
|
|
|
|
vector3df zaxis = position - target;
|
|
|
|
zaxis.normalize();
|
|
|
|
|
|
|
|
vector3df xaxis = upVector.crossProduct(zaxis);
|
|
|
|
xaxis.normalize();
|
|
|
|
|
|
|
|
vector3df yaxis = zaxis.crossProduct(xaxis);
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)xaxis.X;
|
|
|
|
M[1] = (T)yaxis.X;
|
|
|
|
M[2] = (T)zaxis.X;
|
2007-05-20 11:03:49 -07:00
|
|
|
M[3] = 0;
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[4] = (T)xaxis.Y;
|
|
|
|
M[5] = (T)yaxis.Y;
|
|
|
|
M[6] = (T)zaxis.Y;
|
2007-05-20 11:03:49 -07:00
|
|
|
M[7] = 0;
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[8] = (T)xaxis.Z;
|
|
|
|
M[9] = (T)yaxis.Z;
|
|
|
|
M[10] = (T)zaxis.Z;
|
2007-05-20 11:03:49 -07:00
|
|
|
M[11] = 0;
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[12] = (T)-xaxis.dotProduct(position);
|
|
|
|
M[13] = (T)-yaxis.dotProduct(position);
|
|
|
|
M[14] = (T)-zaxis.dotProduct(position);
|
|
|
|
M[15] = 1;
|
2007-05-20 11:03:49 -07:00
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-12 16:02:15 -07:00
|
|
|
//! creates a new matrix as interpolated matrix from this and the passed one.
|
|
|
|
//! \param b: Second matrix to interpolate with
|
2007-05-20 11:03:49 -07:00
|
|
|
//! \param time: Must be a value between 0 and 1.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T> CMatrix4<T>::interpolate(const core::CMatrix4<T>& b, f32 time) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> mat ( EM4CONST_NOTHING );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
for (u32 i=0; i < 16; i += 4)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
mat.M[i+0] = (T)(M[i+0] + ( b.M[i+0] - M[i+0] ) * time);
|
|
|
|
mat.M[i+1] = (T)(M[i+1] + ( b.M[i+1] - M[i+1] ) * time);
|
|
|
|
mat.M[i+2] = (T)(M[i+2] + ( b.M[i+2] - M[i+2] ) * time);
|
|
|
|
mat.M[i+3] = (T)(M[i+3] + ( b.M[i+3] - M[i+3] ) * time);
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
return mat;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! returns transposed matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T> CMatrix4<T>::getTransposed() const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
CMatrix4<T> t ( EM4CONST_NOTHING );
|
2007-05-20 11:03:49 -07:00
|
|
|
getTransposed ( t );
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! returns transposed matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::getTransposed( CMatrix4<T>& o ) const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
o[ 0] = M[ 0];
|
|
|
|
o[ 1] = M[ 4];
|
|
|
|
o[ 2] = M[ 8];
|
|
|
|
o[ 3] = M[12];
|
|
|
|
|
|
|
|
o[ 4] = M[ 1];
|
|
|
|
o[ 5] = M[ 5];
|
|
|
|
o[ 6] = M[ 9];
|
|
|
|
o[ 7] = M[13];
|
|
|
|
|
|
|
|
o[ 8] = M[ 2];
|
|
|
|
o[ 9] = M[ 6];
|
|
|
|
o[10] = M[10];
|
|
|
|
o[11] = M[14];
|
|
|
|
|
|
|
|
o[12] = M[ 3];
|
|
|
|
o[13] = M[ 7];
|
|
|
|
o[14] = M[11];
|
|
|
|
o[15] = M[15];
|
|
|
|
o.definitelyIdentityMatrix=definitelyIdentityMatrix;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// used to scale <-1,-1><1,1> to viewport
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildNDCToDCMatrix( const core::rect<s32>& viewport, f32 zScale)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2008-04-12 16:02:15 -07:00
|
|
|
const f32 scaleX = (viewport.getWidth() - 0.75f ) / 2.0f;
|
|
|
|
const f32 scaleY = -(viewport.getHeight() - 0.75f ) / 2.0f;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2008-04-12 16:02:15 -07:00
|
|
|
const f32 dx = -0.5f + ( (viewport.UpperLeftCorner.X + viewport.LowerRightCorner.X ) / 2.0f );
|
|
|
|
const f32 dy = -0.5f + ( (viewport.UpperLeftCorner.Y + viewport.LowerRightCorner.Y ) / 2.0f );
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
makeIdentity();
|
2007-06-02 03:37:00 -07:00
|
|
|
M[12] = (T)dx;
|
|
|
|
M[13] = (T)dy;
|
2008-04-12 16:02:15 -07:00
|
|
|
return setScale(core::vector3d<T>((T)scaleX, (T)scaleY, (T)zScale));
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Generate texture coordinates as linear functions so that:
|
2007-10-02 07:24:45 -07:00
|
|
|
u = Ux*x + Uy*y + Uz*z + Uw
|
2007-05-20 11:03:49 -07:00
|
|
|
v = Vx*x + Vy*y + Vz*z + Vw
|
|
|
|
The matrix M for this case is:
|
2007-10-02 07:24:45 -07:00
|
|
|
Ux Vx 0 0
|
|
|
|
Uy Vy 0 0
|
|
|
|
Uz Vz 0 0
|
|
|
|
Uw Vw 0 0
|
2007-05-20 11:03:49 -07:00
|
|
|
*/
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::buildTextureTransform( f32 rotateRad,
|
2008-04-29 04:34:54 -07:00
|
|
|
const core::vector2df &rotatecenter,
|
|
|
|
const core::vector2df &translate,
|
|
|
|
const core::vector2df &scale)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-10-17 09:24:01 -07:00
|
|
|
const f32 c = cosf(rotateRad);
|
|
|
|
const f32 s = sinf(rotateRad);
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)(c * scale.X);
|
|
|
|
M[1] = (T)(s * scale.Y);
|
|
|
|
M[2] = 0;
|
|
|
|
M[3] = 0;
|
|
|
|
|
|
|
|
M[4] = (T)(-s * scale.X);
|
|
|
|
M[5] = (T)(c * scale.Y);
|
|
|
|
M[6] = 0;
|
|
|
|
M[7] = 0;
|
|
|
|
|
|
|
|
M[8] = (T)(c * scale.X * rotatecenter.X + -s * rotatecenter.Y + translate.X);
|
|
|
|
M[9] = (T)(s * scale.Y * rotatecenter.X + c * rotatecenter.Y + translate.Y);
|
|
|
|
M[10] = 1;
|
|
|
|
M[11] = 0;
|
|
|
|
|
|
|
|
M[12] = 0;
|
|
|
|
M[13] = 0;
|
|
|
|
M[14] = 0;
|
|
|
|
M[15] = 1;
|
2007-05-20 11:03:49 -07:00
|
|
|
definitelyIdentityMatrix=false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//! rotate about z axis, center ( 0.5, 0.5 )
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setTextureRotationCenter( f32 rotateRad )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-10-17 09:24:01 -07:00
|
|
|
const f32 c = cosf(rotateRad);
|
|
|
|
const f32 s = sinf(rotateRad);
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)c;
|
|
|
|
M[1] = (T)s;
|
2007-05-20 11:03:49 -07:00
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
M[4] = (T)-s;
|
|
|
|
M[5] = (T)c;
|
2008-04-12 16:02:15 -07:00
|
|
|
|
|
|
|
M[8] = (T)(0.5f * ( s - c) + 0.5f);
|
|
|
|
M[9] = (T)(-0.5f * ( s + c) + 0.5f);
|
|
|
|
definitelyIdentityMatrix = definitelyIdentityMatrix && (rotateRad==0.0f);
|
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setTextureTranslate ( f32 x, f32 y )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-10-17 09:24:01 -07:00
|
|
|
M[8] = (T)x;
|
|
|
|
M[9] = (T)y;
|
2008-04-12 16:02:15 -07:00
|
|
|
definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f);
|
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2007-11-13 06:35:29 -08:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setTextureTranslateTransposed ( f32 x, f32 y )
|
2007-11-13 06:35:29 -08:00
|
|
|
{
|
|
|
|
M[2] = (T)x;
|
|
|
|
M[6] = (T)y;
|
|
|
|
definitelyIdentityMatrix = definitelyIdentityMatrix && (x==0.0f) && (y==0.0f) ;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-11-13 06:35:29 -08:00
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setTextureScale ( f32 sx, f32 sy )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)sx;
|
|
|
|
M[5] = (T)sy;
|
2008-04-12 16:02:15 -07:00
|
|
|
definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
|
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setTextureScaleCenter( f32 sx, f32 sy )
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2007-06-02 03:37:00 -07:00
|
|
|
M[0] = (T)sx;
|
|
|
|
M[5] = (T)sy;
|
2008-04-12 16:02:15 -07:00
|
|
|
M[8] = (T)(0.5f - 0.5f * sx);
|
|
|
|
M[9] = (T)(0.5f - 0.5f * sy);
|
|
|
|
definitelyIdentityMatrix = definitelyIdentityMatrix && (sx==1.0f) && (sy==1.0f);
|
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//! sets all matrix data members at once
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
2008-04-12 16:02:15 -07:00
|
|
|
inline CMatrix4<T>& CMatrix4<T>::setM(const T* data)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
2008-04-12 16:02:15 -07:00
|
|
|
memcpy(M,data, 16*sizeof(T));
|
2007-05-20 11:03:49 -07:00
|
|
|
|
|
|
|
definitelyIdentityMatrix = false;
|
2008-04-12 16:02:15 -07:00
|
|
|
return *this;
|
2007-05-20 11:03:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//! sets if the matrix is definitely identity matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline void CMatrix4<T>::setDefinitelyIdentityMatrix( bool isDefinitelyIdentityMatrix)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
definitelyIdentityMatrix = isDefinitelyIdentityMatrix;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! gets if the matrix is definitely identity matrix
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline bool CMatrix4<T>::getDefinitelyIdentityMatrix() const
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
return definitelyIdentityMatrix;
|
|
|
|
}
|
|
|
|
|
|
|
|
//! Multiply by scalar.
|
2007-06-02 03:37:00 -07:00
|
|
|
template <class T>
|
|
|
|
inline CMatrix4<T> operator*(const T scalar, const CMatrix4<T>& mat)
|
2007-05-20 11:03:49 -07:00
|
|
|
{
|
|
|
|
return mat*scalar;
|
|
|
|
}
|
|
|
|
|
2007-06-02 03:37:00 -07:00
|
|
|
typedef CMatrix4<f32> matrix4;
|
2007-05-20 11:03:49 -07:00
|
|
|
const matrix4 IdentityMatrix(matrix4::EM4CONST_IDENTITY);
|
|
|
|
|
|
|
|
} // end namespace core
|
|
|
|
} // end namespace irr
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|