bgc-net/BasicGeometry/FP32Quaternion.cs

203 lines
6.9 KiB
C#

using System;
namespace BasicGeometry
{
public struct FP32Quaternion
{
public float s0 = 0.0f, x1 = 0.0f, x2 = 0.0f, x3 = 0.0f;
public FP32Quaternion(float s0, float x1, float x2, float x3)
{
this.s0 = s0;
this.x1 = x1;
this.x2 = x2;
this.x3 = x3;
}
public FP32Quaternion(in FP32Quaternion quaternion)
{
this.s0 = quaternion.s0;
this.x1 = quaternion.x1;
this.x2 = quaternion.x2;
this.x3 = quaternion.x3;
}
public FP32Quaternion(in FP64Quaternion quaternion)
{
this.s0 = (float)quaternion.s0;
this.x1 = (float)quaternion.x1;
this.x2 = (float)quaternion.x2;
this.x3 = (float)quaternion.x3;
}
public void Reset()
{
this.s0 = 0.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 SetValues(in FP32Quaternion quaternion)
{
this.s0 = quaternion.s0;
this.x1 = quaternion.x1;
this.x2 = quaternion.x2;
this.x3 = quaternion.x3;
}
public void SetValues(in FP64Quaternion quaternion)
{
this.s0 = (float)quaternion.s0;
this.x1 = (float)quaternion.x1;
this.x2 = (float)quaternion.x2;
this.x3 = (float)quaternion.x3;
}
public void SetConjugateOf(in FP32Quaternion quaternion)
{
this.s0 = quaternion.s0;
this.x1 = -quaternion.x1;
this.x2 = -quaternion.x2;
this.x3 = -quaternion.x3;
}
public readonly void MakeRotationMatrix(out FP32Matrix3x3 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 squareModule = (s0s0 + x1x1) + (x2x2 + x3x3);
if (-FP32Utility.EPSYLON <= squareModule && squareModule <= FP32Utility.EPSYLON)
{
FP32Matrix3x3.LoadIdentity(out matrix);
return;
}
float corrector1;
float corrector2;
if (1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0f + FP32Utility.TWO_EPSYLON) {
corrector1 = 2.0f - squareModule;
corrector2 = 2.0f * corrector1;
}
else {
corrector1 = 1.0f / squareModule;
corrector2 = 2.0f / squareModule;
}
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;
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 FP32Matrix3x3 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 squareModule = (s0s0 + x1x1) + (x2x2 + x3x3);
if (-FP32Utility.EPSYLON <= squareModule && squareModule <= FP32Utility.EPSYLON)
{
FP32Matrix3x3.LoadIdentity(out matrix);
return;
}
float corrector1;
float corrector2;
if (1.0f - FP32Utility.TWO_EPSYLON <= squareModule && squareModule <= 1.0f + FP32Utility.TWO_EPSYLON) {
corrector1 = 2.0f - squareModule;
corrector2 = 2.0f * corrector1;
}
else {
corrector1 = 1.0f / squareModule;
corrector2 = 2.0f / squareModule;
}
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;
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 FP32Quaternion quaternion1, in FP32Quaternion quaternion2, out FP32Quaternion 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 FP32Quaternion minuend, in FP32Quaternion subtrahend, out FP32Quaternion 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 FP32Quaternion left, in FP32Quaternion right, out FP32Quaternion 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;
}
}
}