2009-02-22 10:43:35 +00:00
#region - - - License - - -
/ *
Copyright ( c ) 2006 - 2008 The Open Toolkit library .
Permission is hereby granted , free of charge , to any person obtaining a copy of
this software and associated documentation files ( the "Software" ) , to deal in
the Software without restriction , including without limitation the rights to
use , copy , modify , merge , publish , distribute , sublicense , and / or sell copies
of the Software , and to permit persons to whom the Software is furnished to do
so , subject to the following conditions :
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software .
THE SOFTWARE IS PROVIDED "AS IS" , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE .
* /
#endregion
using System ;
using System.Runtime.InteropServices ;
2009-06-25 11:42:05 +00:00
namespace OpenTK
2009-02-22 10:43:35 +00:00
{
/// <summary>
2013-03-20 12:44:12 +00:00
/// Represents a 4x4 matrix containing 3D rotation, scale, transform, and projection.
2009-02-22 10:43:35 +00:00
/// </summary>
2013-03-20 12:44:12 +00:00
/// <seealso cref="Matrix4d"/>
2009-02-22 10:43:35 +00:00
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct Matrix4 : IEquatable < Matrix4 >
{
#region Fields
2009-07-17 08:27:25 +00:00
/// <summary>
2013-01-17 01:45:10 +00:00
/// Top row of the matrix.
2009-07-17 08:27:25 +00:00
/// </summary>
public Vector4 Row0 ;
2013-01-17 01:45:10 +00:00
2009-07-17 08:27:25 +00:00
/// <summary>
2013-01-17 01:45:10 +00:00
/// 2nd row of the matrix.
2009-07-17 08:27:25 +00:00
/// </summary>
public Vector4 Row1 ;
2013-01-17 01:45:10 +00:00
2009-07-17 08:27:25 +00:00
/// <summary>
2013-01-17 01:45:10 +00:00
/// 3rd row of the matrix.
2009-07-17 08:27:25 +00:00
/// </summary>
public Vector4 Row2 ;
2013-01-17 01:45:10 +00:00
2009-07-17 08:27:25 +00:00
/// <summary>
2013-01-17 01:45:10 +00:00
/// Bottom row of the matrix.
2009-07-17 08:27:25 +00:00
/// </summary>
public Vector4 Row3 ;
2009-02-22 10:43:35 +00:00
2009-07-17 08:27:25 +00:00
/// <summary>
2013-01-17 01:45:10 +00:00
/// The identity matrix.
2009-07-17 08:27:25 +00:00
/// </summary>
2013-01-19 23:06:51 +00:00
public static readonly Matrix4 Identity = new Matrix4 ( Vector4 . UnitX , Vector4 . UnitY , Vector4 . UnitZ , Vector4 . UnitW ) ;
/// <summary>
/// The zero matrix.
/// </summary>
public static readonly Matrix4 Zero = new Matrix4 ( Vector4 . Zero , Vector4 . Zero , Vector4 . Zero , Vector4 . Zero ) ;
2009-02-22 10:43:35 +00:00
#endregion
#region Constructors
2009-07-17 08:27:25 +00:00
/// <summary>
2009-04-12 16:34:35 +00:00
/// Constructs a new instance.
2009-07-17 08:27:25 +00:00
/// </summary>
2013-01-17 01:45:10 +00:00
/// <param name="row0">Top row of the matrix.</param>
/// <param name="row1">Second row of the matrix.</param>
/// <param name="row2">Third row of the matrix.</param>
/// <param name="row3">Bottom row of the matrix.</param>
2009-07-17 08:27:25 +00:00
public Matrix4 ( Vector4 row0 , Vector4 row1 , Vector4 row2 , Vector4 row3 )
{
Row0 = row0 ;
Row1 = row1 ;
Row2 = row2 ;
Row3 = row3 ;
}
2009-02-22 10:43:35 +00:00
2009-04-12 16:34:35 +00:00
/// <summary>
/// Constructs a new instance.
/// </summary>
/// <param name="m00">First item of the first row of the matrix.</param>
/// <param name="m01">Second item of the first row of the matrix.</param>
/// <param name="m02">Third item of the first row of the matrix.</param>
/// <param name="m03">Fourth item of the first row of the matrix.</param>
/// <param name="m10">First item of the second row of the matrix.</param>
/// <param name="m11">Second item of the second row of the matrix.</param>
/// <param name="m12">Third item of the second row of the matrix.</param>
/// <param name="m13">Fourth item of the second row of the matrix.</param>
/// <param name="m20">First item of the third row of the matrix.</param>
/// <param name="m21">Second item of the third row of the matrix.</param>
/// <param name="m22">Third item of the third row of the matrix.</param>
/// <param name="m23">First item of the third row of the matrix.</param>
/// <param name="m30">Fourth item of the fourth row of the matrix.</param>
/// <param name="m31">Second item of the fourth row of the matrix.</param>
/// <param name="m32">Third item of the fourth row of the matrix.</param>
/// <param name="m33">Fourth item of the fourth row of the matrix.</param>
public Matrix4 (
float m00 , float m01 , float m02 , float m03 ,
float m10 , float m11 , float m12 , float m13 ,
float m20 , float m21 , float m22 , float m23 ,
float m30 , float m31 , float m32 , float m33 )
{
Row0 = new Vector4 ( m00 , m01 , m02 , m03 ) ;
Row1 = new Vector4 ( m10 , m11 , m12 , m13 ) ;
Row2 = new Vector4 ( m20 , m21 , m22 , m23 ) ;
Row3 = new Vector4 ( m30 , m31 , m32 , m33 ) ;
}
2009-02-22 10:43:35 +00:00
#endregion
#region Public Members
#region Properties
/// <summary>
2013-01-17 01:45:10 +00:00
/// Gets the determinant of this matrix.
2009-02-22 10:43:35 +00:00
/// </summary>
public float Determinant
{
get
{
2013-01-17 01:45:10 +00:00
float m11 = Row0 . X , m12 = Row0 . Y , m13 = Row0 . Z , m14 = Row0 . W ,
m21 = Row1 . X , m22 = Row1 . Y , m23 = Row1 . Z , m24 = Row1 . W ,
m31 = Row2 . X , m32 = Row2 . Y , m33 = Row2 . Z , m34 = Row2 . W ,
m41 = Row3 . X , m42 = Row3 . Y , m43 = Row3 . Z , m44 = Row3 . W ;
2009-02-22 10:43:35 +00:00
return
2013-01-17 01:45:10 +00:00
m11 * m22 * m33 * m44 - m11 * m22 * m34 * m43 + m11 * m23 * m34 * m42 - m11 * m23 * m32 * m44
+ m11 * m24 * m32 * m43 - m11 * m24 * m33 * m42 - m12 * m23 * m34 * m41 + m12 * m23 * m31 * m44
- m12 * m24 * m31 * m43 + m12 * m24 * m33 * m41 - m12 * m21 * m33 * m44 + m12 * m21 * m34 * m43
+ m13 * m24 * m31 * m42 - m13 * m24 * m32 * m41 + m13 * m21 * m32 * m44 - m13 * m21 * m34 * m42
+ m13 * m22 * m34 * m41 - m13 * m22 * m31 * m44 - m14 * m21 * m32 * m43 + m14 * m21 * m33 * m42
- m14 * m22 * m33 * m41 + m14 * m22 * m31 * m43 - m14 * m23 * m31 * m42 + m14 * m23 * m32 * m41 ;
2009-02-22 10:43:35 +00:00
}
}
/// <summary>
2013-01-17 01:45:10 +00:00
/// Gets the first column of this matrix.
2009-02-22 10:43:35 +00:00
/// </summary>
public Vector4 Column0
{
get { return new Vector4 ( Row0 . X , Row1 . X , Row2 . X , Row3 . X ) ; }
2013-01-19 03:21:24 +00:00
set { Row0 . X = value . X ; Row1 . X = value . Y ; Row2 . X = value . Z ; Row3 . X = value . W ; }
2009-02-22 10:43:35 +00:00
}
/// <summary>
2013-01-17 01:45:10 +00:00
/// Gets the second column of this matrix.
2009-02-22 10:43:35 +00:00
/// </summary>
public Vector4 Column1
{
get { return new Vector4 ( Row0 . Y , Row1 . Y , Row2 . Y , Row3 . Y ) ; }
2013-01-19 03:21:24 +00:00
set { Row0 . Y = value . X ; Row1 . Y = value . Y ; Row2 . Y = value . Z ; Row3 . Y = value . W ; }
2009-02-22 10:43:35 +00:00
}
/// <summary>
2013-01-17 01:45:10 +00:00
/// Gets the third column of this matrix.
2009-02-22 10:43:35 +00:00
/// </summary>
public Vector4 Column2
{
get { return new Vector4 ( Row0 . Z , Row1 . Z , Row2 . Z , Row3 . Z ) ; }
2013-01-19 03:21:24 +00:00
set { Row0 . Z = value . X ; Row1 . Z = value . Y ; Row2 . Z = value . Z ; Row3 . Z = value . W ; }
2009-02-22 10:43:35 +00:00
}
/// <summary>
2013-01-17 01:45:10 +00:00
/// Gets the fourth column of this matrix.
2009-02-22 10:43:35 +00:00
/// </summary>
public Vector4 Column3
{
get { return new Vector4 ( Row0 . W , Row1 . W , Row2 . W , Row3 . W ) ; }
2013-01-19 03:21:24 +00:00
set { Row0 . W = value . X ; Row1 . W = value . Y ; Row2 . W = value . Z ; Row3 . W = value . W ; }
2009-02-22 10:43:35 +00:00
}
2009-05-29 16:44:12 +00:00
/// <summary>
/// Gets or sets the value at row 1, column 1 of this instance.
/// </summary>
public float M11 { get { return Row0 . X ; } set { Row0 . X = value ; } }
/// <summary>
/// Gets or sets the value at row 1, column 2 of this instance.
/// </summary>
public float M12 { get { return Row0 . Y ; } set { Row0 . Y = value ; } }
/// <summary>
/// Gets or sets the value at row 1, column 3 of this instance.
/// </summary>
public float M13 { get { return Row0 . Z ; } set { Row0 . Z = value ; } }
/// <summary>
/// Gets or sets the value at row 1, column 4 of this instance.
/// </summary>
public float M14 { get { return Row0 . W ; } set { Row0 . W = value ; } }
/// <summary>
/// Gets or sets the value at row 2, column 1 of this instance.
/// </summary>
public float M21 { get { return Row1 . X ; } set { Row1 . X = value ; } }
/// <summary>
/// Gets or sets the value at row 2, column 2 of this instance.
/// </summary>
public float M22 { get { return Row1 . Y ; } set { Row1 . Y = value ; } }
/// <summary>
/// Gets or sets the value at row 2, column 3 of this instance.
/// </summary>
public float M23 { get { return Row1 . Z ; } set { Row1 . Z = value ; } }
/// <summary>
/// Gets or sets the value at row 2, column 4 of this instance.
/// </summary>
public float M24 { get { return Row1 . W ; } set { Row1 . W = value ; } }
/// <summary>
/// Gets or sets the value at row 3, column 1 of this instance.
/// </summary>
public float M31 { get { return Row2 . X ; } set { Row2 . X = value ; } }
/// <summary>
/// Gets or sets the value at row 3, column 2 of this instance.
/// </summary>
public float M32 { get { return Row2 . Y ; } set { Row2 . Y = value ; } }
/// <summary>
/// Gets or sets the value at row 3, column 3 of this instance.
/// </summary>
public float M33 { get { return Row2 . Z ; } set { Row2 . Z = value ; } }
/// <summary>
/// Gets or sets the value at row 3, column 4 of this instance.
/// </summary>
public float M34 { get { return Row2 . W ; } set { Row2 . W = value ; } }
/// <summary>
/// Gets or sets the value at row 4, column 1 of this instance.
/// </summary>
public float M41 { get { return Row3 . X ; } set { Row3 . X = value ; } }
/// <summary>
2009-10-14 18:30:12 +00:00
/// Gets or sets the value at row 4, column 2 of this instance.
2009-05-29 16:44:12 +00:00
/// </summary>
public float M42 { get { return Row3 . Y ; } set { Row3 . Y = value ; } }
/// <summary>
/// Gets or sets the value at row 4, column 3 of this instance.
/// </summary>
public float M43 { get { return Row3 . Z ; } set { Row3 . Z = value ; } }
/// <summary>
/// Gets or sets the value at row 4, column 4 of this instance.
/// </summary>
public float M44 { get { return Row3 . W ; } set { Row3 . W = value ; } }
2013-02-18 18:46:26 +00:00
2013-03-20 12:44:12 +00:00
#endregion
#region Indexers
/// <summary>
/// Gets or sets the value at a specified row and column.
/// </summary>
public float this [ int rowIndex , int columnIndex ]
{
get
{
if ( rowIndex = = 0 ) return Row0 [ columnIndex ] ;
else if ( rowIndex = = 1 ) return Row1 [ columnIndex ] ;
else if ( rowIndex = = 2 ) return Row2 [ columnIndex ] ;
else if ( rowIndex = = 3 ) return Row3 [ columnIndex ] ;
throw new IndexOutOfRangeException ( "You tried to access this matrix at: (" + rowIndex + ", " + columnIndex + ")" ) ;
}
set
{
if ( rowIndex = = 0 ) Row0 [ columnIndex ] = value ;
else if ( rowIndex = = 1 ) Row1 [ columnIndex ] = value ;
else if ( rowIndex = = 2 ) Row2 [ columnIndex ] = value ;
else if ( rowIndex = = 3 ) Row3 [ columnIndex ] = value ;
throw new IndexOutOfRangeException ( "You tried to set this matrix at: (" + rowIndex + ", " + columnIndex + ")" ) ;
}
}
#endregion
#region Instance
#region public void Invert ( )
/// <summary>
/// Converts this instance into its inverse.
/// </summary>
public void Invert ( )
{
this = Matrix4 . Invert ( this ) ;
}
#endregion
#region public void Transpose ( )
/// <summary>
/// Converts this instance into its transpose.
/// </summary>
public void Transpose ( )
{
this = Matrix4 . Transpose ( this ) ;
}
#endregion
2013-02-18 18:46:26 +00:00
/// <summary>
2013-03-20 12:44:12 +00:00
/// Returns a normalised copy of this instance.
2013-02-18 18:46:26 +00:00
/// </summary>
public Matrix4 Normalized ( )
{
Matrix4 m = this ;
m . Normalize ( ) ;
return m ;
}
/// <summary>
2013-03-20 12:44:12 +00:00
/// Divides each element in the Matrix by the <see cref="Determinant"/>.
2013-02-18 18:46:26 +00:00
/// </summary>
public void Normalize ( )
{
2013-03-19 15:28:31 +00:00
var determinant = this . Determinant ;
Row0 / = determinant ;
Row1 / = determinant ;
Row2 / = determinant ;
Row3 / = determinant ;
2013-02-18 18:46:26 +00:00
}
2013-02-23 18:26:34 +00:00
/// <summary>
/// Returns an inverted copy of this instance.
/// </summary>
public Matrix4 Inverted ( )
{
Matrix4 m = this ;
if ( m . Determinant ! = 0 )
m . Invert ( ) ;
return m ;
}
2013-04-11 21:23:43 +00:00
/// <summary>
/// Returns a copy of this Matrix4 without translation.
/// </summary>
public Matrix4 ClearTranslation ( )
{
Matrix4 m = this ;
m . Row3 . Xyz = Vector3 . Zero ;
return m ;
}
/// <summary>
/// Returns a copy of this Matrix4 without scale.
/// </summary>
public Matrix4 ClearScale ( )
{
Matrix4 m = this ;
m . Row0 . Xyz = m . Row0 . Xyz . Normalized ( ) ;
m . Row1 . Xyz = m . Row1 . Xyz . Normalized ( ) ;
m . Row2 . Xyz = m . Row2 . Xyz . Normalized ( ) ;
return m ;
}
/// <summary>
/// Returns a copy of this Matrix4 without rotation.
/// </summary>
public Matrix4 ClearRotation ( )
{
Matrix4 m = this ;
m . Row0 . Xyz = new Vector3 ( m . Row0 . Xyz . Length , 0 , 0 ) ;
m . Row1 . Xyz = new Vector3 ( 0 , m . Row1 . Xyz . Length , 0 ) ;
m . Row2 . Xyz = new Vector3 ( 0 , 0 , m . Row2 . Xyz . Length ) ;
return m ;
}
/// <summary>
/// Returns a copy of this Matrix4 without projection.
/// </summary>
public Matrix4 ClearProjection ( )
{
Matrix4 m = this ;
m . Column3 = Vector4 . Zero ;
return m ;
}
2013-02-18 18:46:26 +00:00
/// <summary>
2013-03-19 15:28:31 +00:00
/// Returns the translation component of this instance.
2013-02-18 18:46:26 +00:00
/// </summary>
2013-03-19 15:28:31 +00:00
public Vector3 ExtractTranslation ( ) { return Row3 . Xyz ; }
2013-02-18 18:46:26 +00:00
/// <summary>
2013-03-19 15:28:31 +00:00
/// Returns the scale component of this instance.
2013-02-18 18:46:26 +00:00
/// </summary>
2013-04-11 21:23:43 +00:00
public Vector3 ExtractScale ( ) { return new Vector3 ( Row0 . Xyz . Length , Row1 . Xyz . Length , Row2 . Xyz . Length ) ; }
2013-02-18 18:46:26 +00:00
/// <summary>
2013-03-19 15:28:31 +00:00
/// Returns the rotation component of this instance. Quite slow.
2013-02-18 18:46:26 +00:00
/// </summary>
2013-03-20 12:44:12 +00:00
/// <param name="row_normalise">Whether the method should row-normalise (i.e. remove scale from) the Matrix. Pass false if you know it's already normalised.</param>
2013-03-19 15:28:31 +00:00
public Quaternion ExtractRotation ( bool row_normalise = true )
2013-02-18 18:46:26 +00:00
{
2013-03-19 15:28:31 +00:00
var row0 = Row0 . Xyz ;
var row1 = Row1 . Xyz ;
var row2 = Row2 . Xyz ;
if ( row_normalise )
{
2013-03-20 12:44:12 +00:00
row0 = row0 . Normalized ( ) ;
row1 = row1 . Normalized ( ) ;
row2 = row2 . Normalized ( ) ;
2013-03-19 15:28:31 +00:00
}
// code below adapted from Blender
Quaternion q = new Quaternion ( ) ;
double trace = 0.25 * ( row0 [ 0 ] + row1 [ 1 ] + row2 [ 2 ] + 1.0 ) ;
if ( trace > 0 )
{
double sq = Math . Sqrt ( trace ) ;
q . W = ( float ) sq ;
sq = 1.0 / ( 4.0 * sq ) ;
q . X = ( float ) ( ( row1 [ 2 ] - row2 [ 1 ] ) * sq ) ;
q . Y = ( float ) ( ( row2 [ 0 ] - row0 [ 2 ] ) * sq ) ;
q . Z = ( float ) ( ( row0 [ 1 ] - row1 [ 0 ] ) * sq ) ;
}
else if ( row0 [ 0 ] > row1 [ 1 ] & & row0 [ 0 ] > row2 [ 2 ] )
2013-02-18 18:46:26 +00:00
{
2013-03-19 15:28:31 +00:00
double sq = 2.0 * Math . Sqrt ( 1.0 + row0 [ 0 ] - row1 [ 1 ] - row2 [ 2 ] ) ;
q . X = ( float ) ( 0.25 * sq ) ;
sq = 1.0 / sq ;
q . W = ( float ) ( ( row2 [ 1 ] - row1 [ 2 ] ) * sq ) ;
q . Y = ( float ) ( ( row1 [ 0 ] + row0 [ 1 ] ) * sq ) ;
q . Z = ( float ) ( ( row2 [ 0 ] + row0 [ 2 ] ) * sq ) ;
}
else if ( row1 [ 1 ] > row2 [ 2 ] )
{
double sq = 2.0 * Math . Sqrt ( 1.0 + row1 [ 1 ] - row0 [ 0 ] - row2 [ 2 ] ) ;
q . Y = ( float ) ( 0.25 * sq ) ;
sq = 1.0 / sq ;
q . W = ( float ) ( ( row2 [ 0 ] - row0 [ 2 ] ) * sq ) ;
q . X = ( float ) ( ( row1 [ 0 ] + row0 [ 1 ] ) * sq ) ;
q . Z = ( float ) ( ( row2 [ 1 ] + row1 [ 2 ] ) * sq ) ;
2013-02-18 18:46:26 +00:00
}
2013-03-19 15:28:31 +00:00
else
{
double sq = 2.0 * Math . Sqrt ( 1.0 + row2 [ 2 ] - row0 [ 0 ] - row1 [ 1 ] ) ;
q . Z = ( float ) ( 0.25 * sq ) ;
sq = 1.0 / sq ;
q . W = ( float ) ( ( row1 [ 0 ] - row0 [ 1 ] ) * sq ) ;
q . X = ( float ) ( ( row2 [ 0 ] + row0 [ 2 ] ) * sq ) ;
q . Y = ( float ) ( ( row2 [ 1 ] + row1 [ 2 ] ) * sq ) ;
}
q . Normalize ( ) ;
return q ;
2013-02-18 18:46:26 +00:00
}
2009-05-29 16:44:12 +00:00
2013-04-11 21:23:43 +00:00
/// <summary>
/// Returns the projection component of this instance.
/// </summary>
public Vector4 ExtractProjection ( )
{
return Column3 ;
}
2009-02-22 10:43:35 +00:00
#endregion
#region Static
2009-07-17 08:27:25 +00:00
#region CreateFromAxisAngle
2009-06-26 21:45:26 +00:00
/// <summary>
/// Build a rotation matrix from the specified axis/angle rotation.
/// </summary>
/// <param name="axis">The axis to rotate about.</param>
/// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param>
/// <param name="result">A matrix instance.</param>
public static void CreateFromAxisAngle ( Vector3 axis , float angle , out Matrix4 result )
{
2013-01-17 01:45:10 +00:00
// normalize and create a local copy of the vector.
axis . Normalize ( ) ;
float axisX = axis . X , axisY = axis . Y , axisZ = axis . Z ;
// calculate angles
2009-06-26 21:45:26 +00:00
float cos = ( float ) System . Math . Cos ( - angle ) ;
float sin = ( float ) System . Math . Sin ( - angle ) ;
float t = 1.0f - cos ;
2013-01-17 01:45:10 +00:00
// do the conversion math once
float tXX = t * axisX * axisX ,
tXY = t * axisX * axisY ,
tXZ = t * axisX * axisZ ,
tYY = t * axisY * axisY ,
tYZ = t * axisY * axisZ ,
tZZ = t * axisZ * axisZ ;
float sinX = sin * axisX ,
sinY = sin * axisY ,
sinZ = sin * axisZ ;
result . Row0 . X = tXX + cos ;
result . Row0 . Y = tXY - sinZ ;
result . Row0 . Z = tXZ + sinY ;
result . Row0 . W = 0 ;
result . Row1 . X = tXY + sinZ ;
result . Row1 . Y = tYY + cos ;
result . Row1 . Z = tYZ - sinX ;
result . Row1 . W = 0 ;
result . Row2 . X = tXZ - sinY ;
result . Row2 . Y = tYZ + sinX ;
result . Row2 . Z = tZZ + cos ;
result . Row2 . W = 0 ;
result . Row3 = Vector4 . UnitW ;
2009-06-26 21:45:26 +00:00
}
2009-07-17 08:27:25 +00:00
2009-06-26 21:45:26 +00:00
/// <summary>
/// Build a rotation matrix from the specified axis/angle rotation.
/// </summary>
/// <param name="axis">The axis to rotate about.</param>
/// <param name="angle">Angle in radians to rotate counter-clockwise (looking in the direction of the given axis).</param>
/// <returns>A matrix instance.</returns>
public static Matrix4 CreateFromAxisAngle ( Vector3 axis , float angle )
{
Matrix4 result ;
2009-07-17 08:27:25 +00:00
CreateFromAxisAngle ( axis , angle , out result ) ;
return result ;
2009-06-26 21:45:26 +00:00
}
2009-07-17 08:27:25 +00:00
#endregion
2009-02-22 10:43:35 +00:00
2013-01-17 01:45:10 +00:00
#region CreateFromQuaternion
/// <summary>
/// Builds a rotation matrix from a quaternion.
/// </summary>
/// <param name="q">The quaternion to rotate by.</param>
/// <param name="result">A matrix instance.</param>
public static void CreateFromQuaternion ( ref Quaternion q , out Matrix4 result )
{
Vector3 axis ;
float angle ;
q . ToAxisAngle ( out axis , out angle ) ;
CreateFromAxisAngle ( axis , angle , out result ) ;
}
/// <summary>
/// Builds a rotation matrix from a quaternion.
/// </summary>
/// <param name="q">The quaternion to rotate by.</param>
/// <returns>A matrix instance.</returns>
public static Matrix4 CreateFromQuaternion ( Quaternion q )
{
Matrix4 result ;
CreateFromQuaternion ( ref q , out result ) ;
return result ;
}
#endregion
2009-09-04 13:02:23 +00:00
#region CreateRotation [ XYZ ]
/// <summary>
/// Builds a rotation matrix for a rotation around the x-axis.
/// </summary>
/// <param name="angle">The counter-clockwise angle in radians.</param>
/// <param name="result">The resulting Matrix4 instance.</param>
public static void CreateRotationX ( float angle , out Matrix4 result )
{
float cos = ( float ) System . Math . Cos ( angle ) ;
float sin = ( float ) System . Math . Sin ( angle ) ;
2013-01-17 01:45:10 +00:00
result = Identity ;
result . Row1 . Y = cos ;
result . Row1 . Z = sin ;
result . Row2 . Y = - sin ;
result . Row2 . Z = cos ;
2009-09-04 13:02:23 +00:00
}
/// <summary>
/// Builds a rotation matrix for a rotation around the x-axis.
/// </summary>
/// <param name="angle">The counter-clockwise angle in radians.</param>
/// <returns>The resulting Matrix4 instance.</returns>
public static Matrix4 CreateRotationX ( float angle )
{
Matrix4 result ;
CreateRotationX ( angle , out result ) ;
return result ;
}
/// <summary>
/// Builds a rotation matrix for a rotation around the y-axis.
/// </summary>
/// <param name="angle">The counter-clockwise angle in radians.</param>
/// <param name="result">The resulting Matrix4 instance.</param>
public static void CreateRotationY ( float angle , out Matrix4 result )
{
float cos = ( float ) System . Math . Cos ( angle ) ;
float sin = ( float ) System . Math . Sin ( angle ) ;
2013-01-17 01:45:10 +00:00
result = Identity ;
result . Row0 . X = cos ;
result . Row0 . Z = - sin ;
result . Row2 . X = sin ;
result . Row2 . Z = cos ;
2009-09-04 13:02:23 +00:00
}
/// <summary>
/// Builds a rotation matrix for a rotation around the y-axis.
/// </summary>
/// <param name="angle">The counter-clockwise angle in radians.</param>
/// <returns>The resulting Matrix4 instance.</returns>
public static Matrix4 CreateRotationY ( float angle )
{
Matrix4 result ;
CreateRotationY ( angle , out result ) ;
return result ;
}
/// <summary>
/// Builds a rotation matrix for a rotation around the z-axis.
/// </summary>
/// <param name="angle">The counter-clockwise angle in radians.</param>
/// <param name="result">The resulting Matrix4 instance.</param>
public static void CreateRotationZ ( float angle , out Matrix4 result )
{
float cos = ( float ) System . Math . Cos ( angle ) ;
float sin = ( float ) System . Math . Sin ( angle ) ;
2013-01-17 01:45:10 +00:00
result = Identity ;
result . Row0 . X = cos ;
result . Row0 . Y = sin ;
result . Row1 . X = - sin ;
result . Row1 . Y = cos ;
2009-09-04 13:02:23 +00:00
}
/// <summary>
/// Builds a rotation matrix for a rotation around the z-axis.
/// </summary>
/// <param name="angle">The counter-clockwise angle in radians.</param>
/// <returns>The resulting Matrix4 instance.</returns>
public static Matrix4 CreateRotationZ ( float angle )
{
Matrix4 result ;
CreateRotationZ ( angle , out result ) ;
return result ;
}
#endregion
2009-05-29 16:44:12 +00:00
#region CreateTranslation
2009-02-22 10:43:35 +00:00
/// <summary>
2009-05-29 16:44:12 +00:00
/// Creates a translation matrix.
2009-02-22 10:43:35 +00:00
/// </summary>
2009-05-29 16:44:12 +00:00
/// <param name="x">X translation.</param>
/// <param name="y">Y translation.</param>
/// <param name="z">Z translation.</param>
/// <param name="result">The resulting Matrix4 instance.</param>
public static void CreateTranslation ( float x , float y , float z , out Matrix4 result )
2009-02-22 10:43:35 +00:00
{
2009-05-29 16:44:12 +00:00
result = Identity ;
2013-01-17 01:45:10 +00:00
result . Row3 . X = x ;
result . Row3 . Y = y ;
result . Row3 . Z = z ;
2009-02-22 10:43:35 +00:00
}
/// <summary>
2009-05-29 16:44:12 +00:00
/// Creates a translation matrix.
2009-02-22 10:43:35 +00:00
/// </summary>
2009-05-29 16:44:12 +00:00
/// <param name="vector">The translation vector.</param>
/// <param name="result">The resulting Matrix4 instance.</param>
public static void CreateTranslation ( ref Vector3 vector , out Matrix4 result )
2009-02-22 10:43:35 +00:00
{
2009-05-29 16:44:12 +00:00
result = Identity ;
2013-01-17 01:45:10 +00:00
result . Row3 . X = vector . X ;
result . Row3 . Y = vector . Y ;
result . Row3 . Z = vector . Z ;
2009-02-22 10:43:35 +00:00
}
/// <summary>
2009-05-29 16:44:12 +00:00
/// Creates a translation matrix.
2009-02-22 10:43:35 +00:00
/// </summary>
2009-05-29 16:44:12 +00:00
/// <param name="x">X translation.</param>
/// <param name="y">Y translation.</param>
/// <param name="z">Z translation.</param>
/// <returns>The resulting Matrix4 instance.</returns>
public static Matrix4 CreateTranslation ( float x , float y , float z )
2009-02-22 10:43:35 +00:00
{
Matrix4 result ;
2009-05-29 16:44:12 +00:00
CreateTranslation ( x , y , z , out result ) ;
return result ;
}
/// <summary>
/// Creates a translation matrix.
/// </summary>
/// <param name="vector">The translation vector.</param>
/// <returns>The resulting Matrix4 instance.</returns>
public static Matrix4 CreateTranslation ( Vector3 vector )
{
Matrix4 result ;
CreateTranslation ( vector . X , vector . Y , vector . Z , out result ) ;
2009-02-22 10:43:35 +00:00
return result ;
}
#endregion
2013-01-17 01:45:10 +00:00
#region CreateScale
/// <summary>
/// Creates a scale matrix.
/// </summary>
/// <param name="scale">Single scale factor for the x, y, and z axes.</param>
/// <returns>A scale matrix.</returns>
public static Matrix4 CreateScale ( float scale )
{
Matrix4 result ;
CreateScale ( scale , out result ) ;
return result ;
}
/// <summary>
/// Creates a scale matrix.
/// </summary>
/// <param name="scale">Scale factors for the x, y, and z axes.</param>
/// <returns>A scale matrix.</returns>
public static Matrix4 CreateScale ( Vector3 scale )
{
Matrix4 result ;
CreateScale ( ref scale , out result ) ;
return result ;
}
/// <summary>
/// Creates a scale matrix.
/// </summary>
/// <param name="x">Scale factor for the x axis.</param>
/// <param name="y">Scale factor for the y axis.</param>
/// <param name="z">Scale factor for the z axis.</param>
/// <returns>A scale matrix.</returns>
public static Matrix4 CreateScale ( float x , float y , float z )
{
Matrix4 result ;
CreateScale ( x , y , z , out result ) ;
return result ;
}
/// <summary>
/// Creates a scale matrix.
/// </summary>
/// <param name="scale">Single scale factor for the x, y, and z axes.</param>
/// <param name="result">A scale matrix.</param>
public static void CreateScale ( float scale , out Matrix4 result )
{
result = Identity ;
result . Row0 . X = scale ;
result . Row1 . Y = scale ;
result . Row2 . Z = scale ;
}
/// <summary>
/// Creates a scale matrix.
/// </summary>
/// <param name="scale">Scale factors for the x, y, and z axes.</param>
/// <param name="result">A scale matrix.</param>
public static void CreateScale ( ref Vector3 scale , out Matrix4 result )
{
result = Identity ;
result . Row0 . X = scale . X ;
result . Row1 . Y = scale . Y ;
result . Row2 . Z = scale . Z ;
}
/// <summary>
/// Creates a scale matrix.
/// </summary>
/// <param name="x">Scale factor for the x axis.</param>
/// <param name="y">Scale factor for the y axis.</param>
/// <param name="z">Scale factor for the z axis.</param>
2013-01-20 21:38:25 +00:00
/// <param name="result">A scale matrix.</param>
2013-01-17 01:45:10 +00:00
public static void CreateScale ( float x , float y , float z , out Matrix4 result )
{
result = Identity ;
result . Row0 . X = x ;
result . Row1 . Y = y ;
result . Row2 . Z = z ;
}
#endregion
2009-05-29 16:44:12 +00:00
#region CreateOrthographic
/// <summary>
/// Creates an orthographic projection matrix.
/// </summary>
/// <param name="width">The width of the projection volume.</param>
/// <param name="height">The height of the projection volume.</param>
/// <param name="zNear">The near edge of the projection volume.</param>
/// <param name="zFar">The far edge of the projection volume.</param>
/// <param name="result">The resulting Matrix4 instance.</param>
public static void CreateOrthographic ( float width , float height , float zNear , float zFar , out Matrix4 result )
{
CreateOrthographicOffCenter ( - width / 2 , width / 2 , - height / 2 , height / 2 , zNear , zFar , out result ) ;
}
/// <summary>
/// Creates an orthographic projection matrix.
/// </summary>
/// <param name="width">The width of the projection volume.</param>
/// <param name="height">The height of the projection volume.</param>
/// <param name="zNear">The near edge of the projection volume.</param>
/// <param name="zFar">The far edge of the projection volume.</param>
/// <rereturns>The resulting Matrix4 instance.</rereturns>
public static Matrix4 CreateOrthographic ( float width , float height , float zNear , float zFar )
{
Matrix4 result ;
CreateOrthographicOffCenter ( - width / 2 , width / 2 , - height / 2 , height / 2 , zNear , zFar , out result ) ;
return result ;
}
#endregion
#region CreateOrthographicOffCenter
/// <summary>
/// Creates an orthographic projection matrix.
/// </summary>
/// <param name="left">The left edge of the projection volume.</param>
/// <param name="right">The right edge of the projection volume.</param>
/// <param name="bottom">The bottom edge of the projection volume.</param>
/// <param name="top">The top edge of the projection volume.</param>
/// <param name="zNear">The near edge of the projection volume.</param>
/// <param name="zFar">The far edge of the projection volume.</param>
/// <param name="result">The resulting Matrix4 instance.</param>
public static void CreateOrthographicOffCenter ( float left , float right , float bottom , float top , float zNear , float zFar , out Matrix4 result )
{
2013-01-17 01:45:10 +00:00
result = Identity ;
2009-05-29 16:44:12 +00:00
2013-01-17 01:45:10 +00:00
float invRL = 1.0f / ( right - left ) ;
float invTB = 1.0f / ( top - bottom ) ;
float invFN = 1.0f / ( zFar - zNear ) ;
2009-05-29 16:44:12 +00:00
2013-01-17 01:45:10 +00:00
result . Row0 . X = 2 * invRL ;
result . Row1 . Y = 2 * invTB ;
result . Row2 . Z = - 2 * invFN ;
2009-05-29 16:44:12 +00:00
2013-01-17 01:45:10 +00:00
result . Row3 . X = - ( right + left ) * invRL ;
result . Row3 . Y = - ( top + bottom ) * invTB ;
result . Row3 . Z = - ( zFar + zNear ) * invFN ;
2009-05-29 16:44:12 +00:00
}
/// <summary>
/// Creates an orthographic projection matrix.
/// </summary>
/// <param name="left">The left edge of the projection volume.</param>
/// <param name="right">The right edge of the projection volume.</param>
/// <param name="bottom">The bottom edge of the projection volume.</param>
/// <param name="top">The top edge of the projection volume.</param>
/// <param name="zNear">The near edge of the projection volume.</param>
/// <param name="zFar">The far edge of the projection volume.</param>
/// <returns>The resulting Matrix4 instance.</returns>
public static Matrix4 CreateOrthographicOffCenter ( float left , float right , float bottom , float top , float zNear , float zFar )
{
Matrix4 result ;
CreateOrthographicOffCenter ( left , right , bottom , top , zNear , zFar , out result ) ;
return result ;
}
#endregion
2009-07-17 08:27:25 +00:00
#region CreatePerspectiveFieldOfView
2009-06-25 22:47:01 +00:00
/// <summary>
/// Creates a perspective projection matrix.
/// </summary>
/// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
/// <param name="aspect">Aspect ratio of the view (width / height)</param>
/// <param name="zNear">Distance to the near clip plane</param>
/// <param name="zFar">Distance to the far clip plane</param>
/// <param name="result">A projection matrix that transforms camera space to raster space</param>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown under the following conditions:
/// <list type="bullet">
/// <item>fovy is zero, less than zero or larger than Math.PI</item>
/// <item>aspect is negative or zero</item>
/// <item>zNear is negative or zero</item>
/// <item>zFar is negative or zero</item>
/// <item>zNear is larger than zFar</item>
/// </list>
/// </exception>
public static void CreatePerspectiveFieldOfView ( float fovy , float aspect , float zNear , float zFar , out Matrix4 result )
{
2009-07-17 08:27:25 +00:00
if ( fovy < = 0 | | fovy > Math . PI )
throw new ArgumentOutOfRangeException ( "fovy" ) ;
if ( aspect < = 0 )
throw new ArgumentOutOfRangeException ( "aspect" ) ;
if ( zNear < = 0 )
throw new ArgumentOutOfRangeException ( "zNear" ) ;
if ( zFar < = 0 )
throw new ArgumentOutOfRangeException ( "zFar" ) ;
2009-06-25 22:47:01 +00:00
float yMax = zNear * ( float ) System . Math . Tan ( 0.5f * fovy ) ;
float yMin = - yMax ;
float xMin = yMin * aspect ;
float xMax = yMax * aspect ;
CreatePerspectiveOffCenter ( xMin , xMax , yMin , yMax , zNear , zFar , out result ) ;
}
2009-07-17 08:27:25 +00:00
2009-06-25 22:47:01 +00:00
/// <summary>
/// Creates a perspective projection matrix.
/// </summary>
/// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
/// <param name="aspect">Aspect ratio of the view (width / height)</param>
/// <param name="zNear">Distance to the near clip plane</param>
/// <param name="zFar">Distance to the far clip plane</param>
/// <returns>A projection matrix that transforms camera space to raster space</returns>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown under the following conditions:
/// <list type="bullet">
/// <item>fovy is zero, less than zero or larger than Math.PI</item>
/// <item>aspect is negative or zero</item>
/// <item>zNear is negative or zero</item>
/// <item>zFar is negative or zero</item>
/// <item>zNear is larger than zFar</item>
/// </list>
/// </exception>
public static Matrix4 CreatePerspectiveFieldOfView ( float fovy , float aspect , float zNear , float zFar )
{
2009-07-17 08:27:25 +00:00
Matrix4 result ;
CreatePerspectiveFieldOfView ( fovy , aspect , zNear , zFar , out result ) ;
return result ;
2009-06-25 22:47:01 +00:00
}
2009-07-17 08:27:25 +00:00
#endregion
#region CreatePerspectiveOffCenter
2009-06-25 22:47:01 +00:00
/// <summary>
/// Creates an perspective projection matrix.
/// </summary>
/// <param name="left">Left edge of the view frustum</param>
/// <param name="right">Right edge of the view frustum</param>
/// <param name="bottom">Bottom edge of the view frustum</param>
/// <param name="top">Top edge of the view frustum</param>
/// <param name="zNear">Distance to the near clip plane</param>
/// <param name="zFar">Distance to the far clip plane</param>
/// <param name="result">A projection matrix that transforms camera space to raster space</param>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown under the following conditions:
/// <list type="bullet">
/// <item>zNear is negative or zero</item>
/// <item>zFar is negative or zero</item>
/// <item>zNear is larger than zFar</item>
/// </list>
/// </exception>
public static void CreatePerspectiveOffCenter ( float left , float right , float bottom , float top , float zNear , float zFar , out Matrix4 result )
{
2009-07-17 08:27:25 +00:00
if ( zNear < = 0 )
throw new ArgumentOutOfRangeException ( "zNear" ) ;
if ( zFar < = 0 )
throw new ArgumentOutOfRangeException ( "zFar" ) ;
if ( zNear > = zFar )
throw new ArgumentOutOfRangeException ( "zNear" ) ;
float x = ( 2.0f * zNear ) / ( right - left ) ;
float y = ( 2.0f * zNear ) / ( top - bottom ) ;
float a = ( right + left ) / ( right - left ) ;
float b = ( top + bottom ) / ( top - bottom ) ;
float c = - ( zFar + zNear ) / ( zFar - zNear ) ;
float d = - ( 2.0f * zFar * zNear ) / ( zFar - zNear ) ;
2013-01-17 01:45:10 +00:00
result . Row0 . X = x ;
2013-01-18 23:13:36 +00:00
result . Row0 . Y = 0 ;
result . Row0 . Z = 0 ;
result . Row0 . W = 0 ;
result . Row1 . X = 0 ;
2013-01-17 01:45:10 +00:00
result . Row1 . Y = y ;
2013-01-18 23:13:36 +00:00
result . Row1 . Z = 0 ;
result . Row1 . W = 0 ;
2013-01-17 01:45:10 +00:00
result . Row2 . X = a ;
result . Row2 . Y = b ;
result . Row2 . Z = c ;
result . Row2 . W = - 1 ;
2013-01-18 23:13:36 +00:00
result . Row3 . X = 0 ;
result . Row3 . Y = 0 ;
2013-01-17 01:45:10 +00:00
result . Row3 . Z = d ;
result . Row3 . W = 0 ;
2009-06-25 22:47:01 +00:00
}
2009-07-17 08:27:25 +00:00
2009-06-25 22:47:01 +00:00
/// <summary>
/// Creates an perspective projection matrix.
/// </summary>
/// <param name="left">Left edge of the view frustum</param>
/// <param name="right">Right edge of the view frustum</param>
/// <param name="bottom">Bottom edge of the view frustum</param>
/// <param name="top">Top edge of the view frustum</param>
/// <param name="zNear">Distance to the near clip plane</param>
/// <param name="zFar">Distance to the far clip plane</param>
/// <returns>A projection matrix that transforms camera space to raster space</returns>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown under the following conditions:
/// <list type="bullet">
/// <item>zNear is negative or zero</item>
/// <item>zFar is negative or zero</item>
/// <item>zNear is larger than zFar</item>
/// </list>
/// </exception>
public static Matrix4 CreatePerspectiveOffCenter ( float left , float right , float bottom , float top , float zNear , float zFar )
{
2009-07-17 08:27:25 +00:00
Matrix4 result ;
CreatePerspectiveOffCenter ( left , right , bottom , top , zNear , zFar , out result ) ;
return result ;
2009-06-25 22:47:01 +00:00
}
2013-01-03 16:19:06 +00:00
2009-07-17 08:27:25 +00:00
#endregion
2009-05-29 16:44:12 +00:00
#region Obsolete Functions
2009-02-22 10:43:35 +00:00
#region Translation Functions
/// <summary>
2009-05-29 16:44:12 +00:00
/// Builds a translation matrix.
2009-02-22 10:43:35 +00:00
/// </summary>
2009-05-29 16:44:12 +00:00
/// <param name="trans">The translation vector.</param>
/// <returns>A new Matrix4 instance.</returns>
[Obsolete("Use CreateTranslation instead.")]
2009-02-22 10:43:35 +00:00
public static Matrix4 Translation ( Vector3 trans )
{
2013-01-17 01:45:10 +00:00
return CreateTranslation ( trans ) ;
2009-02-22 10:43:35 +00:00
}
/// <summary>
/// Build a translation matrix with the given translation
/// </summary>
/// <param name="x">X translation</param>
/// <param name="y">Y translation</param>
/// <param name="z">Z translation</param>
/// <returns>A Translation matrix</returns>
2009-05-29 16:44:12 +00:00
[Obsolete("Use CreateTranslation instead.")]
2009-02-22 10:43:35 +00:00
public static Matrix4 Translation ( float x , float y , float z )
{
2013-01-17 01:45:10 +00:00
return CreateTranslation ( x , y , z ) ;
2009-05-29 16:44:12 +00:00
}
#endregion
2009-02-22 10:43:35 +00:00
#region Rotation Functions
/// <summary>
/// Build a rotation matrix that rotates about the x-axis
/// </summary>
/// <param name="angle">angle in radians to rotate counter-clockwise around the x-axis</param>
/// <returns>A rotation matrix</returns>
2009-06-26 21:45:26 +00:00
[Obsolete("Use CreateRotationX instead.")]
2009-02-22 10:43:35 +00:00
public static Matrix4 RotateX ( float angle )
{
2013-01-17 01:45:10 +00:00
return CreateRotationX ( angle ) ;
2009-02-22 10:43:35 +00:00
}
/// <summary>
/// Build a rotation matrix that rotates about the y-axis
/// </summary>
/// <param name="angle">angle in radians to rotate counter-clockwise around the y-axis</param>
/// <returns>A rotation matrix</returns>
2009-06-26 21:45:26 +00:00
[Obsolete("Use CreateRotationY instead.")]
2009-02-22 10:43:35 +00:00
public static Matrix4 RotateY ( float angle )
{
2013-01-17 01:45:10 +00:00
return CreateRotationY ( angle ) ;
2009-02-22 10:43:35 +00:00
}
/// <summary>
/// Build a rotation matrix that rotates about the z-axis
/// </summary>
/// <param name="angle">angle in radians to rotate counter-clockwise around the z-axis</param>
/// <returns>A rotation matrix</returns>
2009-06-26 21:45:26 +00:00
[Obsolete("Use CreateRotationZ instead.")]
2009-02-22 10:43:35 +00:00
public static Matrix4 RotateZ ( float angle )
{
2013-01-17 01:45:10 +00:00
return CreateRotationZ ( angle ) ;
2009-02-22 10:43:35 +00:00
}
/// <summary>
/// Build a rotation matrix to rotate about the given axis
/// </summary>
/// <param name="axis">the axis to rotate about</param>
/// <param name="angle">angle in radians to rotate counter-clockwise (looking in the direction of the given axis)</param>
/// <returns>A rotation matrix</returns>
2009-06-26 21:45:26 +00:00
[Obsolete("Use CreateFromAxisAngle instead.")]
2009-02-22 10:43:35 +00:00
public static Matrix4 Rotate ( Vector3 axis , float angle )
{
2013-01-17 01:45:10 +00:00
return CreateFromAxisAngle ( axis , angle ) ;
2009-02-22 10:43:35 +00:00
}
/// <summary>
/// Build a rotation matrix from a quaternion
/// </summary>
/// <param name="q">the quaternion</param>
/// <returns>A rotation matrix</returns>
2013-01-17 01:45:10 +00:00
[Obsolete("Use CreateRotation instead.")]
2009-02-22 10:43:35 +00:00
public static Matrix4 Rotate ( Quaternion q )
{
2013-01-17 01:45:10 +00:00
return CreateFromQuaternion ( q ) ;
2009-02-22 10:43:35 +00:00
}
#endregion
2013-01-17 01:45:10 +00:00
#region Scale Functions
2009-02-22 10:43:35 +00:00
/// <summary>
2013-01-17 01:45:10 +00:00
/// Build a scaling matrix
2009-02-22 10:43:35 +00:00
/// </summary>
2013-01-17 01:45:10 +00:00
/// <param name="scale">Single scale factor for x,y and z axes</param>
/// <returns>A scaling matrix</returns>
[Obsolete("Use CreateScale instead.")]
public static Matrix4 Scale ( float scale )
2009-02-22 10:43:35 +00:00
{
2013-01-17 01:45:10 +00:00
return Scale ( scale , scale , scale ) ;
}
2009-02-22 10:43:35 +00:00
2013-01-17 01:45:10 +00:00
/// <summary>
/// Build a scaling matrix
/// </summary>
/// <param name="scale">Scale factors for x,y and z axes</param>
/// <returns>A scaling matrix</returns>
[Obsolete("Use CreateScale instead.")]
public static Matrix4 Scale ( Vector3 scale )
{
return Scale ( scale . X , scale . Y , scale . Z ) ;
2009-02-22 10:43:35 +00:00
}
2009-08-14 12:37:18 +00:00
/// <summary>
2013-01-17 01:45:10 +00:00
/// Build a scaling matrix
2009-08-14 12:37:18 +00:00
/// </summary>
2013-01-17 01:45:10 +00:00
/// <param name="x">Scale factor for x-axis</param>
/// <param name="y">Scale factor for y-axis</param>
/// <param name="z">Scale factor for z-axis</param>
/// <returns>A scaling matrix</returns>
[Obsolete("Use CreateScale instead.")]
public static Matrix4 Scale ( float x , float y , float z )
2009-08-14 12:37:18 +00:00
{
2013-01-17 01:45:10 +00:00
Matrix4 result ;
result . Row0 = Vector4 . UnitX * x ;
result . Row1 = Vector4 . UnitY * y ;
result . Row2 = Vector4 . UnitZ * z ;
result . Row3 = Vector4 . UnitW ;
return result ;
2009-08-14 12:37:18 +00:00
}
2013-01-17 01:45:10 +00:00
#endregion
#region Camera Helper Functions
2009-02-22 10:43:35 +00:00
/// <summary>
/// Build a projection matrix
/// </summary>
/// <param name="left">Left edge of the view frustum</param>
/// <param name="right">Right edge of the view frustum</param>
/// <param name="bottom">Bottom edge of the view frustum</param>
/// <param name="top">Top edge of the view frustum</param>
/// <param name="near">Distance to the near clip plane</param>
/// <param name="far">Distance to the far clip plane</param>
/// <returns>A projection matrix that transforms camera space to raster space</returns>
2009-06-25 22:47:01 +00:00
[Obsolete("Use CreatePerspectiveOffCenter instead.")]
2009-02-22 10:43:35 +00:00
public static Matrix4 Frustum ( float left , float right , float bottom , float top , float near , float far )
{
float invRL = 1.0f / ( right - left ) ;
float invTB = 1.0f / ( top - bottom ) ;
float invFN = 1.0f / ( far - near ) ;
return new Matrix4 ( new Vector4 ( 2.0f * near * invRL , 0.0f , 0.0f , 0.0f ) ,
new Vector4 ( 0.0f , 2.0f * near * invTB , 0.0f , 0.0f ) ,
new Vector4 ( ( right + left ) * invRL , ( top + bottom ) * invTB , - ( far + near ) * invFN , - 1.0f ) ,
new Vector4 ( 0.0f , 0.0f , - 2.0f * far * near * invFN , 0.0f ) ) ;
}
/// <summary>
/// Build a projection matrix
/// </summary>
/// <param name="fovy">Angle of the field of view in the y direction (in radians)</param>
/// <param name="aspect">Aspect ratio of the view (width / height)</param>
/// <param name="near">Distance to the near clip plane</param>
/// <param name="far">Distance to the far clip plane</param>
/// <returns>A projection matrix that transforms camera space to raster space</returns>
2009-06-25 22:47:01 +00:00
[Obsolete("Use CreatePerspectiveFieldOfView instead.")]
2009-02-22 10:43:35 +00:00
public static Matrix4 Perspective ( float fovy , float aspect , float near , float far )
{
float yMax = near * ( float ) System . Math . Tan ( 0.5f * fovy ) ;
float yMin = - yMax ;
float xMin = yMin * aspect ;
float xMax = yMax * aspect ;
return Frustum ( xMin , xMax , yMin , yMax , near , far ) ;
}
#endregion
2013-01-17 01:45:10 +00:00
#endregion
#region Camera Helper Functions
/// <summary>
/// Build a world space to camera space matrix
/// </summary>
/// <param name="eye">Eye (camera) position in world space</param>
/// <param name="target">Target position in world space</param>
/// <param name="up">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
/// <returns>A Matrix4 that transforms world space to camera space</returns>
public static Matrix4 LookAt ( Vector3 eye , Vector3 target , Vector3 up )
{
Vector3 z = Vector3 . Normalize ( eye - target ) ;
Vector3 x = Vector3 . Normalize ( Vector3 . Cross ( up , z ) ) ;
Vector3 y = Vector3 . Normalize ( Vector3 . Cross ( z , x ) ) ;
2013-01-18 23:13:36 +00:00
Matrix4 result ;
2013-01-17 01:45:10 +00:00
result . Row0 . X = x . X ;
result . Row0 . Y = y . X ;
result . Row0 . Z = z . X ;
2013-01-18 23:13:36 +00:00
result . Row0 . W = 0 ;
2013-01-17 01:45:10 +00:00
result . Row1 . X = x . Y ;
result . Row1 . Y = y . Y ;
result . Row1 . Z = z . Y ;
2013-01-18 23:13:36 +00:00
result . Row1 . W = 0 ;
2013-01-17 01:45:10 +00:00
result . Row2 . X = x . Z ;
result . Row2 . Y = y . Z ;
result . Row2 . Z = z . Z ;
2013-01-18 23:13:36 +00:00
result . Row2 . W = 0 ;
result . Row3 . X = - ( ( x . X * eye . X ) + ( x . Y * eye . Y ) + ( x . Z * eye . Z ) ) ;
result . Row3 . Y = - ( ( y . X * eye . X ) + ( y . Y * eye . Y ) + ( y . Z * eye . Z ) ) ;
result . Row3 . Z = - ( ( z . X * eye . X ) + ( z . Y * eye . Y ) + ( z . Z * eye . Z ) ) ;
result . Row3 . W = 1 ;
2013-01-17 01:45:10 +00:00
return result ;
}
/// <summary>
/// Build a world space to camera space matrix
/// </summary>
/// <param name="eyeX">Eye (camera) position in world space</param>
/// <param name="eyeY">Eye (camera) position in world space</param>
/// <param name="eyeZ">Eye (camera) position in world space</param>
/// <param name="targetX">Target position in world space</param>
/// <param name="targetY">Target position in world space</param>
/// <param name="targetZ">Target position in world space</param>
/// <param name="upX">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
/// <param name="upY">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
/// <param name="upZ">Up vector in world space (should not be parallel to the camera direction, that is target - eye)</param>
/// <returns>A Matrix4 that transforms world space to camera space</returns>
public static Matrix4 LookAt ( float eyeX , float eyeY , float eyeZ , float targetX , float targetY , float targetZ , float upX , float upY , float upZ )
{
return LookAt ( new Vector3 ( eyeX , eyeY , eyeZ ) , new Vector3 ( targetX , targetY , targetZ ) , new Vector3 ( upX , upY , upZ ) ) ;
}
#endregion
2009-02-22 10:43:35 +00:00
#region Multiply Functions
/// <summary>
2009-06-19 13:41:32 +00:00
/// Multiplies two instances.
2009-02-22 10:43:35 +00:00
/// </summary>
2009-03-25 21:53:12 +00:00
/// <param name="left">The left operand of the multiplication.</param>
/// <param name="right">The right operand of the multiplication.</param>
2013-01-19 08:29:22 +00:00
/// <returns>A new instance that is the result of the multiplication.</returns>
2009-02-22 10:43:35 +00:00
public static Matrix4 Mult ( Matrix4 left , Matrix4 right )
{
2009-06-19 13:41:32 +00:00
Matrix4 result ;
2009-07-17 08:27:25 +00:00
Mult ( ref left , ref right , out result ) ;
return result ;
2009-02-22 10:43:35 +00:00
}
2009-07-17 08:27:25 +00:00
/// <summary>
/// Multiplies two instances.
/// </summary>
2009-06-19 13:41:32 +00:00
/// <param name="left">The left operand of the multiplication.</param>
/// <param name="right">The right operand of the multiplication.</param>
2013-01-19 08:29:22 +00:00
/// <param name="result">A new instance that is the result of the multiplication.</param>
2009-02-22 10:43:35 +00:00
public static void Mult ( ref Matrix4 left , ref Matrix4 right , out Matrix4 result )
{
2011-09-04 20:52:42 +00:00
float lM11 = left . Row0 . X , lM12 = left . Row0 . Y , lM13 = left . Row0 . Z , lM14 = left . Row0 . W ,
lM21 = left . Row1 . X , lM22 = left . Row1 . Y , lM23 = left . Row1 . Z , lM24 = left . Row1 . W ,
lM31 = left . Row2 . X , lM32 = left . Row2 . Y , lM33 = left . Row2 . Z , lM34 = left . Row2 . W ,
lM41 = left . Row3 . X , lM42 = left . Row3 . Y , lM43 = left . Row3 . Z , lM44 = left . Row3 . W ,
rM11 = right . Row0 . X , rM12 = right . Row0 . Y , rM13 = right . Row0 . Z , rM14 = right . Row0 . W ,
rM21 = right . Row1 . X , rM22 = right . Row1 . Y , rM23 = right . Row1 . Z , rM24 = right . Row1 . W ,
rM31 = right . Row2 . X , rM32 = right . Row2 . Y , rM33 = right . Row2 . Z , rM34 = right . Row2 . W ,
rM41 = right . Row3 . X , rM42 = right . Row3 . Y , rM43 = right . Row3 . Z , rM44 = right . Row3 . W ;
result . Row0 . X = ( ( ( lM11 * rM11 ) + ( lM12 * rM21 ) ) + ( lM13 * rM31 ) ) + ( lM14 * rM41 ) ;
result . Row0 . Y = ( ( ( lM11 * rM12 ) + ( lM12 * rM22 ) ) + ( lM13 * rM32 ) ) + ( lM14 * rM42 ) ;
result . Row0 . Z = ( ( ( lM11 * rM13 ) + ( lM12 * rM23 ) ) + ( lM13 * rM33 ) ) + ( lM14 * rM43 ) ;
result . Row0 . W = ( ( ( lM11 * rM14 ) + ( lM12 * rM24 ) ) + ( lM13 * rM34 ) ) + ( lM14 * rM44 ) ;
result . Row1 . X = ( ( ( lM21 * rM11 ) + ( lM22 * rM21 ) ) + ( lM23 * rM31 ) ) + ( lM24 * rM41 ) ;
result . Row1 . Y = ( ( ( lM21 * rM12 ) + ( lM22 * rM22 ) ) + ( lM23 * rM32 ) ) + ( lM24 * rM42 ) ;
result . Row1 . Z = ( ( ( lM21 * rM13 ) + ( lM22 * rM23 ) ) + ( lM23 * rM33 ) ) + ( lM24 * rM43 ) ;
result . Row1 . W = ( ( ( lM21 * rM14 ) + ( lM22 * rM24 ) ) + ( lM23 * rM34 ) ) + ( lM24 * rM44 ) ;
result . Row2 . X = ( ( ( lM31 * rM11 ) + ( lM32 * rM21 ) ) + ( lM33 * rM31 ) ) + ( lM34 * rM41 ) ;
result . Row2 . Y = ( ( ( lM31 * rM12 ) + ( lM32 * rM22 ) ) + ( lM33 * rM32 ) ) + ( lM34 * rM42 ) ;
result . Row2 . Z = ( ( ( lM31 * rM13 ) + ( lM32 * rM23 ) ) + ( lM33 * rM33 ) ) + ( lM34 * rM43 ) ;
result . Row2 . W = ( ( ( lM31 * rM14 ) + ( lM32 * rM24 ) ) + ( lM33 * rM34 ) ) + ( lM34 * rM44 ) ;
result . Row3 . X = ( ( ( lM41 * rM11 ) + ( lM42 * rM21 ) ) + ( lM43 * rM31 ) ) + ( lM44 * rM41 ) ;
result . Row3 . Y = ( ( ( lM41 * rM12 ) + ( lM42 * rM22 ) ) + ( lM43 * rM32 ) ) + ( lM44 * rM42 ) ;
result . Row3 . Z = ( ( ( lM41 * rM13 ) + ( lM42 * rM23 ) ) + ( lM43 * rM33 ) ) + ( lM44 * rM43 ) ;
result . Row3 . W = ( ( ( lM41 * rM14 ) + ( lM42 * rM24 ) ) + ( lM43 * rM34 ) ) + ( lM44 * rM44 ) ;
2009-02-22 10:43:35 +00:00
}
#endregion
#region Invert Functions
/// <summary>
/// Calculate the inverse of the given matrix
/// </summary>
/// <param name="mat">The matrix to invert</param>
2013-01-17 01:49:26 +00:00
/// <param name="result">The inverse of the given matrix if it has one, or the input if it is singular</param>
2009-02-22 10:43:35 +00:00
/// <exception cref="InvalidOperationException">Thrown if the Matrix4 is singular.</exception>
2013-01-17 01:49:26 +00:00
public static void Invert ( ref Matrix4 mat , out Matrix4 result )
2009-02-22 10:43:35 +00:00
{
int [ ] colIdx = { 0 , 0 , 0 , 0 } ;
int [ ] rowIdx = { 0 , 0 , 0 , 0 } ;
int [ ] pivotIdx = { - 1 , - 1 , - 1 , - 1 } ;
// convert the matrix to an array for easy looping
float [ , ] inverse = { { mat . Row0 . X , mat . Row0 . Y , mat . Row0 . Z , mat . Row0 . W } ,
2009-07-17 08:27:25 +00:00
{ mat . Row1 . X , mat . Row1 . Y , mat . Row1 . Z , mat . Row1 . W } ,
{ mat . Row2 . X , mat . Row2 . Y , mat . Row2 . Z , mat . Row2 . W } ,
{ mat . Row3 . X , mat . Row3 . Y , mat . Row3 . Z , mat . Row3 . W } } ;
2009-02-22 10:43:35 +00:00
int icol = 0 ;
int irow = 0 ;
for ( int i = 0 ; i < 4 ; i + + )
{
// Find the largest pivot value
float maxPivot = 0.0f ;
for ( int j = 0 ; j < 4 ; j + + )
{
if ( pivotIdx [ j ] ! = 0 )
{
for ( int k = 0 ; k < 4 ; + + k )
{
if ( pivotIdx [ k ] = = - 1 )
{
float absVal = System . Math . Abs ( inverse [ j , k ] ) ;
if ( absVal > maxPivot )
{
maxPivot = absVal ;
irow = j ;
icol = k ;
}
}
else if ( pivotIdx [ k ] > 0 )
{
2013-01-17 01:49:26 +00:00
result = mat ;
return ;
2009-02-22 10:43:35 +00:00
}
}
}
}
+ + ( pivotIdx [ icol ] ) ;
// Swap rows over so pivot is on diagonal
if ( irow ! = icol )
{
for ( int k = 0 ; k < 4 ; + + k )
{
float f = inverse [ irow , k ] ;
inverse [ irow , k ] = inverse [ icol , k ] ;
inverse [ icol , k ] = f ;
}
}
rowIdx [ i ] = irow ;
colIdx [ i ] = icol ;
float pivot = inverse [ icol , icol ] ;
// check for singular matrix
if ( pivot = = 0.0f )
{
throw new InvalidOperationException ( "Matrix is singular and cannot be inverted." ) ;
}
// Scale row so it has a unit diagonal
float oneOverPivot = 1.0f / pivot ;
inverse [ icol , icol ] = 1.0f ;
for ( int k = 0 ; k < 4 ; + + k )
inverse [ icol , k ] * = oneOverPivot ;
// Do elimination of non-diagonal elements
for ( int j = 0 ; j < 4 ; + + j )
{
// check this isn't on the diagonal
if ( icol ! = j )
{
float f = inverse [ j , icol ] ;
inverse [ j , icol ] = 0.0f ;
for ( int k = 0 ; k < 4 ; + + k )
inverse [ j , k ] - = inverse [ icol , k ] * f ;
}
}
}
for ( int j = 3 ; j > = 0 ; - - j )
{
int ir = rowIdx [ j ] ;
int ic = colIdx [ j ] ;
for ( int k = 0 ; k < 4 ; + + k )
{
float f = inverse [ k , ir ] ;
inverse [ k , ir ] = inverse [ k , ic ] ;
inverse [ k , ic ] = f ;
}
}
2013-01-17 01:49:26 +00:00
result . Row0 . X = inverse [ 0 , 0 ] ;
result . Row0 . Y = inverse [ 0 , 1 ] ;
result . Row0 . Z = inverse [ 0 , 2 ] ;
result . Row0 . W = inverse [ 0 , 3 ] ;
result . Row1 . X = inverse [ 1 , 0 ] ;
result . Row1 . Y = inverse [ 1 , 1 ] ;
result . Row1 . Z = inverse [ 1 , 2 ] ;
result . Row1 . W = inverse [ 1 , 3 ] ;
result . Row2 . X = inverse [ 2 , 0 ] ;
result . Row2 . Y = inverse [ 2 , 1 ] ;
result . Row2 . Z = inverse [ 2 , 2 ] ;
result . Row2 . W = inverse [ 2 , 3 ] ;
result . Row3 . X = inverse [ 3 , 0 ] ;
result . Row3 . Y = inverse [ 3 , 1 ] ;
result . Row3 . Z = inverse [ 3 , 2 ] ;
result . Row3 . W = inverse [ 3 , 3 ] ;
}
/// <summary>
/// Calculate the inverse of the given matrix
/// </summary>
/// <param name="mat">The matrix to invert</param>
/// <returns>The inverse of the given matrix if it has one, or the input if it is singular</returns>
/// <exception cref="InvalidOperationException">Thrown if the Matrix4 is singular.</exception>
public static Matrix4 Invert ( Matrix4 mat )
{
Matrix4 result ;
Invert ( ref mat , out result ) ;
return result ;
2009-02-22 10:43:35 +00:00
}
#endregion
#region Transpose
/// <summary>
/// Calculate the transpose of the given matrix
/// </summary>
/// <param name="mat">The matrix to transpose</param>
/// <returns>The transpose of the given matrix</returns>
public static Matrix4 Transpose ( Matrix4 mat )
{
return new Matrix4 ( mat . Column0 , mat . Column1 , mat . Column2 , mat . Column3 ) ;
}
/// <summary>
/// Calculate the transpose of the given matrix
/// </summary>
/// <param name="mat">The matrix to transpose</param>
2009-03-25 21:53:12 +00:00
/// <param name="result">The result of the calculation</param>
2009-02-22 10:43:35 +00:00
public static void Transpose ( ref Matrix4 mat , out Matrix4 result )
{
result . Row0 = mat . Column0 ;
result . Row1 = mat . Column1 ;
result . Row2 = mat . Column2 ;
result . Row3 = mat . Column3 ;
}
#endregion
#endregion
#region Operators
/// <summary>
/// Matrix multiplication
/// </summary>
/// <param name="left">left-hand operand</param>
/// <param name="right">right-hand operand</param>
2013-01-17 01:45:10 +00:00
/// <returns>A new Matrix4 which holds the result of the multiplication</returns>
2009-02-22 10:43:35 +00:00
public static Matrix4 operator * ( Matrix4 left , Matrix4 right )
{
return Matrix4 . Mult ( left , right ) ;
}
2009-09-04 23:11:20 +00:00
/// <summary>
/// Compares two instances for equality.
/// </summary>
/// <param name="left">The first instance.</param>
/// <param name="right">The second instance.</param>
/// <returns>True, if left equals right; false otherwise.</returns>
2009-02-22 10:43:35 +00:00
public static bool operator = = ( Matrix4 left , Matrix4 right )
{
return left . Equals ( right ) ;
}
2009-09-04 23:11:20 +00:00
/// <summary>
/// Compares two instances for inequality.
/// </summary>
/// <param name="left">The first instance.</param>
/// <param name="right">The second instance.</param>
/// <returns>True, if left does not equal right; false otherwise.</returns>
2009-02-22 10:43:35 +00:00
public static bool operator ! = ( Matrix4 left , Matrix4 right )
{
return ! left . Equals ( right ) ;
}
#endregion
#region Overrides
#region public override string ToString ( )
/// <summary>
2013-01-17 01:45:10 +00:00
/// Returns a System.String that represents the current Matrix4.
2009-02-22 10:43:35 +00:00
/// </summary>
2013-01-17 01:45:10 +00:00
/// <returns>The string representation of the matrix.</returns>
2009-02-22 10:43:35 +00:00
public override string ToString ( )
{
return String . Format ( "{0}\n{1}\n{2}\n{3}" , Row0 , Row1 , Row2 , Row3 ) ;
}
#endregion
#region public override int GetHashCode ( )
/// <summary>
/// Returns the hashcode for this instance.
/// </summary>
/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
public override int GetHashCode ( )
{
return Row0 . GetHashCode ( ) ^ Row1 . GetHashCode ( ) ^ Row2 . GetHashCode ( ) ^ Row3 . GetHashCode ( ) ;
}
#endregion
#region public override bool Equals ( object obj )
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
2009-06-19 13:41:32 +00:00
/// <param name="obj">The object to compare tresult.</param>
2009-02-22 10:43:35 +00:00
/// <returns>True if the instances are equal; false otherwise.</returns>
public override bool Equals ( object obj )
{
if ( ! ( obj is Matrix4 ) )
return false ;
return this . Equals ( ( Matrix4 ) obj ) ;
}
#endregion
#endregion
#endregion
#region IEquatable < Matrix4 > Members
/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
2009-03-25 21:53:12 +00:00
/// <param name="other">An matrix to compare with this matrix.</param>
2009-02-22 10:43:35 +00:00
/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
public bool Equals ( Matrix4 other )
{
return
Row0 = = other . Row0 & &
Row1 = = other . Row1 & &
Row2 = = other . Row2 & &
Row3 = = other . Row3 ;
}
#endregion
}
}