233 lines
7.8 KiB
C#
233 lines
7.8 KiB
C#
using System;
|
|
|
|
namespace BasicGeometry
|
|
{
|
|
public struct QuaternionFP32
|
|
{
|
|
public float s0 = 0.0f, x1 = 0.0f, x2 = 0.0f, x3 = 0.0f;
|
|
|
|
public QuaternionFP32(float s0, float x1, float x2, float x3)
|
|
{
|
|
this.s0 = s0;
|
|
this.x1 = x1;
|
|
this.x2 = x2;
|
|
this.x3 = x3;
|
|
}
|
|
|
|
public QuaternionFP32(in QuaternionFP32 quaternion)
|
|
{
|
|
this.s0 = quaternion.s0;
|
|
this.x1 = quaternion.x1;
|
|
this.x2 = quaternion.x2;
|
|
this.x3 = quaternion.x3;
|
|
}
|
|
|
|
public QuaternionFP32(in QuaternionFP64 quaternion)
|
|
{
|
|
this.s0 = (float)quaternion.s0;
|
|
this.x1 = (float)quaternion.x1;
|
|
this.x2 = (float)quaternion.x2;
|
|
this.x3 = (float)quaternion.x3;
|
|
}
|
|
|
|
public readonly float GetSquareModulus()
|
|
{
|
|
return this.s0 * this.s0 + this.x1 * this.x1 + (this.x2 * this.x2 + this.x3 * this.x3);
|
|
}
|
|
|
|
public readonly float GetModulus()
|
|
{
|
|
return MathF.Sqrt(this.GetSquareModulus());
|
|
}
|
|
|
|
public readonly bool IsZero()
|
|
{
|
|
return this.GetSquareModulus() <= UtilityFP32.SQUARE_EPSYLON;
|
|
}
|
|
|
|
public readonly bool IsUnit()
|
|
{
|
|
return UtilityFP32.IsSqareUnit(this.GetSquareModulus());
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
this.s0 = 0.0f;
|
|
this.x1 = 0.0f;
|
|
this.x2 = 0.0f;
|
|
this.x3 = 0.0f;
|
|
}
|
|
|
|
public void SetToIdentity()
|
|
{
|
|
this.s0 = 1.0f;
|
|
this.x1 = 0.0f;
|
|
this.x2 = 0.0f;
|
|
this.x3 = 0.0f;
|
|
}
|
|
|
|
public void Conjugate()
|
|
{
|
|
this.x1 = -this.x1;
|
|
this.x2 = -this.x2;
|
|
this.x3 = -this.x3;
|
|
}
|
|
|
|
public void SetValues(float s0, float x1, float x2, float x3)
|
|
{
|
|
this.s0 = s0;
|
|
this.x1 = x1;
|
|
this.x2 = x2;
|
|
this.x3 = x3;
|
|
}
|
|
|
|
public void Set(in QuaternionFP32 quaternion)
|
|
{
|
|
this.s0 = quaternion.s0;
|
|
this.x1 = quaternion.x1;
|
|
this.x2 = quaternion.x2;
|
|
this.x3 = quaternion.x3;
|
|
}
|
|
|
|
public void SetValues(in QuaternionFP64 quaternion)
|
|
{
|
|
this.s0 = (float)quaternion.s0;
|
|
this.x1 = (float)quaternion.x1;
|
|
this.x2 = (float)quaternion.x2;
|
|
this.x3 = (float)quaternion.x3;
|
|
}
|
|
|
|
public static void MakeConjugate(in QuaternionFP32 quaternion, out QuaternionFP32 conjugate)
|
|
{
|
|
conjugate.s0 = quaternion.s0;
|
|
conjugate.x1 = -quaternion.x1;
|
|
conjugate.x2 = -quaternion.x2;
|
|
conjugate.x3 = -quaternion.x3;
|
|
}
|
|
|
|
public readonly void MakeRotationMatrix(out Matrix3x3FP32 matrix)
|
|
{
|
|
float s0s0 = this.s0 * this.s0;
|
|
float x1x1 = this.x1 * this.x1;
|
|
float x2x2 = this.x2 * this.x2;
|
|
float x3x3 = this.x3 * this.x3;
|
|
|
|
float squareModulus = (s0s0 + x1x1) + (x2x2 + x3x3);
|
|
|
|
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON)
|
|
{
|
|
Matrix3x3FP32.LoadIdentity(out matrix);
|
|
return;
|
|
}
|
|
|
|
float corrector1 = 1.0f / squareModulus;
|
|
|
|
float s0x1 = this.s0 * this.x1;
|
|
float s0x2 = this.s0 * this.x2;
|
|
float s0x3 = this.s0 * this.x3;
|
|
float x1x2 = this.x1 * this.x2;
|
|
float x1x3 = this.x1 * this.x3;
|
|
float x2x3 = this.x2 * this.x3;
|
|
|
|
float corrector2 = 2.0f * corrector1;
|
|
|
|
matrix.r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
|
|
matrix.r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
|
|
matrix.r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
|
|
|
|
matrix.r1c2 = corrector2 * (x1x2 - s0x3);
|
|
matrix.r2c3 = corrector2 * (x2x3 - s0x1);
|
|
matrix.r3c1 = corrector2 * (x1x3 - s0x2);
|
|
|
|
matrix.r2c1 = corrector2 * (x1x2 + s0x3);
|
|
matrix.r3c2 = corrector2 * (x2x3 + s0x1);
|
|
matrix.r1c3 = corrector2 * (x1x3 + s0x2);
|
|
}
|
|
|
|
public readonly void MakeReverseMatrix(out Matrix3x3FP32 matrix)
|
|
{
|
|
float s0s0 = this.s0 * this.s0;
|
|
float x1x1 = this.x1 * this.x1;
|
|
float x2x2 = this.x2 * this.x2;
|
|
float x3x3 = this.x3 * this.x3;
|
|
|
|
float squareModulus = (s0s0 + x1x1) + (x2x2 + x3x3);
|
|
|
|
if (squareModulus <= UtilityFP32.SQUARE_EPSYLON)
|
|
{
|
|
Matrix3x3FP32.LoadIdentity(out matrix);
|
|
return;
|
|
}
|
|
|
|
float corrector1 = 1.0f / squareModulus;
|
|
|
|
float s0x1 = this.s0 * this.x1;
|
|
float s0x2 = this.s0 * this.x2;
|
|
float s0x3 = this.s0 * this.x3;
|
|
float x1x2 = this.x1 * this.x2;
|
|
float x1x3 = this.x1 * this.x3;
|
|
float x2x3 = this.x2 * this.x3;
|
|
|
|
float corrector2 = 2.0f * corrector1;
|
|
|
|
matrix.r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
|
|
matrix.r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
|
|
matrix.r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
|
|
|
|
matrix.r1c2 = corrector2 * (x1x2 + s0x3);
|
|
matrix.r2c3 = corrector2 * (x2x3 + s0x1);
|
|
matrix.r3c1 = corrector2 * (x1x3 + s0x2);
|
|
|
|
matrix.r2c1 = corrector2 * (x1x2 - s0x3);
|
|
matrix.r3c2 = corrector2 * (x2x3 - s0x1);
|
|
matrix.r1c3 = corrector2 * (x1x3 - s0x2);
|
|
}
|
|
|
|
public static void Add(in QuaternionFP32 quaternion1, in QuaternionFP32 quaternion2, out QuaternionFP32 sum)
|
|
{
|
|
sum.s0 = quaternion1.s0 + quaternion2.s0;
|
|
sum.x1 = quaternion1.x1 + quaternion2.x1;
|
|
sum.x2 = quaternion1.x2 + quaternion2.x2;
|
|
sum.x3 = quaternion1.x3 + quaternion2.x3;
|
|
}
|
|
|
|
public static void Subtract(in QuaternionFP32 minuend, in QuaternionFP32 subtrahend, out QuaternionFP32 difference)
|
|
{
|
|
difference.s0 = minuend.s0 - subtrahend.s0;
|
|
difference.x1 = minuend.x1 - subtrahend.x1;
|
|
difference.x2 = minuend.x2 - subtrahend.x2;
|
|
difference.x3 = minuend.x3 - subtrahend.x3;
|
|
}
|
|
|
|
public static void Multiply(in QuaternionFP32 left, in QuaternionFP32 right, out QuaternionFP32 product)
|
|
{
|
|
float s0 = left.s0 * right.s0 - left.x1 * right.x1 - (left.x2 * right.x2 + left.x3 * right.x3);
|
|
float x1 = left.x1 * right.s0 + left.s0 * right.x1 - (left.x3 * right.x2 - left.x2 * right.x3);
|
|
float x2 = left.x2 * right.s0 + left.s0 * right.x2 - (left.x1 * right.x3 - left.x3 * right.x1);
|
|
float x3 = left.x3 * right.s0 + left.s0 * right.x3 - (left.x2 * right.x1 - left.x1 * right.x2);
|
|
|
|
product.s0 = s0;
|
|
product.x1 = x1;
|
|
product.x2 = x2;
|
|
product.x3 = x3;
|
|
}
|
|
|
|
public static bool AreClose(QuaternionFP32 quaternion1, QuaternionFP32 quaternion2)
|
|
{
|
|
float ds0 = quaternion1.s0 - quaternion2.s0;
|
|
float dx1 = quaternion1.x1 - quaternion2.x1;
|
|
float dx2 = quaternion1.x2 - quaternion2.x2;
|
|
float dx3 = quaternion1.x3 - quaternion2.x3;
|
|
|
|
float squareModulus1 = quaternion1.GetSquareModulus();
|
|
float squareModulus2 = quaternion2.GetSquareModulus();
|
|
float squareDistance = (ds0 * ds0 + dx1 * dx1) + (dx2 * dx2 + dx3 * dx3);
|
|
|
|
if (squareModulus1 <= UtilityFP32.EPSYLON_EFFECTIVENESS_LIMIT || squareModulus2 <= UtilityFP32.EPSYLON_EFFECTIVENESS_LIMIT) {
|
|
return squareDistance <= UtilityFP32.SQUARE_EPSYLON;
|
|
}
|
|
|
|
return squareDistance <= UtilityFP32.SQUARE_EPSYLON * squareModulus1 && squareDistance <= UtilityFP32.SQUARE_EPSYLON * squareModulus2;
|
|
}
|
|
}
|
|
}
|