New math classes by george.
This commit is contained in:
parent
a65e1ea45c
commit
cd1b48f207
6 changed files with 2425 additions and 294 deletions
|
@ -1,5 +1,6 @@
|
|||
#region --- License ---
|
||||
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
|
||||
* Contributions by Andy Gill.
|
||||
* See license.txt for license info
|
||||
*/
|
||||
#endregion
|
||||
|
@ -38,6 +39,28 @@ namespace OpenTK.Math
|
|||
return x;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert degrees to radians
|
||||
/// </summary>
|
||||
/// <param name="degrees">An angle in degrees</param>
|
||||
/// <returns>The angle expressed in radians</returns>
|
||||
public static float DegreesToRadians(float degrees)
|
||||
{
|
||||
const float degToRad = (float)System.Math.PI / 180.0f;
|
||||
return degrees * degToRad;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert radians to degrees
|
||||
/// </summary>
|
||||
/// <param name="degrees">An angle in radians</param>
|
||||
/// <returns>The angle expressed in degrees</returns>
|
||||
public static float RadiansToDegrees(float radians)
|
||||
{
|
||||
const float radToDeg = 180.0f / (float)System.Math.PI;
|
||||
return radians * radToDeg;
|
||||
}
|
||||
}
|
||||
|
||||
#if false
|
||||
|
|
523
Source/OpenTK/Math/Matrix4.cs
Normal file
523
Source/OpenTK/Math/Matrix4.cs
Normal file
|
@ -0,0 +1,523 @@
|
|||
#region --- License ---
|
||||
/* Copyright (c) 2006, 2007 the OpenTK team
|
||||
* Implemented by Andy Gill
|
||||
* See license.txt for license info
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenTK.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a 4x4 Matrix
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Matrix4
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// Top row of the matrix
|
||||
/// </summary>
|
||||
public Vector4 Row0;
|
||||
/// <summary>
|
||||
/// 2nd row of the matrix
|
||||
/// </summary>
|
||||
public Vector4 Row1;
|
||||
/// <summary>
|
||||
/// 3rd row of the matrix
|
||||
/// </summary>
|
||||
public Vector4 Row2;
|
||||
/// <summary>
|
||||
/// Bottom row of the matrix
|
||||
/// </summary>
|
||||
public Vector4 Row3;
|
||||
|
||||
/// <summary>
|
||||
/// The identity matrix
|
||||
/// </summary>
|
||||
public static Matrix4 Identity = new Matrix4(Vector4.UnitX, Vector4.UnitY, Vector4.UnitZ, Vector4.UnitW);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new matrix from 4 vectors representing each row
|
||||
/// </summary>
|
||||
/// <param name="row0">Top row of the matrix</param>
|
||||
/// <param name="row1">2nd row of the matrix</param>
|
||||
/// <param name="row2">3rd row of the matrix</param>
|
||||
/// <param name="row3">Bottom row of the matrix</param>
|
||||
public Matrix4(Vector4 row0, Vector4 row1, Vector4 row2, Vector4 row3)
|
||||
{
|
||||
Row0 = row0;
|
||||
Row1 = row1;
|
||||
Row2 = row2;
|
||||
Row3 = row3;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
#region public void Invert()
|
||||
|
||||
public void Invert()
|
||||
{
|
||||
this = Matrix4.Invert(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public void Transpose()
|
||||
|
||||
public void Transpose()
|
||||
{
|
||||
this = Matrix4.Transpose(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// The determinant of this matrix
|
||||
/// </summary>
|
||||
public float Determinant
|
||||
{
|
||||
get
|
||||
{
|
||||
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
|
||||
+ 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
|
||||
- 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
|
||||
+ 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
|
||||
+ 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
|
||||
- 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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The first column of this matrix
|
||||
/// </summary>
|
||||
public Vector4 Column0
|
||||
{
|
||||
get { return new Vector4(Row0.X, Row1.X, Row2.X, Row3.X); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The second column of this matrix
|
||||
/// </summary>
|
||||
public Vector4 Column1
|
||||
{
|
||||
get { return new Vector4(Row0.Y, Row1.Y, Row2.Y, Row3.Y); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The third column of this matrix
|
||||
/// </summary>
|
||||
public Vector4 Column2
|
||||
{
|
||||
get { return new Vector4(Row0.Z, Row1.Z, Row2.Z, Row3.Z); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The fourth column of this matrix
|
||||
/// </summary>
|
||||
public Vector4 Column3
|
||||
{
|
||||
get { return new Vector4(Row0.W, Row1.W, Row2.W, Row3.W); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Operator overloads
|
||||
|
||||
/// <summary>
|
||||
/// Matrix multiplication
|
||||
/// </summary>
|
||||
/// <param name="left">left-hand operand</param>
|
||||
/// <param name="right">right-hand operand</param>
|
||||
/// <returns>A new Matrix44 which holds the result of the multiplication</returns>
|
||||
public static Matrix4 operator *(Matrix4 left, Matrix4 right)
|
||||
{
|
||||
return Matrix4.Mult(left, right);
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
unsafe public static explicit operator float*(Matrix4 mat)
|
||||
{
|
||||
return &mat.Row0.X;
|
||||
}
|
||||
|
||||
public static explicit operator IntPtr(Matrix4 mat)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (IntPtr)(&mat.Row0.X);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Static functions
|
||||
|
||||
#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
|
||||
|
||||
#region Translation Functions
|
||||
|
||||
/// <summary>
|
||||
/// Build a translation matrix with the given translation
|
||||
/// </summary>
|
||||
/// <param name="trans">The vector to translate along</param>
|
||||
/// <returns>A Translation matrix</returns>
|
||||
public static Matrix4 Translation(Vector3 trans)
|
||||
{
|
||||
return Translation(trans.X, trans.Y, trans.Z);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public static Matrix4 Translation(float x, float y, float z)
|
||||
{
|
||||
Matrix4 result = Identity;
|
||||
result.Row3 = new Vector4(x, y, z, 1.0f);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#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>
|
||||
public static Matrix4 RotateX(float angle)
|
||||
{
|
||||
float cos = (float)System.Math.Cos(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>
|
||||
/// 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>
|
||||
public static Matrix4 RotateY(float angle)
|
||||
{
|
||||
float cos = (float)System.Math.Cos(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>
|
||||
/// 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>
|
||||
public static Matrix4 RotateZ(float angle)
|
||||
{
|
||||
float cos = (float)System.Math.Cos(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>
|
||||
/// 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>
|
||||
public static Matrix4 Rotate(Vector3 axis, float angle)
|
||||
{
|
||||
float cos = (float)System.Math.Cos(-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>
|
||||
/// Build a rotation matrix from a quaternion
|
||||
/// </summary>
|
||||
/// <param name="q">the quaternion</param>
|
||||
/// <returns>A rotation matrix</returns>
|
||||
public static Matrix4 Rotate(Quaternion q)
|
||||
{
|
||||
Vector3 axis;
|
||||
float angle;
|
||||
q.ToAxisAngle(out axis, out angle);
|
||||
return Rotate(axis, angle);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Multiply Functions
|
||||
|
||||
/// <summary>
|
||||
/// Post multiply this matrix by another matrix
|
||||
/// </summary>
|
||||
/// <param name="right">The matrix to multiply</param>
|
||||
/// <returns>A new Matrix44 that is the result of the multiplication</returns>
|
||||
public static Matrix4 Mult(Matrix4 left, Matrix4 right)
|
||||
{
|
||||
Vector4 col0 = right.Column0;
|
||||
Vector4 col1 = right.Column1;
|
||||
Vector4 col2 = right.Column2;
|
||||
Vector4 col3 = right.Column3;
|
||||
|
||||
left.Row0 = new Vector4(Vector4.Dot(left.Row0, col0), Vector4.Dot(left.Row0, col1), Vector4.Dot(left.Row0, col2), Vector4.Dot(left.Row0, col3));
|
||||
left.Row1 = new Vector4(Vector4.Dot(left.Row1, col0), Vector4.Dot(left.Row1, col1), Vector4.Dot(left.Row1, col2), Vector4.Dot(left.Row1, col3));
|
||||
left.Row2 = new Vector4(Vector4.Dot(left.Row2, col0), Vector4.Dot(left.Row2, col1), Vector4.Dot(left.Row2, col2), Vector4.Dot(left.Row2, col3));
|
||||
left.Row3 = new Vector4(Vector4.Dot(left.Row3, col0), Vector4.Dot(left.Row3, col1), Vector4.Dot(left.Row3, col2), Vector4.Dot(left.Row3, col3));
|
||||
return left;
|
||||
}
|
||||
|
||||
public static void Mult(ref Matrix4 left, ref Matrix4 right, out Matrix4 result)
|
||||
{
|
||||
Vector4 col0 = right.Column0;
|
||||
Vector4 col1 = right.Column1;
|
||||
Vector4 col2 = right.Column2;
|
||||
Vector4 col3 = right.Column3;
|
||||
|
||||
result.Row0 = new Vector4(Vector4.Dot(left.Row0, col0), Vector4.Dot(left.Row0, col1), Vector4.Dot(left.Row0, col2), Vector4.Dot(left.Row0, col3));
|
||||
result.Row1 = new Vector4(Vector4.Dot(left.Row1, col0), Vector4.Dot(left.Row1, col1), Vector4.Dot(left.Row1, col2), Vector4.Dot(left.Row1, col3));
|
||||
result.Row2 = new Vector4(Vector4.Dot(left.Row2, col0), Vector4.Dot(left.Row2, col1), Vector4.Dot(left.Row2, col2), Vector4.Dot(left.Row2, col3));
|
||||
result.Row3 = new Vector4(Vector4.Dot(left.Row3, col0), Vector4.Dot(left.Row3, col1), Vector4.Dot(left.Row3, col2), Vector4.Dot(left.Row3, col3));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Invert Functions
|
||||
|
||||
/// <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>
|
||||
public static Matrix4 Invert(Matrix4 mat)
|
||||
{
|
||||
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},
|
||||
{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} };
|
||||
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)
|
||||
{
|
||||
return mat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
++(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)
|
||||
{
|
||||
return mat;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
mat.Row0 = new Vector4(inverse[0, 0], inverse[0, 1], inverse[0, 2], inverse[0, 3]);
|
||||
mat.Row1 = new Vector4(inverse[1, 0], inverse[1, 1], inverse[1, 2], inverse[1, 3]);
|
||||
mat.Row2 = new Vector4(inverse[2, 0], inverse[2, 1], inverse[2, 2], inverse[2, 3]);
|
||||
mat.Row3 = new Vector4(inverse[3, 0], inverse[3, 1], inverse[3, 2], inverse[3, 3]);
|
||||
return mat;
|
||||
}
|
||||
|
||||
#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>
|
||||
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 public override string ToString()
|
||||
|
||||
/// <summary>
|
||||
/// Returns a System.String that represents the current Matrix44.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0}\n{1}\n{2}\n{3}", Row0, Row1, Row2, Row3);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
458
Source/OpenTK/Math/Quaternion.cs
Normal file
458
Source/OpenTK/Math/Quaternion.cs
Normal file
|
@ -0,0 +1,458 @@
|
|||
#region --- License ---
|
||||
/* Copyright (c) 2006, 2007 the OpenTK team
|
||||
* Implemented by Andy Gill
|
||||
* See license.txt for license info
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenTK.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Quaternion
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Quaternion
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// The vector part of the quaternion
|
||||
/// </summary>
|
||||
public Vector3 XYZ;
|
||||
/// <summary>
|
||||
/// The w component of the quaternion
|
||||
/// </summary>
|
||||
public float W;
|
||||
|
||||
public static Quaternion Identity = new Quaternion(0, 0, 0, 1);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Quaternion from vector and w components
|
||||
/// </summary>
|
||||
/// <param name="v">The vector part</param>
|
||||
/// <param name="w">The w part</param>
|
||||
public Quaternion(Vector3 v, float w)
|
||||
{
|
||||
XYZ = v;
|
||||
W = w;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Quaternion
|
||||
/// </summary>
|
||||
/// <param name="x">The x component</param>
|
||||
/// <param name="y">The y component</param>
|
||||
/// <param name="z">The z component</param>
|
||||
/// <param name="w">The w component</param>
|
||||
public Quaternion(float x, float y, float z, float w)
|
||||
{
|
||||
XYZ = new Vector3(x, y, z);
|
||||
W = w;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
#region pubilc void ToAxisAngle(out Vector3 axis, out float angle)
|
||||
|
||||
/// <summary>
|
||||
/// Convert the current quaternion to axis angle representation
|
||||
/// </summary>
|
||||
/// <param name="axis">The resultant axis</param>
|
||||
/// <param name="angle">The resultant angle</param>
|
||||
public void ToAxisAngle(out Vector3 axis, out float angle)
|
||||
{
|
||||
Quaternion q = this;
|
||||
if (q.W > 1.0f)
|
||||
q.Normalize();
|
||||
|
||||
angle = 2.0f * (float)System.Math.Acos(q.W);
|
||||
float den = (float)System.Math.Sqrt(1.0 - q.W * q.W);
|
||||
axis = q.XYZ;
|
||||
if (den > 0.0001f)
|
||||
{
|
||||
axis = q.XYZ / den;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public float Length
|
||||
|
||||
/// <summary>
|
||||
/// Gets the length (magnitude) of the quaternion.
|
||||
/// </summary>
|
||||
/// <seealso cref="LengthSquared"/>
|
||||
public float Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return (float)System.Math.Sqrt(W * W + XYZ.LengthSquared);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public float LengthSquared
|
||||
|
||||
/// <summary>
|
||||
/// Gets the square of the quaternion length (magnitude).
|
||||
/// </summary>
|
||||
public float LengthSquared
|
||||
{
|
||||
get
|
||||
{
|
||||
return W * W + XYZ.LengthSquared;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public void Normalize()
|
||||
|
||||
/// <summary>
|
||||
/// Scales the Quaternion to unit length.
|
||||
/// </summary>
|
||||
public void Normalize()
|
||||
{
|
||||
float scale = 1.0f / this.Length;
|
||||
XYZ *= scale;
|
||||
W *= scale;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public void Conjugate()
|
||||
|
||||
/// <summary>
|
||||
/// Convert this quaternion to its conjugate
|
||||
/// </summary>
|
||||
public void Conjugate()
|
||||
{
|
||||
XYZ = -XYZ;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Operator overloads
|
||||
|
||||
public static Quaternion operator +(Quaternion left, Quaternion right)
|
||||
{
|
||||
left.XYZ += right.XYZ;
|
||||
left.W += right.W;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static Quaternion operator -(Quaternion left, Quaternion right)
|
||||
{
|
||||
left.XYZ -= right.XYZ;
|
||||
left.W -= right.W;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static Quaternion operator *(Quaternion left, Quaternion right)
|
||||
{
|
||||
float w = left.W * right.W - Vector3.Dot(left.XYZ, right.XYZ);
|
||||
left.XYZ = right.W * left.XYZ + left.W * right.XYZ + Vector3.Cross(left.XYZ, right.XYZ);
|
||||
left.W = w;
|
||||
return left;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
unsafe public static explicit operator float*(Quaternion q)
|
||||
{
|
||||
return &q.XYZ.X;
|
||||
}
|
||||
|
||||
public static explicit operator IntPtr(Quaternion q)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (IntPtr)(&q.XYZ.X);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Static functions
|
||||
|
||||
#region Add
|
||||
|
||||
/// <summary>
|
||||
/// Add two quaternions
|
||||
/// </summary>
|
||||
/// <param name="left">The first operand</param>
|
||||
/// <param name="right">The second operand</param>
|
||||
/// <returns>The result of the addition</returns>
|
||||
public static Quaternion Add(Quaternion left, Quaternion right)
|
||||
{
|
||||
left.XYZ += right.XYZ;
|
||||
left.W += right.W;
|
||||
return left;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add two quaternions
|
||||
/// </summary>
|
||||
/// <param name="left">The first operand</param>
|
||||
/// <param name="right">The second operand</param>
|
||||
/// <param name="result">The result of the addition</param>
|
||||
public static void Add(ref Quaternion left, ref Quaternion right, out Quaternion result)
|
||||
{
|
||||
result.XYZ = left.XYZ + right.XYZ;
|
||||
result.W = left.W + right.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sub
|
||||
|
||||
public static Quaternion Sub(Quaternion left, Quaternion right)
|
||||
{
|
||||
left.XYZ -= right.XYZ;
|
||||
left.W -= right.W;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static void Sub(ref Quaternion left, ref Quaternion right, out Quaternion result)
|
||||
{
|
||||
result.XYZ = left.XYZ - right.XYZ;
|
||||
result.W = left.W - right.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mult
|
||||
|
||||
public static Quaternion Mult(Quaternion left, Quaternion right)
|
||||
{
|
||||
float w = left.W * right.W - Vector3.Dot(left.XYZ, right.XYZ);
|
||||
left.XYZ = right.W * left.XYZ + left.W * right.XYZ + Vector3.Cross(left.XYZ, right.XYZ);
|
||||
left.W = w;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static void Mult(ref Quaternion left, ref Quaternion right, out Quaternion result)
|
||||
{
|
||||
result.W = left.W * right.W - Vector3.Dot(left.XYZ, right.XYZ);
|
||||
result.XYZ = right.W * left.XYZ + left.W * right.XYZ + Vector3.Cross(left.XYZ, right.XYZ);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Conjugate
|
||||
|
||||
/// <summary>
|
||||
/// Get the conjugate of the given quaternion
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion</param>
|
||||
/// <returns>The conjugate of the given quaternion</returns>
|
||||
public static Quaternion Conjugate(Quaternion q)
|
||||
{
|
||||
q.XYZ = -q.XYZ;
|
||||
return q;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the conjugate of the given quaternion
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion</param>
|
||||
/// <param name="result">The conjugate of the given quaternion</param>
|
||||
public static void Conjugate(ref Quaternion q, out Quaternion result)
|
||||
{
|
||||
result.XYZ = -q.XYZ;
|
||||
result.W = q.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Invert
|
||||
|
||||
/// <summary>
|
||||
/// Get the inverse of the given quaternion
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion to invert</param>
|
||||
/// <returns>The inverse of the given quaternion</returns>
|
||||
public static Quaternion Invert(Quaternion q)
|
||||
{
|
||||
float lengthSq = q.LengthSquared;
|
||||
if (lengthSq != 0.0)
|
||||
{
|
||||
float i = 1.0f / lengthSq;
|
||||
q.XYZ *= -i;
|
||||
q.W *= i;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the inverse of the given quaternion
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion to invert</param>
|
||||
/// <param name="result">The inverse of the given quaternion</param>
|
||||
public static void Invert(ref Quaternion q, out Quaternion result)
|
||||
{
|
||||
float lengthSq = q.LengthSquared;
|
||||
if (lengthSq != 0.0)
|
||||
{
|
||||
float i = 1.0f / lengthSq;
|
||||
result.XYZ = q.XYZ * -i;
|
||||
result.W = q.W * i;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = q;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Normalize
|
||||
|
||||
/// <summary>
|
||||
/// Scale the given quaternion to unit length
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion to normalize</param>
|
||||
/// <returns>The normalized quaternion</returns>
|
||||
public static Quaternion Normalize(Quaternion q)
|
||||
{
|
||||
float scale = 1.0f / q.Length;
|
||||
q.XYZ *= scale;
|
||||
q.W *= scale;
|
||||
return q;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale the given quaternion to unit length
|
||||
/// </summary>
|
||||
/// <param name="q">The quaternion to normalize</param>
|
||||
/// <param name="result">The normalized quaternion</param>
|
||||
public static void Normalize(ref Quaternion q, out Quaternion result)
|
||||
{
|
||||
float scale = 1.0f / q.Length;
|
||||
result.XYZ = q.XYZ * scale;
|
||||
result.W = q.W * scale;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region FromAxisAngle
|
||||
|
||||
/// <summary>
|
||||
/// Build a quaternion from the given axis and angle
|
||||
/// </summary>
|
||||
/// <param name="axis">The axis to rotate about</param>
|
||||
/// <param name="angle">The rotation angle in radians</param>
|
||||
/// <returns></returns>
|
||||
public static Quaternion FromAxisAngle(Vector3 axis, float angle)
|
||||
{
|
||||
if (axis.LengthSquared == 0.0f)
|
||||
return Identity;
|
||||
|
||||
Quaternion result = Identity;
|
||||
|
||||
angle *= 0.5f;
|
||||
axis.Normalize();
|
||||
result.XYZ = axis * (float)System.Math.Sin(angle);
|
||||
result.W = (float)System.Math.Cos(angle);
|
||||
|
||||
return Normalize(result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Slerp
|
||||
|
||||
/// <summary>
|
||||
/// Do Spherical linear interpolation between two quaternions
|
||||
/// </summary>
|
||||
/// <param name="q1">The first quaternion</param>
|
||||
/// <param name="q2">The second quaternion</param>
|
||||
/// <param name="blend">The blend factor</param>
|
||||
/// <returns>A smooth blend between the given quaternions</returns>
|
||||
public static Quaternion Slerp(Quaternion q1, Quaternion q2, float blend)
|
||||
{
|
||||
// if either input is zero, return the other.
|
||||
if (q1.LengthSquared == 0.0f)
|
||||
{
|
||||
if (q2.LengthSquared == 0.0f)
|
||||
{
|
||||
return Identity;
|
||||
}
|
||||
return q2;
|
||||
}
|
||||
else if (q2.LengthSquared == 0.0f)
|
||||
{
|
||||
return q1;
|
||||
}
|
||||
|
||||
|
||||
float cosHalfAngle = q1.W * q2.W + Vector3.Dot(q1.XYZ, q2.XYZ);
|
||||
|
||||
if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f)
|
||||
{
|
||||
// angle = 0.0f, so just return one input.
|
||||
return q1;
|
||||
}
|
||||
else if (cosHalfAngle < 0.0f)
|
||||
{
|
||||
q2.XYZ = -q2.XYZ;
|
||||
q2.W = -q2.W;
|
||||
cosHalfAngle = -cosHalfAngle;
|
||||
}
|
||||
|
||||
float blendA;
|
||||
float blendB;
|
||||
if (cosHalfAngle < 0.99f)
|
||||
{
|
||||
// do proper slerp for big angles
|
||||
float halfAngle = (float)System.Math.Acos(cosHalfAngle);
|
||||
float sinHalfAngle = (float)System.Math.Sin(halfAngle);
|
||||
float oneOverSinHalfAngle = 1.0f / sinHalfAngle;
|
||||
blendA = (float)System.Math.Sin(halfAngle * (1.0f - blend)) * oneOverSinHalfAngle;
|
||||
blendB = (float)System.Math.Sin(halfAngle * blend) * oneOverSinHalfAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
// do lerp if angle is really small.
|
||||
blendA = 1.0f - blend;
|
||||
blendB = blend;
|
||||
}
|
||||
|
||||
Quaternion result = new Quaternion(blendA * q1.XYZ + blendB * q2.XYZ, blendA * q1.W + blendB * q2.W);
|
||||
if (result.LengthSquared > 0.0f)
|
||||
return Normalize(result);
|
||||
else
|
||||
return Identity;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region public override string ToString()
|
||||
|
||||
/// <summary>
|
||||
/// Returns a System.String that represents the current Quaternion.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("V: {0}, W: {1}", XYZ, W);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#region --- License ---
|
||||
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
|
||||
* Contributions by Andy Gill.
|
||||
* See license.txt for license info
|
||||
*/
|
||||
#endregion
|
||||
|
@ -32,6 +33,10 @@ namespace OpenTK.Math
|
|||
/// </summary>
|
||||
public float Y;
|
||||
|
||||
public static Vector2 UnitX = new Vector2(1, 0);
|
||||
public static Vector2 UnitY = new Vector2(0, 1);
|
||||
public static Vector2 Zero = new Vector2(0, 0);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
@ -43,8 +48,8 @@ namespace OpenTK.Math
|
|||
/// <param name="y">The y coordinate of the net Vector2.</param>
|
||||
public Vector2(float x, float y)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -53,8 +58,8 @@ namespace OpenTK.Math
|
|||
/// <param name="v">The Vector2 to copy components from.</param>
|
||||
public Vector2(Vector2 v)
|
||||
{
|
||||
X = v.X;
|
||||
Y = v.Y;
|
||||
X = v.X;
|
||||
Y = v.Y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -63,8 +68,8 @@ namespace OpenTK.Math
|
|||
/// <param name="v">The Vector3 to copy components from. Z is discarded.</param>
|
||||
public Vector2(Vector3 v)
|
||||
{
|
||||
X = v.X;
|
||||
Y = v.Y;
|
||||
X = v.X;
|
||||
Y = v.Y;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -73,60 +78,14 @@ namespace OpenTK.Math
|
|||
/// <param name="v">The Vector4 to copy components from. Z and W are discarded.</param>
|
||||
public Vector2(Vector4 v)
|
||||
{
|
||||
X = v.X;
|
||||
Y = v.Y;
|
||||
X = v.X;
|
||||
Y = v.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Functions
|
||||
|
||||
#region public Vector2 Add(Vector2 right)
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given Vector2 to the current Vector2.
|
||||
/// </summary>
|
||||
/// <param name="right">The right operand of the addition.</param>
|
||||
/// <returns>The current Vector2, modified by the operation.</returns>
|
||||
public Vector2 Add(Vector2 right)
|
||||
{
|
||||
this.X = X + right.X;
|
||||
this.Y = Y + right.Y;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public Vector2 Sub(Vector2 right)
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given Vector2 from the current Vector2.
|
||||
/// </summary>
|
||||
/// <param name="right">The right operand of the subtraction.</param>
|
||||
/// <returns>The current Vector2, modified by the operation.</returns>
|
||||
public Vector2 Sub(Vector2 right)
|
||||
{
|
||||
this.X = X - right.X;
|
||||
this.Y = Y - right.Y;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public float Dot(Vector2 right)
|
||||
|
||||
/// <summary>
|
||||
/// Computes the dot product between the current Vector2 and the given Vector2.
|
||||
/// </summary>
|
||||
/// <param name="right">The right operand of the dot product.</param>
|
||||
/// <returns>A float containing the result of the operation.</returns>
|
||||
public float Dot(Vector2 right)
|
||||
{
|
||||
return X * right.X + Y * right.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public float Length
|
||||
|
||||
/// <summary>
|
||||
|
@ -136,10 +95,10 @@ namespace OpenTK.Math
|
|||
/// <seealso cref="LengthSquared"/>
|
||||
public float Length
|
||||
{
|
||||
get
|
||||
{
|
||||
return (float)System.Math.Sqrt(X * X + Y * Y);
|
||||
}
|
||||
get
|
||||
{
|
||||
return (float)System.Math.Sqrt(X * X + Y * Y);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -158,10 +117,10 @@ namespace OpenTK.Math
|
|||
/// <seealso cref="OpenTK.Math.FastSqrt"/>
|
||||
public float LengthFast
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1.0f / OpenTK.Math.Functions.InverseSqrtFast(X * X + Y * Y);
|
||||
}
|
||||
get
|
||||
{
|
||||
return 1.0f / OpenTK.Math.Functions.InverseSqrtFast(X * X + Y * Y);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -179,59 +138,53 @@ namespace OpenTK.Math
|
|||
/// <seealso cref="FastLength"/>
|
||||
public float LengthSquared
|
||||
{
|
||||
get
|
||||
{
|
||||
return X * X + Y * Y;
|
||||
}
|
||||
get
|
||||
{
|
||||
return X * X + Y * Y;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public Vector2 Normalize()
|
||||
#region public void Normalize()
|
||||
|
||||
/// <summary>
|
||||
/// Scales the Vector2 to unit length.
|
||||
/// </summary>
|
||||
/// <returns>The normalized version of the current vector.</returns>
|
||||
public Vector2 Normalize()
|
||||
public void Normalize()
|
||||
{
|
||||
float scale = 1.0f / this.Length;
|
||||
X *= scale;
|
||||
Y *= scale;
|
||||
return this;
|
||||
float scale = 1.0f / this.Length;
|
||||
X *= scale;
|
||||
Y *= scale;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public Vector2 NormalizeFast()
|
||||
#region public void NormalizeFast()
|
||||
|
||||
/// <summary>
|
||||
/// Scales the Vector2 to approximately unit length.
|
||||
/// </summary>
|
||||
/// <returns>The normalized version of the current vector.</returns>
|
||||
public Vector2 NormalizeFast()
|
||||
public void NormalizeFast()
|
||||
{
|
||||
float scale = Functions.InverseSqrtFast(X * X + Y * Y);
|
||||
X *= scale;
|
||||
Y *= scale;
|
||||
return this;
|
||||
float scale = Functions.InverseSqrtFast(X * X + Y * Y);
|
||||
X *= scale;
|
||||
Y *= scale;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public Vector2 Scale(float sx, float sy)
|
||||
#region public void Scale(float sx, float sy)
|
||||
|
||||
/// <summary>
|
||||
/// Scales the current Vector2 by the given amounts.
|
||||
/// </summary>
|
||||
/// <param name="sx">The scale of the X component.</param>
|
||||
/// <param name="sy">The scale of the Y component.</param>
|
||||
/// <returns>The current Vector2, scaled.</returns>
|
||||
public Vector2 Scale(float sx, float sy)
|
||||
public void Scale(float sx, float sy)
|
||||
{
|
||||
this.X = X * sx;
|
||||
this.Y = Y * sy;
|
||||
return this;
|
||||
this.X = X * sx;
|
||||
this.Y = Y * sy;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -240,35 +193,388 @@ namespace OpenTK.Math
|
|||
|
||||
#region Operator overloads
|
||||
|
||||
public static Vector2 operator +(Vector2 left, Vector2 right)
|
||||
{
|
||||
return new Vector2(left).Add(right);
|
||||
}
|
||||
public static Vector2 operator +(Vector2 left, Vector2 right)
|
||||
{
|
||||
left.X += right.X;
|
||||
left.Y += right.Y;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static Vector2 operator -(Vector2 left, Vector2 right)
|
||||
{
|
||||
return new Vector2(left).Sub(right);
|
||||
}
|
||||
public static Vector2 operator -(Vector2 left, Vector2 right)
|
||||
{
|
||||
left.X -= right.X;
|
||||
left.Y -= right.Y;
|
||||
return left;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
unsafe public static explicit operator float*(Vector2 v)
|
||||
{
|
||||
return &v.X;
|
||||
}
|
||||
public static Vector2 operator -(Vector2 vec)
|
||||
{
|
||||
vec.X = -vec.X;
|
||||
vec.Y = -vec.Y;
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static explicit operator IntPtr(Vector2 v)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (IntPtr)(&v.X);
|
||||
}
|
||||
}
|
||||
public static Vector2 operator *(Vector2 vec, float f)
|
||||
{
|
||||
vec.X *= f;
|
||||
vec.Y *= f;
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static Vector2 operator *(float f, Vector2 vec)
|
||||
{
|
||||
vec.X *= f;
|
||||
vec.Y *= f;
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static Vector2 operator /(Vector2 vec, float f)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
vec.X *= mult;
|
||||
vec.Y *= mult;
|
||||
return vec;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
unsafe public static explicit operator float*(Vector2 v)
|
||||
{
|
||||
return &v.X;
|
||||
}
|
||||
|
||||
public static explicit operator IntPtr(Vector2 v)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
return (IntPtr)(&v.X);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public override string ToString()
|
||||
#region Static functions
|
||||
|
||||
/// <summary>
|
||||
#region Add
|
||||
|
||||
/// <summary>
|
||||
/// Add two Vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>Result of addition</returns>
|
||||
public static Vector2 Add(Vector2 a, Vector2 b)
|
||||
{
|
||||
a.X += b.X;
|
||||
a.Y += b.Y;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add two Vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">Result of addition</param>
|
||||
public static void Add(ref Vector2 a, ref Vector2 b, out Vector2 result)
|
||||
{
|
||||
result.X = a.X + b.X;
|
||||
result.Y = a.Y + b.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sub
|
||||
|
||||
/// <summary>
|
||||
/// Subtract one Vector from another
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>Result of subtraction</returns>
|
||||
public static Vector2 Sub(Vector2 a, Vector2 b)
|
||||
{
|
||||
a.X -= b.X;
|
||||
a.Y -= b.Y;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtract one Vector from another
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">Result of subtraction</param>
|
||||
public static void Sub(ref Vector2 a, ref Vector2 b, out Vector2 result)
|
||||
{
|
||||
result.X = a.X - b.X;
|
||||
result.Y = a.Y - b.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mult
|
||||
|
||||
/// <summary>
|
||||
/// Multiply a vector and a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <returns>Result of the multiplication</returns>
|
||||
public static Vector2 Mult(Vector2 a, float f)
|
||||
{
|
||||
a.X *= f;
|
||||
a.Y *= f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply a vector and a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <param name="result">Result of the multiplication</param>
|
||||
public static void Mult(ref Vector2 a, float f, out Vector2 result)
|
||||
{
|
||||
result.X = a.X * f;
|
||||
result.Y = a.Y * f;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Div
|
||||
|
||||
/// <summary>
|
||||
/// Divide a vector by a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <returns>Result of the division</returns>
|
||||
public static Vector2 Div(Vector2 a, float f)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
a.X *= mult;
|
||||
a.Y *= mult;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divide a vector by a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <param name="result">Result of the division</param>
|
||||
public static void Div(ref Vector2 a, float f, out Vector2 result)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
result.X = a.X * mult;
|
||||
result.Y = a.Y * mult;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Min
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise minimum</returns>
|
||||
public static Vector2 Min(Vector2 a, Vector2 b)
|
||||
{
|
||||
a.X = a.X < b.X ? a.X : b.X;
|
||||
a.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise minimum</param>
|
||||
public static void Min(ref Vector2 a, ref Vector2 b, out Vector2 result)
|
||||
{
|
||||
result.X = a.X < b.X ? a.X : b.X;
|
||||
result.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Max
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise maximum</returns>
|
||||
public static Vector2 Max(Vector2 a, Vector2 b)
|
||||
{
|
||||
a.X = a.X > b.X ? a.X : b.X;
|
||||
a.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise maximum</param>
|
||||
public static void Max(ref Vector2 a, ref Vector2 b, out Vector2 result)
|
||||
{
|
||||
result.X = a.X > b.X ? a.X : b.X;
|
||||
result.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Clamp
|
||||
|
||||
/// <summary>
|
||||
/// Clamp a vector to the given minimum and maximum vectors
|
||||
/// </summary>
|
||||
/// <param name="vec">Input vector</param>
|
||||
/// <param name="min">Minimum vector</param>
|
||||
/// <param name="max">Maximum vector</param>
|
||||
/// <returns>The clamped vector</returns>
|
||||
public static Vector2 Clamp(Vector2 vec, Vector2 min, Vector2 max)
|
||||
{
|
||||
vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
|
||||
vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamp a vector to the given minimum and maximum vectors
|
||||
/// </summary>
|
||||
/// <param name="vec">Input vector</param>
|
||||
/// <param name="min">Minimum vector</param>
|
||||
/// <param name="max">Maximum vector</param>
|
||||
/// <param name="result">The clamped vector</param>
|
||||
public static void Clamp(ref Vector2 vec, ref Vector2 min, ref Vector2 max, out Vector2 result)
|
||||
{
|
||||
result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
|
||||
result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Normalize
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <returns>The normalized vector</returns>
|
||||
public static Vector2 Normalize(Vector2 vec)
|
||||
{
|
||||
float scale = 1.0f / vec.Length;
|
||||
vec.X *= scale;
|
||||
vec.Y *= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <param name="result">The normalized vector</param>
|
||||
public static void Normalize(ref Vector2 vec, out Vector2 result)
|
||||
{
|
||||
float scale = 1.0f / vec.Length;
|
||||
result.X = vec.X * scale;
|
||||
result.Y = vec.Y * scale;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region NormalizeFast
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to approximately unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <returns>The normalized vector</returns>
|
||||
public static Vector2 NormalizeFast(Vector2 vec)
|
||||
{
|
||||
float scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
|
||||
vec.X *= scale;
|
||||
vec.Y *= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to approximately unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <param name="result">The normalized vector</param>
|
||||
public static void NormalizeFast(ref Vector2 vec, out Vector2 result)
|
||||
{
|
||||
float scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y);
|
||||
result.X = vec.X * scale;
|
||||
result.Y = vec.Y * scale;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dot
|
||||
|
||||
/// <summary>
|
||||
/// Caclulate the dot (scalar) product of two vectors
|
||||
/// </summary>
|
||||
/// <param name="left">First operand</param>
|
||||
/// <param name="right">Second operand</param>
|
||||
/// <returns>The dot product of the two inputs</returns>
|
||||
public static float Dot(Vector2 left, Vector2 right)
|
||||
{
|
||||
return left.X * right.X + left.Y * right.Y;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lerp
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new Vector that is the linear blend of the 2 given Vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First input vector</param>
|
||||
/// <param name="b">Second input vector</param>
|
||||
/// <param name="blend">The blend factor</param>
|
||||
/// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
|
||||
public static Vector2 Lerp(Vector2 a, Vector2 b, float blend)
|
||||
{
|
||||
a.X = blend * (b.X - a.X) + a.X;
|
||||
a.Y = blend * (b.Y - a.Y) + a.Y;
|
||||
return a;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Barycentric
|
||||
|
||||
/// <summary>
|
||||
/// Interpolate 3 Vectors using Barycentric coordinates
|
||||
/// </summary>
|
||||
/// <param name="a">First input Vector</param>
|
||||
/// <param name="b">Second input Vector</param>
|
||||
/// <param name="c">Third input Vector</param>
|
||||
/// <param name="u">First Barycentric Coordinate</param>
|
||||
/// <param name="v">Second Barycentric Coordinate</param>
|
||||
/// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
|
||||
public static Vector2 BaryCentric(Vector2 a, Vector2 b, Vector2 c, float u, float v)
|
||||
{
|
||||
return a + u * (b - a) + v * (c - a);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region public override string ToString()
|
||||
|
||||
/// <summary>
|
||||
/// Returns a System.String that represents the current Vector2.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#region --- License ---
|
||||
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
|
||||
* Contributions by Andy Gill.
|
||||
* See license.txt for license info
|
||||
*/
|
||||
#endregion
|
||||
|
@ -11,45 +12,50 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace OpenTK.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a three-dimensional vector.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Vector3
|
||||
{
|
||||
#region Fields
|
||||
/// <summary>
|
||||
/// Represents a three-dimensional vector.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct Vector3
|
||||
{
|
||||
#region Fields
|
||||
|
||||
/// <summary>
|
||||
/// The X component of the Vector3.
|
||||
/// </summary>
|
||||
public float X;
|
||||
/// <summary>
|
||||
/// The X component of the Vector3.
|
||||
/// </summary>
|
||||
public float X;
|
||||
|
||||
/// <summary>
|
||||
/// The Y component of the Vector3.
|
||||
/// </summary>
|
||||
public float Y;
|
||||
/// <summary>
|
||||
/// The Y component of the Vector3.
|
||||
/// </summary>
|
||||
public float Y;
|
||||
|
||||
/// <summary>
|
||||
/// The Z component of the Vector3.
|
||||
/// </summary>
|
||||
public float Z;
|
||||
/// <summary>
|
||||
/// The Z component of the Vector3.
|
||||
/// </summary>
|
||||
public float Z;
|
||||
|
||||
public static Vector3 UnitX = new Vector3(1, 0, 0);
|
||||
public static Vector3 UnitY = new Vector3(0, 1, 0);
|
||||
public static Vector3 UnitZ = new Vector3(0, 0, 1);
|
||||
public static Vector3 Zero = new Vector3(0, 0, 0);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new Vector3.
|
||||
/// </summary>
|
||||
/// <param name="x">The x component of the Vector3.</param>
|
||||
/// <param name="y">The y component of the Vector3.</param>
|
||||
/// <param name="z">The z component of the Vector3.</param>
|
||||
public Vector3(float x, float y, float z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
/// <summary>
|
||||
/// Constructs a new Vector3.
|
||||
/// </summary>
|
||||
/// <param name="x">The x component of the Vector3.</param>
|
||||
/// <param name="y">The y component of the Vector3.</param>
|
||||
/// <param name="z">The z component of the Vector3.</param>
|
||||
public Vector3(float x, float y, float z)
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new Vector3 from the given Vector2.
|
||||
|
@ -88,75 +94,6 @@ namespace OpenTK.Math
|
|||
|
||||
#region Functions
|
||||
|
||||
#region public Vector3 Add(Vector3 right)
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given Vector3 to the current Vector3.
|
||||
/// </summary>
|
||||
/// <param name="right">The right operand of the addition.</param>
|
||||
/// <returns>The current Vector3, containing the result of the addition.</returns>
|
||||
public Vector3 Add(Vector3 right)
|
||||
{
|
||||
X += right.X;
|
||||
Y += right.Y;
|
||||
Z += right.Z;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public Vector3 Sub(Vector3 right)
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given Vector3 from the current Vector3.
|
||||
/// </summary>
|
||||
/// <param name="right">The right operand of the subtraction.</param>
|
||||
/// <returns>A new Vector3 containing the result of the subtraction.</returns>
|
||||
public Vector3 Sub(Vector3 right)
|
||||
{
|
||||
X -= right.X;
|
||||
Y -= right.Y;
|
||||
Z -= right.Z;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public float Dot(Vector3 right)
|
||||
|
||||
/// <summary>
|
||||
/// Computes the dot product between the current Vector3 and the given Vector3.
|
||||
/// </summary>
|
||||
/// <param name="right">The right operand of the dot product.</param>
|
||||
/// <returns>A float containing the result of the dot product.</returns>
|
||||
public float Dot(Vector3 right)
|
||||
{
|
||||
return X * right.X + Y * right.Y + Z * right.Z;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public Vector3 Cross(Vector3 right)
|
||||
|
||||
/// <summary>
|
||||
/// Computes the cross product between the current and the given Vector3. The current Vector3 is set to the result of the computation.
|
||||
/// </summary>
|
||||
/// <param name="right">The right operand of the cross product</param>
|
||||
/// <returns>The current </returns>
|
||||
public Vector3 Cross(Vector3 right)
|
||||
{
|
||||
float
|
||||
x = Y * right.Z - Z * right.Y,
|
||||
y = Z * right.X - X * right.Z,
|
||||
z = X * right.Y - Y * right.X;
|
||||
X = x;
|
||||
Y = y;
|
||||
Z = z;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public float Length
|
||||
|
||||
/// <summary>
|
||||
|
@ -222,14 +159,12 @@ namespace OpenTK.Math
|
|||
/// <summary>
|
||||
/// Scales the Vector3 to unit length.
|
||||
/// </summary>
|
||||
/// <returns>The normalized version of the current vector.</returns>
|
||||
public Vector3 Normalize()
|
||||
public void Normalize()
|
||||
{
|
||||
float scale = 1.0f / this.Length;
|
||||
X *= scale;
|
||||
Y *= scale;
|
||||
Z *= scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -239,14 +174,12 @@ namespace OpenTK.Math
|
|||
/// <summary>
|
||||
/// Scales the Vector3 to approximately unit length.
|
||||
/// </summary>
|
||||
/// <returns>The normalized version of the current vector.</returns>
|
||||
public Vector3 NormalizeFast()
|
||||
public void NormalizeFast()
|
||||
{
|
||||
float scale = Functions.InverseSqrtFast(X * X + Y * Y + Z * Z);
|
||||
X *= scale;
|
||||
Y *= scale;
|
||||
Z *= scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -259,13 +192,11 @@ namespace OpenTK.Math
|
|||
/// <param name="sx">The scale of the X component.</param>
|
||||
/// <param name="sy">The scale of the Y component.</param>
|
||||
/// <param name="sz">The scale of the Z component.</param>
|
||||
/// <returns>The current Vector3, scaled.</returns>
|
||||
public Vector3 Scale(float sx, float sy, float sz)
|
||||
public void Scale(float sx, float sy, float sz)
|
||||
{
|
||||
this.X = X * sx;
|
||||
this.Y = Y * sy;
|
||||
this.Z = Z * sz;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -276,14 +207,53 @@ namespace OpenTK.Math
|
|||
|
||||
public static Vector3 operator +(Vector3 left, Vector3 right)
|
||||
{
|
||||
return new Vector3(left.Add(right));
|
||||
left.X += right.X;
|
||||
left.Y += right.Y;
|
||||
left.Z += right.Z;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static Vector3 operator -(Vector3 left, Vector3 right)
|
||||
{
|
||||
return new Vector3(left.Sub(right));
|
||||
left.X -= right.X;
|
||||
left.Y -= right.Y;
|
||||
left.Z -= right.Z;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static Vector3 operator -(Vector3 vec)
|
||||
{
|
||||
vec.X = -vec.X;
|
||||
vec.Y = -vec.Y;
|
||||
vec.Z = -vec.Z;
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static Vector3 operator *(Vector3 vec, float f)
|
||||
{
|
||||
vec.X *= f;
|
||||
vec.Y *= f;
|
||||
vec.Z *= f;
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static Vector3 operator *(float f, Vector3 vec)
|
||||
{
|
||||
vec.X *= f;
|
||||
vec.Y *= f;
|
||||
vec.Z *= f;
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static Vector3 operator /(Vector3 vec, float f)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
vec.X *= mult;
|
||||
vec.Y *= mult;
|
||||
vec.Z *= mult;
|
||||
return vec;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
unsafe public static explicit operator float*(Vector3 v)
|
||||
{
|
||||
|
@ -302,11 +272,477 @@ namespace OpenTK.Math
|
|||
|
||||
#region Static functions
|
||||
|
||||
#endregion
|
||||
#region Add
|
||||
|
||||
public override string ToString()
|
||||
/// <summary>
|
||||
/// Add two Vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>Result of addition</returns>
|
||||
public static Vector3 Add(Vector3 a, Vector3 b)
|
||||
{
|
||||
a.X += b.X;
|
||||
a.Y += b.Y;
|
||||
a.Z += b.Z;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add two Vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">Result of addition</param>
|
||||
public static void Add(ref Vector3 a, ref Vector3 b, out Vector3 result)
|
||||
{
|
||||
result.X = a.X + b.X;
|
||||
result.Y = a.Y + b.Y;
|
||||
result.Z = a.Z + b.Z;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sub
|
||||
|
||||
/// <summary>
|
||||
/// Subtract one Vector from another
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>Result of subtraction</returns>
|
||||
public static Vector3 Sub(Vector3 a, Vector3 b)
|
||||
{
|
||||
a.X -= b.X;
|
||||
a.Y -= b.Y;
|
||||
a.Z -= b.Z;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtract one Vector from another
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">Result of subtraction</param>
|
||||
public static void Sub(ref Vector3 a, ref Vector3 b, out Vector3 result)
|
||||
{
|
||||
result.X = a.X - b.X;
|
||||
result.Y = a.Y - b.Y;
|
||||
result.Z = a.Z - b.Z;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mult
|
||||
|
||||
/// <summary>
|
||||
/// Multiply a vector and a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <returns>Result of the multiplication</returns>
|
||||
public static Vector3 Mult(Vector3 a, float f)
|
||||
{
|
||||
a.X *= f;
|
||||
a.Y *= f;
|
||||
a.Z *= f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply a vector and a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <param name="result">Result of the multiplication</param>
|
||||
public static void Mult(ref Vector3 a, float f, out Vector3 result)
|
||||
{
|
||||
result.X = a.X * f;
|
||||
result.Y = a.Y * f;
|
||||
result.Z = a.Z * f;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Div
|
||||
|
||||
/// <summary>
|
||||
/// Divide a vector by a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <returns>Result of the division</returns>
|
||||
public static Vector3 Div(Vector3 a, float f)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
a.X *= mult;
|
||||
a.Y *= mult;
|
||||
a.Z *= mult;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divide a vector by a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <param name="result">Result of the division</param>
|
||||
public static void Div(ref Vector3 a, float f, out Vector3 result)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
result.X = a.X * mult;
|
||||
result.Y = a.Y * mult;
|
||||
result.Z = a.Z * mult;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Min
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise minimum</returns>
|
||||
public static Vector3 Min(Vector3 a, Vector3 b)
|
||||
{
|
||||
a.X = a.X < b.X ? a.X : b.X;
|
||||
a.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
a.Z = a.Z < b.Z ? a.Z : b.Z;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise minimum</param>
|
||||
public static void Min(ref Vector3 a, ref Vector3 b, out Vector3 result)
|
||||
{
|
||||
result.X = a.X < b.X ? a.X : b.X;
|
||||
result.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
result.Z = a.Z < b.Z ? a.Z : b.Z;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Max
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise maximum</returns>
|
||||
public static Vector3 Max(Vector3 a, Vector3 b)
|
||||
{
|
||||
a.X = a.X > b.X ? a.X : b.X;
|
||||
a.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
a.Z = a.Z > b.Z ? a.Z : b.Z;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise maximum</param>
|
||||
public static void Max(ref Vector3 a, ref Vector3 b, out Vector3 result)
|
||||
{
|
||||
result.X = a.X > b.X ? a.X : b.X;
|
||||
result.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
result.Z = a.Z > b.Z ? a.Z : b.Z;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Clamp
|
||||
|
||||
/// <summary>
|
||||
/// Clamp a vector to the given minimum and maximum vectors
|
||||
/// </summary>
|
||||
/// <param name="vec">Input vector</param>
|
||||
/// <param name="min">Minimum vector</param>
|
||||
/// <param name="max">Maximum vector</param>
|
||||
/// <returns>The clamped vector</returns>
|
||||
public static Vector3 Clamp(Vector3 vec, Vector3 min, Vector3 max)
|
||||
{
|
||||
vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
|
||||
vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
|
||||
vec.Z = vec.Z < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamp a vector to the given minimum and maximum vectors
|
||||
/// </summary>
|
||||
/// <param name="vec">Input vector</param>
|
||||
/// <param name="min">Minimum vector</param>
|
||||
/// <param name="max">Maximum vector</param>
|
||||
/// <param name="result">The clamped vector</param>
|
||||
public static void Clamp(ref Vector3 vec, ref Vector3 min, ref Vector3 max, out Vector3 result)
|
||||
{
|
||||
result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
|
||||
result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
|
||||
result.Z = vec.Z < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Normalize
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <returns>The normalized vector</returns>
|
||||
public static Vector3 Normalize(Vector3 vec)
|
||||
{
|
||||
float scale = 1.0f / vec.Length;
|
||||
vec.X *= scale;
|
||||
vec.Y *= scale;
|
||||
vec.Z *= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <param name="result">The normalized vector</param>
|
||||
public static void Normalize(ref Vector3 vec, out Vector3 result)
|
||||
{
|
||||
float scale = 1.0f / vec.Length;
|
||||
result.X = vec.X * scale;
|
||||
result.Y = vec.Y * scale;
|
||||
result.Z = vec.Z * scale;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region NormalizeFast
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to approximately unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <returns>The normalized vector</returns>
|
||||
public static Vector3 NormalizeFast(Vector3 vec)
|
||||
{
|
||||
float scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z);
|
||||
vec.X *= scale;
|
||||
vec.Y *= scale;
|
||||
vec.Z *= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to approximately unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <param name="result">The normalized vector</param>
|
||||
public static void NormalizeFast(ref Vector3 vec, out Vector3 result)
|
||||
{
|
||||
float scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z);
|
||||
result.X = vec.X * scale;
|
||||
result.Y = vec.Y * scale;
|
||||
result.Z = vec.Z * scale;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dot
|
||||
|
||||
/// <summary>
|
||||
/// Caclulate the dot (scalar) product of two vectors
|
||||
/// </summary>
|
||||
/// <param name="left">First operand</param>
|
||||
/// <param name="right">Second operand</param>
|
||||
/// <returns>The dot product of the two inputs</returns>
|
||||
public static float Dot(Vector3 left, Vector3 right)
|
||||
{
|
||||
return left.X * right.X + left.Y * right.Y + left.Z * right.Z;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Cross
|
||||
|
||||
/// <summary>
|
||||
/// Caclulate the cross (vector) product of two vectors
|
||||
/// </summary>
|
||||
/// <param name="left">First operand</param>
|
||||
/// <param name="right">Second operand</param>
|
||||
/// <returns>The cross product of the two inputs</returns>
|
||||
public static Vector3 Cross(Vector3 left, Vector3 right)
|
||||
{
|
||||
float
|
||||
x = left.Y * right.Z - left.Z * right.Y,
|
||||
y = left.Z * right.X - left.X * right.Z,
|
||||
z = left.X * right.Y - left.Y * right.X;
|
||||
left.X = x;
|
||||
left.Y = y;
|
||||
left.Z = z;
|
||||
return left;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caclulate the cross (vector) product of two vectors
|
||||
/// </summary>
|
||||
/// <param name="left">First operand</param>
|
||||
/// <param name="right">Second operand</param>
|
||||
/// <returns>The cross product of the two inputs</returns>
|
||||
/// <param name="result">The cross product of the two inputs</param>
|
||||
public static void Cross(ref Vector3 left, ref Vector3 right, out Vector3 result)
|
||||
{
|
||||
result.X = left.Y * right.Z - left.Z * right.Y;
|
||||
result.Y = left.Z * right.X - left.X * right.Z;
|
||||
result.Z = left.X * right.Y - left.Y * right.X;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lerp
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new Vector that is the linear blend of the 2 given Vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First input vector</param>
|
||||
/// <param name="b">Second input vector</param>
|
||||
/// <param name="blend">The blend factor</param>
|
||||
/// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
|
||||
public static Vector3 Lerp(Vector3 a, Vector3 b, float blend)
|
||||
{
|
||||
a.X = blend * (b.X - a.X) + a.X;
|
||||
a.Y = blend * (b.Y - a.Y) + a.Y;
|
||||
a.Z = blend * (b.Z - a.Z) + a.Z;
|
||||
return a;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Barycentric
|
||||
|
||||
/// <summary>
|
||||
/// Interpolate 3 Vectors using Barycentric coordinates
|
||||
/// </summary>
|
||||
/// <param name="a">First input Vector</param>
|
||||
/// <param name="b">Second input Vector</param>
|
||||
/// <param name="c">Third input Vector</param>
|
||||
/// <param name="u">First Barycentric Coordinate</param>
|
||||
/// <param name="v">Second Barycentric Coordinate</param>
|
||||
/// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
|
||||
public static Vector3 BaryCentric(Vector3 a, Vector3 b, Vector3 c, float u, float v)
|
||||
{
|
||||
return a + u * (b - a) + v * (c - a);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Transform
|
||||
|
||||
/// <summary>
|
||||
/// Transform a direction vector by the given Matrix
|
||||
/// Assumes the matrix has a bottom row of (0,0,0,1), that is the translation part is ignored.
|
||||
/// </summary>
|
||||
/// <param name="vec">The vector to transform</param>
|
||||
/// <param name="mat">The desired transformation</param>
|
||||
/// <returns>The transformed vector</returns>
|
||||
public static Vector3 TransformVector(Vector3 vec, Matrix4 mat)
|
||||
{
|
||||
Vector3 v;
|
||||
v.X = Vector3.Dot(vec, new Vector3(mat.Column0));
|
||||
v.Y = Vector3.Dot(vec, new Vector3(mat.Column1));
|
||||
v.Z = Vector3.Dot(vec, new Vector3(mat.Column2));
|
||||
return v;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform a Normal by the given Matrix
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This calculates the inverse of the given matrix, use TransformNormalInverse if you
|
||||
/// already have the inverse to avoid this extra calculation
|
||||
/// </remarks>
|
||||
/// <param name="norm">The normal to transform</param>
|
||||
/// <param name="mat">The desired transformation</param>
|
||||
/// <returns>The transformed normal</returns>
|
||||
public static Vector3 TransformNormal(Vector3 norm, Matrix4 mat)
|
||||
{
|
||||
mat.Invert();
|
||||
return TransformNormalInverse(norm, mat);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform a Normal by the (transpose of the) given Matrix
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This version doesn't calculate the inverse matrix.
|
||||
/// Use this version if you already have the inverse of the desired transform to hand
|
||||
/// </remarks>
|
||||
/// <param name="norm">The normal to transform</param>
|
||||
/// <param name="mat">The inverse of the desired transformation</param>
|
||||
/// <returns>The transformed normal</returns>
|
||||
public static Vector3 TransformNormalInverse(Vector3 norm, Matrix4 invMat)
|
||||
{
|
||||
Vector3 n;
|
||||
n.X = Vector3.Dot(norm, new Vector3(invMat.Row0));
|
||||
n.Y = Vector3.Dot(norm, new Vector3(invMat.Row1));
|
||||
n.Z = Vector3.Dot(norm, new Vector3(invMat.Row2));
|
||||
return n;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform a Position by the given Matrix
|
||||
/// </summary>
|
||||
/// <param name="pos">The position to transform</param>
|
||||
/// <param name="mat">The desired transformation</param>
|
||||
/// <returns>The transformed position</returns>
|
||||
public static Vector3 TransformPosition(Vector3 pos, Matrix4 mat)
|
||||
{
|
||||
Vector3 p;
|
||||
p.X = Vector3.Dot(pos, new Vector3(mat.Column0)) + mat.Row3.X;
|
||||
p.Y = Vector3.Dot(pos, new Vector3(mat.Column1)) + mat.Row3.Y;
|
||||
p.Z = Vector3.Dot(pos, new Vector3(mat.Column2)) + mat.Row3.Z;
|
||||
return p;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transform a Vector by the given Matrix
|
||||
/// </summary>
|
||||
/// <param name="pos">The vector to transform</param>
|
||||
/// <param name="mat">The desired transformation</param>
|
||||
/// <returns>The transformed vector</returns>
|
||||
public static Vector4 Transform(Vector3 vec, Matrix4 mat)
|
||||
{
|
||||
Vector4 v4 = new Vector4(vec.X, vec.Y, vec.Z, 1.0f);
|
||||
Vector4 result;
|
||||
result.X = Vector4.Dot(v4, mat.Column0);
|
||||
result.Y = Vector4.Dot(v4, mat.Column1);
|
||||
result.Z = Vector4.Dot(v4, mat.Column2);
|
||||
result.W = Vector4.Dot(v4, mat.Column3);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region public override string ToString()
|
||||
|
||||
/// <summary>
|
||||
/// Returns a System.String that represents the current Vector3.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("({0}, {1}, {2})", X, Y, Z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#region --- License ---
|
||||
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
|
||||
* Contributions by Andy Gill.
|
||||
* See license.txt for license info
|
||||
*/
|
||||
#endregion
|
||||
|
@ -39,6 +40,12 @@ namespace OpenTK.Math
|
|||
/// </summary>
|
||||
public float W;
|
||||
|
||||
public static Vector4 UnitX = new Vector4(1, 0, 0, 0);
|
||||
public static Vector4 UnitY = new Vector4(0, 1, 0, 0);
|
||||
public static Vector4 UnitZ = new Vector4(0, 0, 1, 0);
|
||||
public static Vector4 UnitW = new Vector4(0, 0, 0, 1);
|
||||
public static Vector4 Zero = new Vector4(0, 0, 0, 0);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
@ -98,56 +105,6 @@ namespace OpenTK.Math
|
|||
|
||||
#region Functions
|
||||
|
||||
#region public Vector4 Add(Vector4 right)
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given Vector4 to the current Vector4. W-coordinate remains unaffected.
|
||||
/// </summary>
|
||||
/// <param name="right">The right operand of the addition.</param>
|
||||
/// <returns>A new Vector4 containing the result of the addition.</returns>
|
||||
public Vector4 Add(Vector4 right)
|
||||
{
|
||||
X += right.X;
|
||||
Y += right.Y;
|
||||
Z += right.Z;
|
||||
W += right.W;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public Vector4 Sub(Vector4 right)
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts the given Vector4 from the current Vector4.
|
||||
/// </summary>
|
||||
/// <param name="right">The right operand of the subtraction.</param>
|
||||
/// <returns>A new Vector4 containing the result of the subtraction.</returns>
|
||||
public Vector4 Sub(Vector4 right)
|
||||
{
|
||||
X -= right.X;
|
||||
Y -= right.Y;
|
||||
Z -= right.Z;
|
||||
W -= right.W;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public float Dot(Vector4 right)
|
||||
|
||||
/// <summary>
|
||||
/// Computes the dot product between the current Vector4 and the given Vector4.
|
||||
/// </summary>
|
||||
/// <param name="right">The right operand of the dot product.</param>
|
||||
/// <returns>A float containing the result of the dot product.</returns>
|
||||
public float Dot(Vector4 right)
|
||||
{
|
||||
return X * right.X + Y * right.Y + Z * right.Z + W * right.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public float Length
|
||||
|
||||
/// <summary>
|
||||
|
@ -208,43 +165,39 @@ namespace OpenTK.Math
|
|||
|
||||
#endregion
|
||||
|
||||
#region public Vector4 Normalize()
|
||||
#region public void Normalize()
|
||||
|
||||
/// <summary>
|
||||
/// Scales the Vector4 to unit length.
|
||||
/// </summary>
|
||||
/// <returns>The normalized version of the current vector.</returns>
|
||||
public Vector4 Normalize()
|
||||
public void Normalize()
|
||||
{
|
||||
float scale = 1.0f / this.Length;
|
||||
X *= scale;
|
||||
Y *= scale;
|
||||
Z *= scale;
|
||||
W *= scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public Vector4 NormalizeFast()
|
||||
#region public void NormalizeFast()
|
||||
|
||||
/// <summary>
|
||||
/// Scales the Vector4 to approximately unit length.
|
||||
/// </summary>
|
||||
/// <returns>The normalized version of the current vector.</returns>
|
||||
public Vector4 NormalizeFast()
|
||||
public void NormalizeFast()
|
||||
{
|
||||
float scale = Functions.InverseSqrtFast(X * X + Y * Y + Z * Z);
|
||||
float scale = Functions.InverseSqrtFast(X * X + Y * Y + Z * Z + W * W);
|
||||
X *= scale;
|
||||
Y *= scale;
|
||||
Z *= scale;
|
||||
W *= scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public Vector4 Scale(float sx, float sy, float sz, float sw)
|
||||
#region public void Scale(float sx, float sy, float sz, float sw)
|
||||
|
||||
/// <summary>
|
||||
/// Scales the current Vector4 by the given amounts.
|
||||
|
@ -253,11 +206,13 @@ namespace OpenTK.Math
|
|||
/// <param name="sy">The scale of the Y component.</param>
|
||||
/// <param name="sz">The scale of the Z component.</param>
|
||||
/// <param name="sw">The scale of the Z component.</param>
|
||||
/// <returns>The current Vector4, scaled.</returns>
|
||||
public Vector4 Scale(float sx, float sy, float sz, float sw)
|
||||
public void Scale(float sx, float sy, float sz, float sw)
|
||||
{
|
||||
return new Vector4(X * sx, Y * sy, Z * sz, W * sw);
|
||||
}
|
||||
this.X = X * sx;
|
||||
this.Y = Y * sy;
|
||||
this.Z = Z * sz;
|
||||
this.W = W * sw;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -267,14 +222,59 @@ namespace OpenTK.Math
|
|||
|
||||
public static Vector4 operator +(Vector4 left, Vector4 right)
|
||||
{
|
||||
return left.Add(right);
|
||||
left.X += right.X;
|
||||
left.Y += right.Y;
|
||||
left.Z += right.Z;
|
||||
left.W += right.W;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static Vector4 operator -(Vector4 left, Vector4 right)
|
||||
{
|
||||
return left.Sub(right);
|
||||
left.X -= right.X;
|
||||
left.Y -= right.Y;
|
||||
left.Z -= right.Z;
|
||||
left.W -= right.W;
|
||||
return left;
|
||||
}
|
||||
|
||||
public static Vector4 operator -(Vector4 vec)
|
||||
{
|
||||
vec.X = -vec.X;
|
||||
vec.Y = -vec.Y;
|
||||
vec.Z = -vec.Z;
|
||||
vec.W = -vec.W;
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static Vector4 operator *(Vector4 vec, float f)
|
||||
{
|
||||
vec.X *= f;
|
||||
vec.Y *= f;
|
||||
vec.Z *= f;
|
||||
vec.W *= f;
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static Vector4 operator *(float f, Vector4 vec)
|
||||
{
|
||||
vec.X *= f;
|
||||
vec.Y *= f;
|
||||
vec.Z *= f;
|
||||
vec.W *= f;
|
||||
return vec;
|
||||
}
|
||||
|
||||
public static Vector4 operator /(Vector4 vec, float f)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
vec.X *= mult;
|
||||
vec.Y *= mult;
|
||||
vec.Z *= mult;
|
||||
vec.W *= mult;
|
||||
return vec;
|
||||
}
|
||||
|
||||
[CLSCompliant(false)]
|
||||
unsafe public static explicit operator float*(Vector4 v)
|
||||
{
|
||||
|
@ -289,12 +289,397 @@ namespace OpenTK.Math
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
#region Static functions
|
||||
|
||||
#region Add
|
||||
|
||||
/// <summary>
|
||||
/// Add two Vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>Result of addition</returns>
|
||||
public static Vector4 Add(Vector4 a, Vector4 b)
|
||||
{
|
||||
a.X += b.X;
|
||||
a.Y += b.Y;
|
||||
a.Z += b.Z;
|
||||
a.W += b.W;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add two Vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">Result of addition</param>
|
||||
public static void Add(ref Vector4 a, ref Vector4 b, out Vector4 result)
|
||||
{
|
||||
result.X = a.X + b.X;
|
||||
result.Y = a.Y + b.Y;
|
||||
result.Z = a.Z + b.Z;
|
||||
result.W = a.W + b.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sub
|
||||
|
||||
/// <summary>
|
||||
/// Subtract one Vector from another
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>Result of subtraction</returns>
|
||||
public static Vector4 Sub(Vector4 a, Vector4 b)
|
||||
{
|
||||
a.X -= b.X;
|
||||
a.Y -= b.Y;
|
||||
a.Z -= b.Z;
|
||||
a.W -= b.W;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtract one Vector from another
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">Result of subtraction</param>
|
||||
public static void Sub(ref Vector4 a, ref Vector4 b, out Vector4 result)
|
||||
{
|
||||
result.X = a.X - b.X;
|
||||
result.Y = a.Y - b.Y;
|
||||
result.Z = a.Z - b.Z;
|
||||
result.W = a.W - b.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Mult
|
||||
|
||||
/// <summary>
|
||||
/// Multiply a vector and a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <returns>Result of the multiplication</returns>
|
||||
public static Vector4 Mult(Vector4 a, float f)
|
||||
{
|
||||
a.X *= f;
|
||||
a.Y *= f;
|
||||
a.Z *= f;
|
||||
a.W *= f;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Multiply a vector and a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <param name="result">Result of the multiplication</param>
|
||||
public static void Mult(ref Vector4 a, float f, out Vector4 result)
|
||||
{
|
||||
result.X = a.X * f;
|
||||
result.Y = a.Y * f;
|
||||
result.Z = a.Z * f;
|
||||
result.W = a.W * f;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Div
|
||||
|
||||
/// <summary>
|
||||
/// Divide a vector by a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <returns>Result of the division</returns>
|
||||
public static Vector4 Div(Vector4 a, float f)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
a.X *= mult;
|
||||
a.Y *= mult;
|
||||
a.Z *= mult;
|
||||
a.W *= mult;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Divide a vector by a scalar
|
||||
/// </summary>
|
||||
/// <param name="a">Vector operand</param>
|
||||
/// <param name="f">Scalar operand</param>
|
||||
/// <param name="result">Result of the division</param>
|
||||
public static void Div(ref Vector4 a, float f, out Vector4 result)
|
||||
{
|
||||
float mult = 1.0f / f;
|
||||
result.X = a.X * mult;
|
||||
result.Y = a.Y * mult;
|
||||
result.Z = a.Z * mult;
|
||||
result.W = a.W * mult;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Min
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise minimum</returns>
|
||||
public static Vector4 Min(Vector4 a, Vector4 b)
|
||||
{
|
||||
a.X = a.X < b.X ? a.X : b.X;
|
||||
a.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
a.Z = a.Z < b.Z ? a.Z : b.Z;
|
||||
a.W = a.W < b.W ? a.W : b.W;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise minimum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise minimum</param>
|
||||
public static void Min(ref Vector4 a, ref Vector4 b, out Vector4 result)
|
||||
{
|
||||
result.X = a.X < b.X ? a.X : b.X;
|
||||
result.Y = a.Y < b.Y ? a.Y : b.Y;
|
||||
result.Z = a.Z < b.Z ? a.Z : b.Z;
|
||||
result.W = a.W < b.W ? a.W : b.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Max
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <returns>The component-wise maximum</returns>
|
||||
public static Vector4 Max(Vector4 a, Vector4 b)
|
||||
{
|
||||
a.X = a.X > b.X ? a.X : b.X;
|
||||
a.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
a.Z = a.Z > b.Z ? a.Z : b.Z;
|
||||
a.W = a.W > b.W ? a.W : b.W;
|
||||
return a;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculate the component-wise maximum of two vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First operand</param>
|
||||
/// <param name="b">Second operand</param>
|
||||
/// <param name="result">The component-wise maximum</param>
|
||||
public static void Max(ref Vector4 a, ref Vector4 b, out Vector4 result)
|
||||
{
|
||||
result.X = a.X > b.X ? a.X : b.X;
|
||||
result.Y = a.Y > b.Y ? a.Y : b.Y;
|
||||
result.Z = a.Z > b.Z ? a.Z : b.Z;
|
||||
result.W = a.W > b.W ? a.W : b.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Clamp
|
||||
|
||||
/// <summary>
|
||||
/// Clamp a vector to the given minimum and maximum vectors
|
||||
/// </summary>
|
||||
/// <param name="vec">Input vector</param>
|
||||
/// <param name="min">Minimum vector</param>
|
||||
/// <param name="max">Maximum vector</param>
|
||||
/// <returns>The clamped vector</returns>
|
||||
public static Vector4 Clamp(Vector4 vec, Vector4 min, Vector4 max)
|
||||
{
|
||||
vec.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
|
||||
vec.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
|
||||
vec.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
|
||||
vec.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamp a vector to the given minimum and maximum vectors
|
||||
/// </summary>
|
||||
/// <param name="vec">Input vector</param>
|
||||
/// <param name="min">Minimum vector</param>
|
||||
/// <param name="max">Maximum vector</param>
|
||||
/// <param name="result">The clamped vector</param>
|
||||
public static void Clamp(ref Vector4 vec, ref Vector4 min, ref Vector4 max, out Vector4 result)
|
||||
{
|
||||
result.X = vec.X < min.X ? min.X : vec.X > max.X ? max.X : vec.X;
|
||||
result.Y = vec.Y < min.Y ? min.Y : vec.Y > max.Y ? max.Y : vec.Y;
|
||||
result.Z = vec.X < min.Z ? min.Z : vec.Z > max.Z ? max.Z : vec.Z;
|
||||
result.W = vec.Y < min.W ? min.W : vec.W > max.W ? max.W : vec.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Normalize
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <returns>The normalized vector</returns>
|
||||
public static Vector4 Normalize(Vector4 vec)
|
||||
{
|
||||
float scale = 1.0f / vec.Length;
|
||||
vec.X *= scale;
|
||||
vec.Y *= scale;
|
||||
vec.Z *= scale;
|
||||
vec.W *= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <param name="result">The normalized vector</param>
|
||||
public static void Normalize(ref Vector4 vec, out Vector4 result)
|
||||
{
|
||||
float scale = 1.0f / vec.Length;
|
||||
result.X = vec.X * scale;
|
||||
result.Y = vec.Y * scale;
|
||||
result.Z = vec.Z * scale;
|
||||
result.W = vec.W * scale;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region NormalizeFast
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to approximately unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <returns>The normalized vector</returns>
|
||||
public static Vector4 NormalizeFast(Vector4 vec)
|
||||
{
|
||||
float scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z + vec.W * vec.W);
|
||||
vec.X *= scale;
|
||||
vec.Y *= scale;
|
||||
vec.Z *= scale;
|
||||
vec.W *= scale;
|
||||
return vec;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scale a vector to approximately unit length
|
||||
/// </summary>
|
||||
/// <param name="vec">The input vector</param>
|
||||
/// <param name="result">The normalized vector</param>
|
||||
public static void NormalizeFast(ref Vector4 vec, out Vector4 result)
|
||||
{
|
||||
float scale = Functions.InverseSqrtFast(vec.X * vec.X + vec.Y * vec.Y + vec.Z * vec.Z + vec.W * vec.W);
|
||||
result.X = vec.X * scale;
|
||||
result.Y = vec.Y * scale;
|
||||
result.Z = vec.Z * scale;
|
||||
result.W = vec.W * scale;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Dot
|
||||
|
||||
/// <summary>
|
||||
/// Caclulate the dot product of two vectors
|
||||
/// </summary>
|
||||
/// <param name="left">First operand</param>
|
||||
/// <param name="right">Second operand</param>
|
||||
/// <returns>The dot product of the two inputs</returns>
|
||||
public static float Dot(Vector4 left, Vector4 right)
|
||||
{
|
||||
return left.X * right.X + left.Y * right.Y + left.Z * right.Z + left.W * right.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lerp
|
||||
|
||||
/// <summary>
|
||||
/// Returns a new Vector that is the linear blend of the 2 given Vectors
|
||||
/// </summary>
|
||||
/// <param name="a">First input vector</param>
|
||||
/// <param name="b">Second input vector</param>
|
||||
/// <param name="blend">The blend factor</param>
|
||||
/// <returns>a when blend=0, b when blend=1, and a linear combination otherwise</returns>
|
||||
public static Vector4 Lerp(Vector4 a, Vector4 b, float blend)
|
||||
{
|
||||
a.X = blend * (b.X - a.X) + a.X;
|
||||
a.Y = blend * (b.Y - a.Y) + a.Y;
|
||||
a.Z = blend * (b.Z - a.Z) + a.Z;
|
||||
a.W = blend * (b.W - a.W) + a.W;
|
||||
return a;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Barycentric
|
||||
|
||||
/// <summary>
|
||||
/// Interpolate 3 Vectors using Barycentric coordinates
|
||||
/// </summary>
|
||||
/// <param name="a">First input Vector</param>
|
||||
/// <param name="b">Second input Vector</param>
|
||||
/// <param name="c">Third input Vector</param>
|
||||
/// <param name="u">First Barycentric Coordinate</param>
|
||||
/// <param name="v">Second Barycentric Coordinate</param>
|
||||
/// <returns>a when u=v=0, b when u=1,v=0, c when u=0,v=1, and a linear combination of a,b,c otherwise</returns>
|
||||
public static Vector4 BaryCentric(Vector4 a, Vector4 b, Vector4 c, float u, float v)
|
||||
{
|
||||
return a + u * (b - a) + v * (c - a);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Transform
|
||||
|
||||
/// <summary>
|
||||
/// Transform a Vector by the given Matrix
|
||||
/// </summary>
|
||||
/// <param name="pos">The vector to transform</param>
|
||||
/// <param name="mat">The desired transformation</param>
|
||||
/// <returns>The transformed vector</returns>
|
||||
public static Vector4 Transform(Vector4 vec, Matrix4 mat)
|
||||
{
|
||||
Vector4 result;
|
||||
result.X = Vector4.Dot(vec, mat.Column0);
|
||||
result.Y = Vector4.Dot(vec, mat.Column1);
|
||||
result.Z = Vector4.Dot(vec, mat.Column2);
|
||||
result.W = Vector4.Dot(vec, mat.Column3);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region public override string ToString()
|
||||
|
||||
/// <summary>
|
||||
/// Returns a System.String that represents the current Vector4.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("({0}, {1}, {2}, {3})", X, Y, Z, W);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue