Matrix4 optimizations

This commit is contained in:
Robert Rouhani 2013-01-16 17:45:10 -08:00
parent fa422dca2a
commit 7a0634814e
2 changed files with 384 additions and 315 deletions

167
.gitignore vendored
View file

@ -1,135 +1,56 @@
# Ignores specific to OpenTK.
Binaries/
OpenTK.userprefs
Source/GlobalAssemblyInfo.cs
Version.txt
# OpenTK Resource files that seem like they should be ignored: #OS junk files
Source/Compatibility/Properties/Resources.resources [Tt]humbs.db
Source/Compatibility/Tao/Platform/Windows/SimpleOpenGlControl.resources *.DS_Store
Source/Examples/ExampleBrowser.resources
Source/Examples/OpenAL/1.1/Parrot.resources
Source/Examples/OpenTK/Fonts/FontRenderingBasic.resources
Source/Examples/OpenTK/GLControl/DerivedGLControl.resources
Source/Examples/OpenTK/GLControl/GLControlGameLoop.resources
Source/Examples/OpenTK/GLControl/GLControlSimple.resources
Source/Examples/OpenTK/GLControl/MultipleGLControls.resources
Source/Examples/OpenTK/Test/Extensions.resources
Source/Examples/OpenTK/Test/InputLogger.resources
Source/Examples/Properties/Resources.resources
Source/OpenTK/Properties/Resources.resources
#Visual Studio files
# Build Folders (you can keep bin if you'd like, to store dlls and pdbs) *.exe
[Bb]in/
[Oo]bj/
# mstest test results
TestResults
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Rr]elease/
x64/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb *.pdb
*.pgc *.user
*.pgd *.aps
*.rsp *.pch
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.log
*.vspscc *.vspscc
*.vssscc *.vssscc
.builds *_i.c
*_p.c
# Visual C++ cache files
ipch/
*.aps
*.ncb *.ncb
*.opensdf *.suo
*.tlb
*.tlh
*.bak
*.[Cc]ache
*.ilk
*.log
*.lib
*.sbr
*.sdf *.sdf
ipch/
obj/
[Bb]in
[Dd]ebug*/
[Rr]elease*/
Ankh.NoLoad
# Visual Studio profiler #Tooling
*.psess _ReSharper*/
*.vsp *.resharper
*.vspx
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*
# Mindbench SASS cache
.sass-cache/
# NCrunch
*.ncrunch*
.*crunch*.local.xml
# Installshield output folder
[Ee]xpress
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish
# Publish Web Output
*.Publish.xml
# NuGet Packages Directory
packages
# Windows Azure Build Output
csx
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql
TestResults
[Tt]est[Rr]esult* [Tt]est[Rr]esult*
*.Cache
ClientBin #Project files
[Ss]tyle[Cc]op.* [Bb]uild/
#Subversion files
.svn
# Office Temp Files
~$* ~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects
# Backup & report files from converting an old project file to a newer #MonoDevelop files
# Visual Studio version. Backup files are not needed, because we have git ;-) *.userprefs
_UpgradeReport_Files/ *.pidb
Backup*/
UpgradeLog*.XML
# SQL Server files #Generated
App_Data/*.mdf /Version.txt
App_Data/*.ldf /Source/GlobalAssemblyInfo.cs
/Source/OpenTK/OpenTK.xml
/Source/GLControl/OpenTK.GLControl.xml

View file

@ -37,24 +37,27 @@ namespace OpenTK
#region Fields #region Fields
/// <summary> /// <summary>
/// Top row of the matrix /// Top row of the matrix.
/// </summary> /// </summary>
public Vector4 Row0; public Vector4 Row0;
/// <summary> /// <summary>
/// 2nd row of the matrix /// 2nd row of the matrix.
/// </summary> /// </summary>
public Vector4 Row1; public Vector4 Row1;
/// <summary> /// <summary>
/// 3rd row of the matrix /// 3rd row of the matrix.
/// </summary> /// </summary>
public Vector4 Row2; public Vector4 Row2;
/// <summary> /// <summary>
/// Bottom row of the matrix /// Bottom row of the matrix.
/// </summary> /// </summary>
public Vector4 Row3; public Vector4 Row3;
/// <summary> /// <summary>
/// The identity matrix /// The identity matrix.
/// </summary> /// </summary>
public static Matrix4 Identity = new Matrix4(Vector4.UnitX, Vector4.UnitY, Vector4.UnitZ, Vector4.UnitW); public static Matrix4 Identity = new Matrix4(Vector4.UnitX, Vector4.UnitY, Vector4.UnitZ, Vector4.UnitW);
@ -65,10 +68,10 @@ namespace OpenTK
/// <summary> /// <summary>
/// Constructs a new instance. /// Constructs a new instance.
/// </summary> /// </summary>
/// <param name="row0">Top row of the matrix</param> /// <param name="row0">Top row of the matrix.</param>
/// <param name="row1">Second 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="row2">Third row of the matrix.</param>
/// <param name="row3">Bottom row of the matrix</param> /// <param name="row3">Bottom row of the matrix.</param>
public Matrix4(Vector4 row0, Vector4 row1, Vector4 row2, Vector4 row3) public Matrix4(Vector4 row0, Vector4 row1, Vector4 row2, Vector4 row3)
{ {
Row0 = row0; Row0 = row0;
@ -134,23 +137,29 @@ namespace OpenTK
/// <summary> /// <summary>
/// The determinant of this matrix /// The determinant of this matrix
/// Gets the determinant of this matrix.
/// </summary> /// </summary>
public float Determinant public float Determinant
{ {
get get
{ {
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;
return return
Row0.X * Row1.Y * Row2.Z * Row3.W - Row0.X * Row1.Y * Row2.W * Row3.Z + Row0.X * Row1.Z * Row2.W * Row3.Y - Row0.X * Row1.Z * Row2.Y * Row3.W m11 * m22 * m33 * m44 - m11 * m22 * m34 * m43 + m11 * m23 * m34 * m42 - m11 * m23 * m32 * m44
+ Row0.X * Row1.W * Row2.Y * Row3.Z - Row0.X * Row1.W * Row2.Z * Row3.Y - Row0.Y * Row1.Z * Row2.W * Row3.X + Row0.Y * Row1.Z * Row2.X * Row3.W + m11 * m24 * m32 * m43 - m11 * m24 * m33 * m42 - m12 * m23 * m34 * m41 + m12 * m23 * m31 * m44
- Row0.Y * Row1.W * Row2.X * Row3.Z + Row0.Y * Row1.W * Row2.Z * Row3.X - Row0.Y * Row1.X * Row2.Z * Row3.W + Row0.Y * Row1.X * Row2.W * Row3.Z - m12 * m24 * m31 * m43 + m12 * m24 * m33 * m41 - m12 * m21 * m33 * m44 + m12 * m21 * m34 * m43
+ Row0.Z * Row1.W * Row2.X * Row3.Y - Row0.Z * Row1.W * Row2.Y * Row3.X + Row0.Z * Row1.X * Row2.Y * Row3.W - Row0.Z * Row1.X * Row2.W * Row3.Y + m13 * m24 * m31 * m42 - m13 * m24 * m32 * m41 + m13 * m21 * m32 * m44 - m13 * m21 * m34 * m42
+ Row0.Z * Row1.Y * Row2.W * Row3.X - Row0.Z * Row1.Y * Row2.X * Row3.W - Row0.W * Row1.X * Row2.Y * Row3.Z + Row0.W * Row1.X * Row2.Z * Row3.Y + m13 * m22 * m34 * m41 - m13 * m22 * m31 * m44 - m14 * m21 * m32 * m43 + m14 * m21 * m33 * m42
- Row0.W * Row1.Y * Row2.Z * Row3.X + Row0.W * Row1.Y * Row2.X * Row3.Z - Row0.W * Row1.Z * Row2.X * Row3.Y + Row0.W * Row1.Z * Row2.Y * Row3.X; - m14 * m22 * m33 * m41 + m14 * m22 * m31 * m43 - m14 * m23 * m31 * m42 + m14 * m23 * m32 * m41;
} }
} }
/// <summary> /// <summary>
/// The first column of this matrix /// Gets the first column of this matrix.
/// </summary> /// </summary>
public Vector4 Column0 public Vector4 Column0
{ {
@ -158,7 +167,7 @@ namespace OpenTK
} }
/// <summary> /// <summary>
/// The second column of this matrix /// Gets the second column of this matrix.
/// </summary> /// </summary>
public Vector4 Column1 public Vector4 Column1
{ {
@ -166,7 +175,7 @@ namespace OpenTK
} }
/// <summary> /// <summary>
/// The third column of this matrix /// Gets the third column of this matrix.
/// </summary> /// </summary>
public Vector4 Column2 public Vector4 Column2
{ {
@ -174,7 +183,7 @@ namespace OpenTK
} }
/// <summary> /// <summary>
/// The fourth column of this matrix /// Gets the fourth column of this matrix.
/// </summary> /// </summary>
public Vector4 Column3 public Vector4 Column3
{ {
@ -303,16 +312,40 @@ namespace OpenTK
/// <param name="result">A matrix instance.</param> /// <param name="result">A matrix instance.</param>
public static void CreateFromAxisAngle(Vector3 axis, float angle, out Matrix4 result) public static void CreateFromAxisAngle(Vector3 axis, float angle, out Matrix4 result)
{ {
// normalize and create a local copy of the vector.
axis.Normalize();
float axisX = axis.X, axisY = axis.Y, axisZ = axis.Z;
// calculate angles
float cos = (float)System.Math.Cos(-angle); float cos = (float)System.Math.Cos(-angle);
float sin = (float)System.Math.Sin(-angle); float sin = (float)System.Math.Sin(-angle);
float t = 1.0f - cos; float t = 1.0f - cos;
axis.Normalize(); // 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;
result = new Matrix4(t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f, float sinX = sin * axisX,
t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f, sinY = sin * axisY,
t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f, sinZ = sin * axisZ;
0, 0, 0, 1);
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;
} }
/// <summary> /// <summary>
@ -330,6 +363,35 @@ namespace OpenTK
#endregion #endregion
#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
#region CreateRotation[XYZ] #region CreateRotation[XYZ]
/// <summary> /// <summary>
@ -342,10 +404,11 @@ namespace OpenTK
float cos = (float)System.Math.Cos(angle); float cos = (float)System.Math.Cos(angle);
float sin = (float)System.Math.Sin(angle); float sin = (float)System.Math.Sin(angle);
result.Row0 = Vector4.UnitX; result = Identity;
result.Row1 = new Vector4(0.0f, cos, sin, 0.0f); result.Row1.Y = cos;
result.Row2 = new Vector4(0.0f, -sin, cos, 0.0f); result.Row1.Z = sin;
result.Row3 = Vector4.UnitW; result.Row2.Y = -sin;
result.Row2.Z = cos;
} }
/// <summary> /// <summary>
@ -370,10 +433,11 @@ namespace OpenTK
float cos = (float)System.Math.Cos(angle); float cos = (float)System.Math.Cos(angle);
float sin = (float)System.Math.Sin(angle); float sin = (float)System.Math.Sin(angle);
result.Row0 = new Vector4(cos, 0.0f, -sin, 0.0f); result = Identity;
result.Row1 = Vector4.UnitY; result.Row0.X = cos;
result.Row2 = new Vector4(sin, 0.0f, cos, 0.0f); result.Row0.Z = -sin;
result.Row3 = Vector4.UnitW; result.Row2.X = sin;
result.Row2.Z = cos;
} }
/// <summary> /// <summary>
@ -398,10 +462,11 @@ namespace OpenTK
float cos = (float)System.Math.Cos(angle); float cos = (float)System.Math.Cos(angle);
float sin = (float)System.Math.Sin(angle); float sin = (float)System.Math.Sin(angle);
result.Row0 = new Vector4(cos, sin, 0.0f, 0.0f); result = Identity;
result.Row1 = new Vector4(-sin, cos, 0.0f, 0.0f); result.Row0.X = cos;
result.Row2 = Vector4.UnitZ; result.Row0.Y = sin;
result.Row3 = Vector4.UnitW; result.Row1.X = -sin;
result.Row1.Y = cos;
} }
/// <summary> /// <summary>
@ -430,7 +495,9 @@ namespace OpenTK
public static void CreateTranslation(float x, float y, float z, out Matrix4 result) public static void CreateTranslation(float x, float y, float z, out Matrix4 result)
{ {
result = Identity; result = Identity;
result.Row3 = new Vector4(x, y, z, 1); result.Row3.X = x;
result.Row3.Y = y;
result.Row3.Z = z;
} }
/// <summary> /// <summary>
@ -441,7 +508,9 @@ namespace OpenTK
public static void CreateTranslation(ref Vector3 vector, out Matrix4 result) public static void CreateTranslation(ref Vector3 vector, out Matrix4 result)
{ {
result = Identity; result = Identity;
result.Row3 = new Vector4(vector.X, vector.Y, vector.Z, 1); result.Row3.X = vector.X;
result.Row3.Y = vector.Y;
result.Row3.Z = vector.Z;
} }
/// <summary> /// <summary>
@ -472,6 +541,89 @@ namespace OpenTK
#endregion #endregion
#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>
/// <param name="result">A scale matrix.</returns>
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
#region CreateOrthographic #region CreateOrthographic
/// <summary> /// <summary>
@ -518,20 +670,19 @@ namespace OpenTK
/// <param name="result">The resulting Matrix4 instance.</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) public static void CreateOrthographicOffCenter(float left, float right, float bottom, float top, float zNear, float zFar, out Matrix4 result)
{ {
result = new Matrix4(); result = Identity;
float invRL = 1 / (right - left); float invRL = 1.0f / (right - left);
float invTB = 1 / (top - bottom); float invTB = 1.0f / (top - bottom);
float invFN = 1 / (zFar - zNear); float invFN = 1.0f / (zFar - zNear);
result.M11 = 2 * invRL; result.Row0.X = 2 * invRL;
result.M22 = 2 * invTB; result.Row1.Y = 2 * invTB;
result.M33 = -2 * invFN; result.Row2.Z = -2 * invFN;
result.M41 = -(right + left) * invRL; result.Row3.X = -(right + left) * invRL;
result.M42 = -(top + bottom) * invTB; result.Row3.Y = -(top + bottom) * invTB;
result.M43 = -(zFar + zNear) * invFN; result.Row3.Z = -(zFar + zNear) * invFN;
result.M44 = 1;
} }
/// <summary> /// <summary>
@ -655,10 +806,15 @@ namespace OpenTK
float c = -(zFar + zNear) / (zFar - zNear); float c = -(zFar + zNear) / (zFar - zNear);
float d = -(2.0f * zFar * zNear) / (zFar - zNear); float d = -(2.0f * zFar * zNear) / (zFar - zNear);
result = new Matrix4(x, 0, 0, 0, result = Identity;
0, y, 0, 0, result.Row0.X = x;
a, b, c, -1, result.Row1.Y = y;
0, 0, d, 0); result.Row2.X = a;
result.Row2.Y = b;
result.Row2.Z = c;
result.Row2.W = -1;
result.Row3.Z = d;
result.Row3.W = 0;
} }
/// <summary> /// <summary>
@ -775,7 +931,7 @@ namespace OpenTK
[Obsolete("Use CreateTranslation instead.")] [Obsolete("Use CreateTranslation instead.")]
public static Matrix4 Translation(Vector3 trans) public static Matrix4 Translation(Vector3 trans)
{ {
return Translation(trans.X, trans.Y, trans.Z); return CreateTranslation(trans);
} }
/// <summary> /// <summary>
@ -788,52 +944,7 @@ namespace OpenTK
[Obsolete("Use CreateTranslation instead.")] [Obsolete("Use CreateTranslation instead.")]
public static Matrix4 Translation(float x, float y, float z) public static Matrix4 Translation(float x, float y, float z)
{ {
Matrix4 result = Identity; return CreateTranslation(x, y, z);
result.Row3 = new Vector4(x, y, z, 1.0f);
return result;
}
#endregion
#endregion
#region Scale Functions
/// <summary>
/// Build a scaling matrix
/// </summary>
/// <param name="scale">Single scale factor for x,y and z axes</param>
/// <returns>A scaling matrix</returns>
public static Matrix4 Scale(float scale)
{
return Scale(scale, scale, scale);
}
/// <summary>
/// Build a scaling matrix
/// </summary>
/// <param name="scale">Scale factors for x,y and z axes</param>
/// <returns>A scaling matrix</returns>
public static Matrix4 Scale(Vector3 scale)
{
return Scale(scale.X, scale.Y, scale.Z);
}
/// <summary>
/// Build a scaling matrix
/// </summary>
/// <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>
public static Matrix4 Scale(float x, float y, float z)
{
Matrix4 result;
result.Row0 = Vector4.UnitX * x;
result.Row1 = Vector4.UnitY * y;
result.Row2 = Vector4.UnitZ * z;
result.Row3 = Vector4.UnitW;
return result;
} }
#endregion #endregion
@ -848,15 +959,7 @@ namespace OpenTK
[Obsolete("Use CreateRotationX instead.")] [Obsolete("Use CreateRotationX instead.")]
public static Matrix4 RotateX(float angle) public static Matrix4 RotateX(float angle)
{ {
float cos = (float)System.Math.Cos(angle); return CreateRotationX(angle);
float sin = (float)System.Math.Sin(angle);
Matrix4 result;
result.Row0 = Vector4.UnitX;
result.Row1 = new Vector4(0.0f, cos, sin, 0.0f);
result.Row2 = new Vector4(0.0f, -sin, cos, 0.0f);
result.Row3 = Vector4.UnitW;
return result;
} }
/// <summary> /// <summary>
@ -867,15 +970,7 @@ namespace OpenTK
[Obsolete("Use CreateRotationY instead.")] [Obsolete("Use CreateRotationY instead.")]
public static Matrix4 RotateY(float angle) public static Matrix4 RotateY(float angle)
{ {
float cos = (float)System.Math.Cos(angle); return CreateRotationY(angle);
float sin = (float)System.Math.Sin(angle);
Matrix4 result;
result.Row0 = new Vector4(cos, 0.0f, -sin, 0.0f);
result.Row1 = Vector4.UnitY;
result.Row2 = new Vector4(sin, 0.0f, cos, 0.0f);
result.Row3 = Vector4.UnitW;
return result;
} }
/// <summary> /// <summary>
@ -886,15 +981,7 @@ namespace OpenTK
[Obsolete("Use CreateRotationZ instead.")] [Obsolete("Use CreateRotationZ instead.")]
public static Matrix4 RotateZ(float angle) public static Matrix4 RotateZ(float angle)
{ {
float cos = (float)System.Math.Cos(angle); return CreateRotationZ(angle);
float sin = (float)System.Math.Sin(angle);
Matrix4 result;
result.Row0 = new Vector4(cos, sin, 0.0f, 0.0f);
result.Row1 = new Vector4(-sin, cos, 0.0f, 0.0f);
result.Row2 = Vector4.UnitZ;
result.Row3 = Vector4.UnitW;
return result;
} }
/// <summary> /// <summary>
@ -906,18 +993,7 @@ namespace OpenTK
[Obsolete("Use CreateFromAxisAngle instead.")] [Obsolete("Use CreateFromAxisAngle instead.")]
public static Matrix4 Rotate(Vector3 axis, float angle) public static Matrix4 Rotate(Vector3 axis, float angle)
{ {
float cos = (float)System.Math.Cos(-angle); return CreateFromAxisAngle(axis, angle);
float sin = (float)System.Math.Sin(-angle);
float t = 1.0f - cos;
axis.Normalize();
Matrix4 result;
result.Row0 = new Vector4(t * axis.X * axis.X + cos, t * axis.X * axis.Y - sin * axis.Z, t * axis.X * axis.Z + sin * axis.Y, 0.0f);
result.Row1 = new Vector4(t * axis.X * axis.Y + sin * axis.Z, t * axis.Y * axis.Y + cos, t * axis.Y * axis.Z - sin * axis.X, 0.0f);
result.Row2 = new Vector4(t * axis.X * axis.Z - sin * axis.Y, t * axis.Y * axis.Z + sin * axis.X, t * axis.Z * axis.Z + cos, 0.0f);
result.Row3 = Vector4.UnitW;
return result;
} }
/// <summary> /// <summary>
@ -925,59 +1001,60 @@ namespace OpenTK
/// </summary> /// </summary>
/// <param name="q">the quaternion</param> /// <param name="q">the quaternion</param>
/// <returns>A rotation matrix</returns> /// <returns>A rotation matrix</returns>
[Obsolete("Use CreateRotation instead.")]
public static Matrix4 Rotate(Quaternion q) public static Matrix4 Rotate(Quaternion q)
{ {
Vector3 axis; return CreateFromQuaternion(q);
float angle; }
q.ToAxisAngle(out axis, out angle);
return CreateFromAxisAngle(axis, angle); #endregion
#region Scale Functions
/// <summary>
/// Build a scaling matrix
/// </summary>
/// <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)
{
return Scale(scale, scale, scale);
}
/// <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);
}
/// <summary>
/// Build a scaling matrix
/// </summary>
/// <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)
{
Matrix4 result;
result.Row0 = Vector4.UnitX * x;
result.Row1 = Vector4.UnitY * y;
result.Row2 = Vector4.UnitZ * z;
result.Row3 = Vector4.UnitW;
return result;
} }
#endregion #endregion
#region Camera Helper Functions #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));
Matrix4 rot = new Matrix4(new Vector4(x.X, y.X, z.X, 0.0f),
new Vector4(x.Y, y.Y, z.Y, 0.0f),
new Vector4(x.Z, y.Z, z.Z, 0.0f),
Vector4.UnitW);
Matrix4 trans = Matrix4.CreateTranslation(-eye);
return trans * rot;
}
/// <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));
}
/// <summary> /// <summary>
/// Build a projection matrix /// Build a projection matrix
/// </summary> /// </summary>
@ -1021,6 +1098,64 @@ namespace OpenTK
#endregion #endregion
#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));
Matrix4 result = Identity;
//rotation
result.Row0.X = x.X;
result.Row0.Y = y.X;
result.Row0.Z = z.X;
result.Row1.X = x.Y;
result.Row1.Y = y.Y;
result.Row1.Z = z.Y;
result.Row2.X = x.Z;
result.Row2.Y = y.Z;
result.Row2.Z = z.Z;
//position
result.Row0.W = -eye.X;
result.Row1.W = -eye.Y;
result.Row2.W = -eye.Z;
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
#region Multiply Functions #region Multiply Functions
/// <summary> /// <summary>
@ -1178,10 +1313,23 @@ namespace OpenTK
} }
} }
mat.Row0 = new Vector4(inverse[0, 0], inverse[0, 1], inverse[0, 2], inverse[0, 3]); mat.Row0.X = inverse[0, 0];
mat.Row1 = new Vector4(inverse[1, 0], inverse[1, 1], inverse[1, 2], inverse[1, 3]); mat.Row0.Y = inverse[0, 1];
mat.Row2 = new Vector4(inverse[2, 0], inverse[2, 1], inverse[2, 2], inverse[2, 3]); mat.Row0.Z = inverse[0, 2];
mat.Row3 = new Vector4(inverse[3, 0], inverse[3, 1], inverse[3, 2], inverse[3, 3]); mat.Row0.W = inverse[0, 3];
mat.Row1.X = inverse[1, 0];
mat.Row1.Y = inverse[1, 1];
mat.Row1.Z = inverse[1, 2];
mat.Row1.W = inverse[1, 3];
mat.Row2.X = inverse[2, 0];
mat.Row2.Y = inverse[2, 1];
mat.Row2.Z = inverse[2, 2];
mat.Row2.W = inverse[2, 3];
mat.Row3.X = inverse[3, 0];
mat.Row3.Y = inverse[3, 1];
mat.Row3.Z = inverse[3, 2];
mat.Row3.W = inverse[3, 3];
return mat; return mat;
} }
@ -1224,7 +1372,7 @@ namespace OpenTK
/// </summary> /// </summary>
/// <param name="left">left-hand operand</param> /// <param name="left">left-hand operand</param>
/// <param name="right">right-hand operand</param> /// <param name="right">right-hand operand</param>
/// <returns>A new Matrix44 which holds the result of the multiplication</returns> /// <returns>A new Matrix4 which holds the result of the multiplication</returns>
public static Matrix4 operator *(Matrix4 left, Matrix4 right) public static Matrix4 operator *(Matrix4 left, Matrix4 right)
{ {
return Matrix4.Mult(left, right); return Matrix4.Mult(left, right);
@ -1259,9 +1407,9 @@ namespace OpenTK
#region public override string ToString() #region public override string ToString()
/// <summary> /// <summary>
/// Returns a System.String that represents the current Matrix44. /// Returns a System.String that represents the current Matrix4.
/// </summary> /// </summary>
/// <returns></returns> /// <returns>The string representation of the matrix.</returns>
public override string ToString() public override string ToString()
{ {
return String.Format("{0}\n{1}\n{2}\n{3}", Row0, Row1, Row2, Row3); return String.Format("{0}\n{1}\n{2}\n{3}", Row0, Row1, Row2, Row3);