Changes suggested by Rob Rouhani

* Turned the new Matrix4 properties into methods
* Matrix4.Normalize() now behaves correctly. ExtractRotation() does its
own row normalisation.
This commit is contained in:
Tom Edwards 2013-03-19 15:28:31 +00:00
parent b20b21d228
commit 498b659d58

View file

@ -275,9 +275,11 @@ namespace OpenTK
/// </summary>
public void Normalize()
{
Row0.Xyz = Row0.Xyz.Normalized();
Row1.Xyz = Row1.Xyz.Normalized();
Row2.Xyz = Row2.Xyz.Normalized();
var determinant = this.Determinant;
Row0 /= determinant;
Row1 /= determinant;
Row2 /= determinant;
Row3 /= determinant;
}
/// <summary>
@ -292,72 +294,81 @@ namespace OpenTK
}
/// <summary>
/// Gets the translation component of this instance.
/// Returns the translation component of this instance.
/// </summary>
public Vector3 TranslationPart { get { return Row3.Xyz; } }
public Vector3 ExtractTranslation() { return Row3.Xyz; }
/// <summary>
/// Gets the scale component of this instance.
/// Returns the scale component of this instance.
/// </summary>
public Vector3 ScalePart { get { return new Vector3 (Row0.Length, Row1.Length, Row2.Length); } }
public Vector3 ExtractScale() { return new Vector3 (Row0.Length, Row1.Length, Row2.Length); }
/// <summary>
/// Gets the rotation component of this instance. The Matrix MUST be normalized first.
/// Returns the rotation component of this instance. Quite slow.
/// </summary>
public Quaternion RotationPart
/// <param name="row_normalise">Whether the method should operate on a row-normalised (i.e. scale == 1) version of the Matrix. Pass false if you know it's already normalised.</param>
public Quaternion ExtractRotation(bool row_normalise = true)
{
get
var row0 = Row0.Xyz;
var row1 = Row1.Xyz;
var row2 = Row2.Xyz;
if (row_normalise)
{
if (row0.LengthSquared != 1) row0 = row0.Normalized();
if (row1.LengthSquared != 1) row1 = row1.Normalized();
if (row2.LengthSquared != 1) row2 = row2.Normalized();
}
// code below adapted from Blender
Quaternion q = new Quaternion();
double trace = 0.25 * (row0[0] + row1[1] + row2[2] + 1.0);
// Adapted from Blender
double trace = 0.25 * (Row0[0] + Row1[1] + Row2[2] + 1.0);
if (trace > 0.0f)
if (trace > 0)
{
double sq = Math.Sqrt(trace);
q.W = (float)sq;
sq = 1.0 / (4.0 * sq);
q.X = (float)((Row1[2] - Row2[1]) * sq);
q.Y = (float)((Row2[0] - Row0[2]) * sq);
q.Z = (float)((Row0[1] - Row1[0]) * sq);
q.X = (float)((row1[2] - row2[1]) * sq);
q.Y = (float)((row2[0] - row0[2]) * sq);
q.Z = (float)((row0[1] - row1[0]) * sq);
}
else if (Row0[0] > Row1[1] && Row0[0] > Row2[2])
else if (row0[0] > row1[1] && row0[0] > row2[2])
{
double sq = 2.0 * Math.Sqrt(1.0 + Row0[0] - Row1[1] - Row2[2]);
double sq = 2.0 * Math.Sqrt(1.0 + row0[0] - row1[1] - row2[2]);
q.X = (float)(0.25 * sq);
sq = 1.0 / sq;
q.W = (float)((Row2[1] - Row1[2]) * sq);
q.Y = (float)((Row1[0] + Row0[1]) * sq);
q.Z = (float)((Row2[0] + Row0[2]) * sq);
q.W = (float)((row2[1] - row1[2]) * sq);
q.Y = (float)((row1[0] + row0[1]) * sq);
q.Z = (float)((row2[0] + row0[2]) * sq);
}
else if (Row1[1] > Row2[2])
else if (row1[1] > row2[2])
{
double sq = 2.0 * Math.Sqrt(1.0 + Row1[1] - Row0[0] - Row2[2]);
double sq = 2.0 * Math.Sqrt(1.0 + row1[1] - row0[0] - row2[2]);
q.Y = (float)(0.25 * sq);
sq = 1.0 / sq;
q.W = (float)((Row2[0] - Row0[2]) * sq);
q.X = (float)((Row1[0] + Row0[1]) * sq);
q.Z = (float)((Row2[1] + Row1[2]) * sq);
q.W = (float)((row2[0] - row0[2]) * sq);
q.X = (float)((row1[0] + row0[1]) * sq);
q.Z = (float)((row2[1] + row1[2]) * sq);
}
else
{
double sq = 2.0 * Math.Sqrt(1.0 + Row2[2] - Row0[0] - Row1[1]);
double sq = 2.0 * Math.Sqrt(1.0 + row2[2] - row0[0] - row1[1]);
q.Z = (float)(0.25 * sq);
sq = 1.0 / sq;
q.W = (float)((Row1[0] - Row0[1]) * sq);
q.X = (float)((Row2[0] + Row0[2]) * sq);
q.Y = (float)((Row2[1] + Row1[2]) * sq);
q.W = (float)((row1[0] - row0[1]) * sq);
q.X = (float)((row2[0] + row0[2]) * sq);
q.Y = (float)((row2[1] + row1[2]) * sq);
}
q.Normalize();
return q;
}
}
#endregion