Compare commits
5 Commits
8357c5d623
...
67cf8b31fb
Author | SHA1 | Date | |
---|---|---|---|
67cf8b31fb | |||
db36669afb | |||
b21ca6b4fb | |||
b3975ed256 | |||
36f56c4956 |
19
LinearAlgebra/.editorconfig
Normal file
19
LinearAlgebra/.editorconfig
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# EditorConfig is awesome: https://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = crlf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
insert_final_newline = false
|
||||||
|
max_line_length = 80
|
||||||
|
|
||||||
|
[*.cs]
|
||||||
|
csharp_new_line_before_open_brace = none
|
||||||
|
# Suppress warnings everywhere
|
||||||
|
dotnet_diagnostic.IDE1006.severity = none
|
||||||
|
dotnet_diagnostic.IDE0130.severity = none
|
@ -1,13 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace LinearAlgebra
|
namespace LinearAlgebra {
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// %Angle utilities
|
/// %Angle utilities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Angle
|
public static class Angle {
|
||||||
{
|
|
||||||
public const float pi = 3.1415927410125732421875F;
|
public const float pi = 3.1415927410125732421875F;
|
||||||
// public static float Rad2Deg = 360.0f / ((float)Math.PI * 2);
|
// public static float Rad2Deg = 360.0f / ((float)Math.PI * 2);
|
||||||
// public static float Deg2Rad = ((float)Math.PI * 2) / 360.0f;
|
// public static float Deg2Rad = ((float)Math.PI * 2) / 360.0f;
|
||||||
@ -23,8 +21,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="max">The maximum angle</param>
|
/// <param name="max">The maximum angle</param>
|
||||||
/// <returns>The clamped angle</returns>
|
/// <returns>The clamped angle</returns>
|
||||||
/// Angles are normalized
|
/// Angles are normalized
|
||||||
public static float Clamp(float angle, float min, float max)
|
public static float Clamp(float angle, float min, float max) {
|
||||||
{
|
|
||||||
float normalizedAngle = Normalize(angle);
|
float normalizedAngle = Normalize(angle);
|
||||||
return Float.Clamp(normalizedAngle, min, max);
|
return Float.Clamp(normalizedAngle, min, max);
|
||||||
}
|
}
|
||||||
@ -36,8 +33,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="b">The second angle</param>
|
/// <param name="b">The second angle</param>
|
||||||
/// <returns>the angle between the two angles</returns>
|
/// <returns>the angle between the two angles</returns>
|
||||||
/// Angle values should be degrees
|
/// Angle values should be degrees
|
||||||
public static float Difference(float a, float b)
|
public static float Difference(float a, float b) {
|
||||||
{
|
|
||||||
float r = Normalize(b - a);
|
float r = Normalize(b - a);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -48,8 +44,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="angle">The angle to normalize</param>
|
/// <param name="angle">The angle to normalize</param>
|
||||||
/// <returns>The normalized angle in interval (-180..180] </returns>
|
/// <returns>The normalized angle in interval (-180..180] </returns>
|
||||||
/// Angle values should be in degrees
|
/// Angle values should be in degrees
|
||||||
public static float Normalize(float angle)
|
public static float Normalize(float angle) {
|
||||||
{
|
|
||||||
if (float.IsInfinity(angle))
|
if (float.IsInfinity(angle))
|
||||||
return angle;
|
return angle;
|
||||||
|
|
||||||
@ -66,8 +61,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="maxAngle">Maximum angle to rotate</param>
|
/// <param name="maxAngle">Maximum angle to rotate</param>
|
||||||
/// <returns>The resulting angle</returns>
|
/// <returns>The resulting angle</returns>
|
||||||
/// This function is compatible with radian and degrees angles
|
/// This function is compatible with radian and degrees angles
|
||||||
public static float MoveTowards(float fromAngle, float toAngle, float maxAngle)
|
public static float MoveTowards(float fromAngle, float toAngle, float maxAngle) {
|
||||||
{
|
|
||||||
float d = toAngle - fromAngle;
|
float d = toAngle - fromAngle;
|
||||||
d = Normalize(d);
|
d = Normalize(d);
|
||||||
d = Math.Sign(d) * Float.Clamp(Math.Abs(d), 0, maxAngle);
|
d = Math.Sign(d) * Float.Clamp(Math.Abs(d), 0, maxAngle);
|
||||||
@ -83,8 +77,7 @@ namespace LinearAlgebra
|
|||||||
/// Vectors a and b must be normalized
|
/// Vectors a and b must be normalized
|
||||||
/// \deprecated Please use Vector2.ToFactor instead.
|
/// \deprecated Please use Vector2.ToFactor instead.
|
||||||
[Obsolete("Please use Vector2.ToFactor instead.")]
|
[Obsolete("Please use Vector2.ToFactor instead.")]
|
||||||
public static float ToFactor(Vector2 v1, Vector2 v2)
|
public static float ToFactor(Vector2 v1, Vector2 v2) {
|
||||||
{
|
|
||||||
return (1 - Vector2.Dot(v1, v2)) / 2;
|
return (1 - Vector2.Dot(v1, v2)) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,34 +6,57 @@ using Vector3Float = UnityEngine.Vector3;
|
|||||||
namespace LinearAlgebra
|
namespace LinearAlgebra
|
||||||
{
|
{
|
||||||
|
|
||||||
public class Direction
|
/// <summary>
|
||||||
{
|
/// A direction in 3D space
|
||||||
|
/// </summary>
|
||||||
|
/// A direction is represented using two angles:
|
||||||
|
/// * The horizontal angle ranging from -180 (inclusive) to 180 (exclusive)
|
||||||
|
/// degrees which is a rotation in the horizontal plane
|
||||||
|
/// * A vertical angle ranging from -90 (inclusive) to 90 (exclusive) degrees
|
||||||
|
/// which is the rotation in the up/down direction applied after the horizontal
|
||||||
|
/// rotation has been applied.
|
||||||
|
/// The angles are automatically normalized to stay within the abovenmentioned
|
||||||
|
/// ranges.
|
||||||
|
public class Direction {
|
||||||
public float horizontal;
|
public float horizontal;
|
||||||
public float vertical;
|
public float vertical;
|
||||||
|
|
||||||
public Direction()
|
public Direction() {
|
||||||
{
|
|
||||||
horizontal = 0;
|
horizontal = 0;
|
||||||
vertical = 0;
|
vertical = 0;
|
||||||
}
|
}
|
||||||
public Direction(float horizontal, float vertical)
|
// public Direction(float horizontal, float vertical) {
|
||||||
{
|
// this.horizontal = horizontal;
|
||||||
this.horizontal = horizontal;
|
// this.vertical = vertical;
|
||||||
this.vertical = vertical;
|
// //Normalize();
|
||||||
|
// }
|
||||||
|
|
||||||
|
public static Direction Degrees(float horizontal, float vertical) {
|
||||||
|
Direction d = new() {
|
||||||
|
horizontal = horizontal,
|
||||||
|
vertical = vertical
|
||||||
|
};
|
||||||
//Normalize();
|
//Normalize();
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
public static Direction Radians(float horizontal, float vertical) {
|
||||||
|
Direction d = new() {
|
||||||
|
horizontal = horizontal * Angle.Rad2Deg,
|
||||||
|
vertical = vertical * Angle.Rad2Deg
|
||||||
|
};
|
||||||
|
//Normalize();
|
||||||
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly static Direction forward = new Direction(0, 0);
|
public readonly static Direction forward = Degrees(0, 0);
|
||||||
public readonly static Direction backward = new Direction(-180, 0);
|
public readonly static Direction backward = Degrees(-180, 0);
|
||||||
public readonly static Direction up = new Direction(0, 90);
|
public readonly static Direction up = Degrees(0, 90);
|
||||||
public readonly static Direction down = new Direction(0, -90);
|
public readonly static Direction down = Degrees(0, -90);
|
||||||
public readonly static Direction left = new Direction(-90, 0);
|
public readonly static Direction left = Degrees(-90, 0);
|
||||||
public readonly static Direction right = new Direction(90, 0);
|
public readonly static Direction right = Degrees(90, 0);
|
||||||
|
|
||||||
public void Normalize()
|
public void Normalize() {
|
||||||
{
|
if (this.vertical > 90 || this.vertical < -90) {
|
||||||
if (this.vertical > 90 || this.vertical < -90)
|
|
||||||
{
|
|
||||||
this.horizontal += 180;
|
this.horizontal += 180;
|
||||||
this.vertical = 180 - this.vertical;
|
this.vertical = 180 - this.vertical;
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
namespace LinearAlgebra
|
namespace LinearAlgebra {
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Float number utilities
|
/// Float number utilities
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Float
|
public class Float {
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The precision of float numbers
|
/// The precision of float numbers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -22,8 +20,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="min">The minimum value</param>
|
/// <param name="min">The minimum value</param>
|
||||||
/// <param name="max">The maximum value</param>
|
/// <param name="max">The maximum value</param>
|
||||||
/// <returns>The clamped value</returns>
|
/// <returns>The clamped value</returns>
|
||||||
public static float Clamp(float f, float min, float max)
|
public static float Clamp(float f, float min, float max) {
|
||||||
{
|
|
||||||
if (f < min)
|
if (f < min)
|
||||||
return min;
|
return min;
|
||||||
if (f > max)
|
if (f > max)
|
||||||
@ -36,8 +33,7 @@ namespace LinearAlgebra
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="f">The value to clamp</param>
|
/// <param name="f">The value to clamp</param>
|
||||||
/// <returns>The clamped value</returns>
|
/// <returns>The clamped value</returns>
|
||||||
public static float Clamp01(float f)
|
public static float Clamp01(float f) {
|
||||||
{
|
|
||||||
return Clamp(f, 0, 1);
|
return Clamp(f, 0, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,7 @@ using Vector2Float = UnityEngine.Vector2;
|
|||||||
using Quaternion = UnityEngine.Quaternion;
|
using Quaternion = UnityEngine.Quaternion;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace LinearAlgebra
|
namespace LinearAlgebra {
|
||||||
{
|
|
||||||
|
|
||||||
public readonly struct Slice
|
public readonly struct Slice
|
||||||
{
|
{
|
||||||
@ -19,8 +18,7 @@ namespace LinearAlgebra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Matrix2
|
public class Matrix2 {
|
||||||
{
|
|
||||||
public float[,] data { get; }
|
public float[,] data { get; }
|
||||||
|
|
||||||
public int nRows => data.GetLength(0);
|
public int nRows => data.GetLength(0);
|
||||||
@ -30,16 +28,13 @@ namespace LinearAlgebra
|
|||||||
{
|
{
|
||||||
this.data = new float[nRows, nCols];
|
this.data = new float[nRows, nCols];
|
||||||
}
|
}
|
||||||
public Matrix2(float[,] data)
|
public Matrix2(float[,] data) {
|
||||||
{
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Matrix2 Clone()
|
public Matrix2 Clone() {
|
||||||
{
|
|
||||||
float[,] data = new float[this.nRows, nCols];
|
float[,] data = new float[this.nRows, nCols];
|
||||||
for (int rowIx = 0; rowIx < this.nRows; rowIx++)
|
for (int rowIx = 0; rowIx < this.nRows; rowIx++) {
|
||||||
{
|
|
||||||
for (int colIx = 0; colIx < this.nCols; colIx++)
|
for (int colIx = 0; colIx < this.nCols; colIx++)
|
||||||
data[rowIx, colIx] = this.data[rowIx, colIx];
|
data[rowIx, colIx] = this.data[rowIx, colIx];
|
||||||
}
|
}
|
||||||
@ -51,8 +46,7 @@ namespace LinearAlgebra
|
|||||||
return new Matrix2(nRows, nCols);
|
return new Matrix2(nRows, nCols);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix2 FromVector3(Vector3Float v)
|
public static Matrix2 FromVector3(Vector3Float v) {
|
||||||
{
|
|
||||||
float[,] result = new float[3, 1];
|
float[,] result = new float[3, 1];
|
||||||
result[0, 0] = v.x;
|
result[0, 0] = v.x;
|
||||||
result[1, 0] = v.y;
|
result[1, 0] = v.y;
|
||||||
@ -71,8 +65,7 @@ namespace LinearAlgebra
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix2 Diagonal(Matrix1 v)
|
public static Matrix2 Diagonal(Matrix1 v) {
|
||||||
{
|
|
||||||
float[,] resultData = new float[v.size, v.size];
|
float[,] resultData = new float[v.size, v.size];
|
||||||
for (int ix = 0; ix < v.size; ix++)
|
for (int ix = 0; ix < v.size; ix++)
|
||||||
resultData[ix, ix] = v.data[ix];
|
resultData[ix, ix] = v.data[ix];
|
||||||
@ -98,8 +91,7 @@ namespace LinearAlgebra
|
|||||||
this.data[ix, ix] = f;
|
this.data[ix, ix] = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix2 SkewMatrix(Vector3Float v)
|
public static Matrix2 SkewMatrix(Vector3Float v) {
|
||||||
{
|
|
||||||
float[,] result = new float[3, 3] {
|
float[,] result = new float[3, 3] {
|
||||||
{0, -v.z, v.y},
|
{0, -v.z, v.y},
|
||||||
{v.z, 0, -v.x},
|
{v.z, 0, -v.x},
|
||||||
@ -127,13 +119,11 @@ namespace LinearAlgebra
|
|||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
public void SetRow(int rowIx, Matrix1 v)
|
public void SetRow(int rowIx, Matrix1 v) {
|
||||||
{
|
|
||||||
for (uint ix = 0; ix < v.size; ix++)
|
for (uint ix = 0; ix < v.size; ix++)
|
||||||
this.data[rowIx, ix] = v.data[ix];
|
this.data[rowIx, ix] = v.data[ix];
|
||||||
}
|
}
|
||||||
public void SetRow3(int rowIx, Vector3Float v)
|
public void SetRow3(int rowIx, Vector3Float v) {
|
||||||
{
|
|
||||||
this.data[rowIx, 0] = v.x;
|
this.data[rowIx, 0] = v.x;
|
||||||
this.data[rowIx, 1] = v.y;
|
this.data[rowIx, 1] = v.y;
|
||||||
this.data[rowIx, 2] = v.z;
|
this.data[rowIx, 2] = v.z;
|
||||||
@ -150,8 +140,7 @@ namespace LinearAlgebra
|
|||||||
public Matrix1 GetColumn(int colIx)
|
public Matrix1 GetColumn(int colIx)
|
||||||
{
|
{
|
||||||
float[] column = new float[this.nRows];
|
float[] column = new float[this.nRows];
|
||||||
for (int i = 0; i < this.nRows; i++)
|
for (int i = 0; i < this.nRows; i++) {
|
||||||
{
|
|
||||||
column[i] = this.data[i, colIx];
|
column[i] = this.data[i, colIx];
|
||||||
}
|
}
|
||||||
return new Matrix1(column);
|
return new Matrix1(column);
|
||||||
@ -166,12 +155,9 @@ namespace LinearAlgebra
|
|||||||
this.data[2, colIx] = v.z;
|
this.data[2, colIx] = v.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool AllClose(Matrix2 A, Matrix2 B, float atol = 1e-08f)
|
public static bool AllClose(Matrix2 A, Matrix2 B, float atol = 1e-08f) {
|
||||||
{
|
for (int i = 0; i < A.nRows; i++) {
|
||||||
for (int i = 0; i < A.nRows; i++)
|
for (int j = 0; j < A.nCols; j++) {
|
||||||
{
|
|
||||||
for (int j = 0; j < A.nCols; j++)
|
|
||||||
{
|
|
||||||
float d = MathF.Abs(A.data[i, j] - B.data[i, j]);
|
float d = MathF.Abs(A.data[i, j] - B.data[i, j]);
|
||||||
if (d > atol)
|
if (d > atol)
|
||||||
return false;
|
return false;
|
||||||
@ -180,75 +166,63 @@ namespace LinearAlgebra
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Matrix2 Transpose()
|
public Matrix2 Transpose() {
|
||||||
{
|
|
||||||
float[,] resultData = new float[this.nCols, this.nRows];
|
float[,] resultData = new float[this.nCols, this.nRows];
|
||||||
for (uint rowIx = 0; rowIx < this.nRows; rowIx++)
|
for (uint rowIx = 0; rowIx < this.nRows; rowIx++) {
|
||||||
{
|
|
||||||
for (uint colIx = 0; colIx < this.nCols; colIx++)
|
for (uint colIx = 0; colIx < this.nCols; colIx++)
|
||||||
resultData[colIx, rowIx] = this.data[rowIx, colIx];
|
resultData[colIx, rowIx] = this.data[rowIx, colIx];
|
||||||
}
|
}
|
||||||
return new Matrix2(resultData);
|
return new Matrix2(resultData);
|
||||||
// double checked code
|
// double checked code
|
||||||
}
|
}
|
||||||
public Matrix2 transposed
|
public Matrix2 transposed {
|
||||||
{
|
|
||||||
get => Transpose();
|
get => Transpose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix2 operator -(Matrix2 m)
|
public static Matrix2 operator -(Matrix2 m) {
|
||||||
{
|
|
||||||
float[,] result = new float[m.nRows, m.nCols];
|
float[,] result = new float[m.nRows, m.nCols];
|
||||||
|
|
||||||
for (int i = 0; i < m.nRows; i++)
|
for (int i = 0; i < m.nRows; i++) {
|
||||||
{
|
|
||||||
for (int j = 0; j < m.nCols; j++)
|
for (int j = 0; j < m.nCols; j++)
|
||||||
result[i, j] = -m.data[i, j];
|
result[i, j] = -m.data[i, j];
|
||||||
}
|
}
|
||||||
return new Matrix2(result);
|
return new Matrix2(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix2 operator -(Matrix2 A, Matrix2 B)
|
public static Matrix2 operator -(Matrix2 A, Matrix2 B) {
|
||||||
{
|
|
||||||
if (A.nRows != B.nRows || A.nCols != B.nCols)
|
if (A.nRows != B.nRows || A.nCols != B.nCols)
|
||||||
throw new System.ArgumentException("Size of A must match size of B.");
|
throw new System.ArgumentException("Size of A must match size of B.");
|
||||||
|
|
||||||
float[,] result = new float[A.nRows, B.nCols];
|
float[,] result = new float[A.nRows, B.nCols];
|
||||||
|
|
||||||
for (int i = 0; i < A.nRows; i++)
|
for (int i = 0; i < A.nRows; i++) {
|
||||||
{
|
|
||||||
for (int j = 0; j < A.nCols; j++)
|
for (int j = 0; j < A.nCols; j++)
|
||||||
result[i, j] = A.data[i, j] - B.data[i, j];
|
result[i, j] = A.data[i, j] - B.data[i, j];
|
||||||
}
|
}
|
||||||
return new Matrix2(result);
|
return new Matrix2(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix2 operator +(Matrix2 A, Matrix2 B)
|
public static Matrix2 operator +(Matrix2 A, Matrix2 B) {
|
||||||
{
|
|
||||||
if (A.nRows != B.nRows || A.nCols != B.nCols)
|
if (A.nRows != B.nRows || A.nCols != B.nCols)
|
||||||
throw new System.ArgumentException("Size of A must match size of B.");
|
throw new System.ArgumentException("Size of A must match size of B.");
|
||||||
|
|
||||||
float[,] result = new float[A.nRows, B.nCols];
|
float[,] result = new float[A.nRows, B.nCols];
|
||||||
|
|
||||||
for (int i = 0; i < A.nRows; i++)
|
for (int i = 0; i < A.nRows; i++) {
|
||||||
{
|
|
||||||
for (int j = 0; j < A.nCols; j++)
|
for (int j = 0; j < A.nCols; j++)
|
||||||
result[i, j] = A.data[i, j] + B.data[i, j];
|
result[i, j] = A.data[i, j] + B.data[i, j];
|
||||||
}
|
}
|
||||||
return new Matrix2(result);
|
return new Matrix2(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix2 operator *(Matrix2 A, Matrix2 B)
|
public static Matrix2 operator *(Matrix2 A, Matrix2 B) {
|
||||||
{
|
|
||||||
if (A.nCols != B.nRows)
|
if (A.nCols != B.nRows)
|
||||||
throw new System.ArgumentException("Number of columns in A must match number of rows in B.");
|
throw new System.ArgumentException("Number of columns in A must match number of rows in B.");
|
||||||
|
|
||||||
float[,] result = new float[A.nRows, B.nCols];
|
float[,] result = new float[A.nRows, B.nCols];
|
||||||
|
|
||||||
for (int i = 0; i < A.nRows; i++)
|
for (int i = 0; i < A.nRows; i++) {
|
||||||
{
|
for (int j = 0; j < B.nCols; j++) {
|
||||||
for (int j = 0; j < B.nCols; j++)
|
|
||||||
{
|
|
||||||
float sum = 0.0f;
|
float sum = 0.0f;
|
||||||
for (int k = 0; k < A.nCols; k++)
|
for (int k = 0; k < A.nCols; k++)
|
||||||
sum += A.data[i, k] * B.data[k, j];
|
sum += A.data[i, k] * B.data[k, j];
|
||||||
@ -261,14 +235,11 @@ namespace LinearAlgebra
|
|||||||
// double checked code
|
// double checked code
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix1 operator *(Matrix2 A, Matrix1 v)
|
public static Matrix1 operator *(Matrix2 A, Matrix1 v) {
|
||||||
{
|
|
||||||
float[] result = new float[A.nRows];
|
float[] result = new float[A.nRows];
|
||||||
|
|
||||||
for (int i = 0; i < A.nRows; i++)
|
for (int i = 0; i < A.nRows; i++) {
|
||||||
{
|
for (int j = 0; j < A.nCols; j++) {
|
||||||
for (int j = 0; j < A.nCols; j++)
|
|
||||||
{
|
|
||||||
result[i] += A.data[i, j] * v.data[j];
|
result[i] += A.data[i, j] * v.data[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,8 +247,7 @@ namespace LinearAlgebra
|
|||||||
return new Matrix1(result);
|
return new Matrix1(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3Float operator *(Matrix2 A, Vector3Float v)
|
public static Vector3Float operator *(Matrix2 A, Vector3Float v) {
|
||||||
{
|
|
||||||
return new Vector3Float(
|
return new Vector3Float(
|
||||||
A.data[0, 0] * v.x + A.data[0, 1] * v.y + A.data[0, 2] * v.z,
|
A.data[0, 0] * v.x + A.data[0, 1] * v.y + A.data[0, 2] * v.z,
|
||||||
A.data[1, 0] * v.x + A.data[1, 1] * v.y + A.data[1, 2] * v.z,
|
A.data[1, 0] * v.x + A.data[1, 1] * v.y + A.data[1, 2] * v.z,
|
||||||
@ -285,41 +255,34 @@ namespace LinearAlgebra
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix2 operator *(Matrix2 A, float s)
|
public static Matrix2 operator *(Matrix2 A, float s) {
|
||||||
{
|
|
||||||
float[,] result = new float[A.nRows, A.nCols];
|
float[,] result = new float[A.nRows, A.nCols];
|
||||||
|
|
||||||
for (int i = 0; i < A.nRows; i++)
|
for (int i = 0; i < A.nRows; i++) {
|
||||||
{
|
|
||||||
for (int j = 0; j < A.nCols; j++)
|
for (int j = 0; j < A.nCols; j++)
|
||||||
result[i, j] = A.data[i, j] * s;
|
result[i, j] = A.data[i, j] * s;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Matrix2(result);
|
return new Matrix2(result);
|
||||||
}
|
}
|
||||||
public static Matrix2 operator *(float s, Matrix2 A)
|
public static Matrix2 operator *(float s, Matrix2 A) {
|
||||||
{
|
|
||||||
return A * s;
|
return A * s;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix2 operator /(Matrix2 A, float s)
|
public static Matrix2 operator /(Matrix2 A, float s) {
|
||||||
{
|
|
||||||
float[,] result = new float[A.nRows, A.nCols];
|
float[,] result = new float[A.nRows, A.nCols];
|
||||||
|
|
||||||
for (int i = 0; i < A.nRows; i++)
|
for (int i = 0; i < A.nRows; i++) {
|
||||||
{
|
|
||||||
for (int j = 0; j < A.nCols; j++)
|
for (int j = 0; j < A.nCols; j++)
|
||||||
result[i, j] = A.data[i, j] / s;
|
result[i, j] = A.data[i, j] / s;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Matrix2(result);
|
return new Matrix2(result);
|
||||||
}
|
}
|
||||||
public static Matrix2 operator /(float s, Matrix2 A)
|
public static Matrix2 operator /(float s, Matrix2 A) {
|
||||||
{
|
|
||||||
float[,] result = new float[A.nRows, A.nCols];
|
float[,] result = new float[A.nRows, A.nCols];
|
||||||
|
|
||||||
for (int i = 0; i < A.nRows; i++)
|
for (int i = 0; i < A.nRows; i++) {
|
||||||
{
|
|
||||||
for (int j = 0; j < A.nCols; j++)
|
for (int j = 0; j < A.nCols; j++)
|
||||||
result[i, j] = s / A.data[i, j];
|
result[i, j] = s / A.data[i, j];
|
||||||
}
|
}
|
||||||
@ -368,8 +331,7 @@ namespace LinearAlgebra
|
|||||||
|
|
||||||
return new Matrix2(result);
|
return new Matrix2(result);
|
||||||
}
|
}
|
||||||
public Matrix2 Slice(Slice rowRange, Slice colRange)
|
public Matrix2 Slice(Slice rowRange, Slice colRange) {
|
||||||
{
|
|
||||||
return Slice((rowRange.start, rowRange.stop), (colRange.start, colRange.stop));
|
return Slice((rowRange.start, rowRange.stop), (colRange.start, colRange.stop));
|
||||||
}
|
}
|
||||||
public Matrix2 Slice((int start, int stop) rowRange, (int start, int stop) colRange)
|
public Matrix2 Slice((int start, int stop) rowRange, (int start, int stop) colRange)
|
||||||
@ -412,26 +374,22 @@ namespace LinearAlgebra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Matrix2 Inverse()
|
public Matrix2 Inverse() {
|
||||||
{
|
|
||||||
Matrix2 A = this;
|
Matrix2 A = this;
|
||||||
// unchecked
|
// unchecked
|
||||||
int n = A.nRows;
|
int n = A.nRows;
|
||||||
|
|
||||||
// Create an identity matrix of the same size as the original matrix
|
// Create an identity matrix of the same size as the original matrix
|
||||||
float[,] augmentedMatrix = new float[n, 2 * n];
|
float[,] augmentedMatrix = new float[n, 2 * n];
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++) {
|
||||||
{
|
for (int j = 0; j < n; j++) {
|
||||||
for (int j = 0; j < n; j++)
|
|
||||||
{
|
|
||||||
augmentedMatrix[i, j] = A.data[i, j];
|
augmentedMatrix[i, j] = A.data[i, j];
|
||||||
augmentedMatrix[i, j + n] = (i == j) ? 1 : 0; // Identity matrix
|
augmentedMatrix[i, j + n] = (i == j) ? 1 : 0; // Identity matrix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform Gaussian elimination
|
// Perform Gaussian elimination
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
// Find the pivot row
|
// Find the pivot row
|
||||||
float pivot = augmentedMatrix[i, i];
|
float pivot = augmentedMatrix[i, i];
|
||||||
if (Math.Abs(pivot) < 1e-10) // Check for singular matrix
|
if (Math.Abs(pivot) < 1e-10) // Check for singular matrix
|
||||||
@ -442,8 +400,7 @@ namespace LinearAlgebra
|
|||||||
augmentedMatrix[i, j] /= pivot;
|
augmentedMatrix[i, j] /= pivot;
|
||||||
|
|
||||||
// Eliminate the column below the pivot
|
// Eliminate the column below the pivot
|
||||||
for (int j = i + 1; j < n; j++)
|
for (int j = i + 1; j < n; j++) {
|
||||||
{
|
|
||||||
float factor = augmentedMatrix[j, i];
|
float factor = augmentedMatrix[j, i];
|
||||||
for (int k = 0; k < 2 * n; k++)
|
for (int k = 0; k < 2 * n; k++)
|
||||||
augmentedMatrix[j, k] -= factor * augmentedMatrix[i, k];
|
augmentedMatrix[j, k] -= factor * augmentedMatrix[i, k];
|
||||||
@ -464,8 +421,7 @@ namespace LinearAlgebra
|
|||||||
|
|
||||||
// Extract the inverse matrix from the augmented matrix
|
// Extract the inverse matrix from the augmented matrix
|
||||||
float[,] inverse = new float[n, n];
|
float[,] inverse = new float[n, n];
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
for (int j = 0; j < n; j++)
|
for (int j = 0; j < n; j++)
|
||||||
inverse[i, j] = augmentedMatrix[i, j + n];
|
inverse[i, j] = augmentedMatrix[i, j + n];
|
||||||
}
|
}
|
||||||
@ -499,13 +455,11 @@ namespace LinearAlgebra
|
|||||||
float[,] minor = new float[n - 1, n - 1];
|
float[,] minor = new float[n - 1, n - 1];
|
||||||
|
|
||||||
int r = 0, c = 0;
|
int r = 0, c = 0;
|
||||||
for (int i = 0; i < n; i++)
|
for (int i = 0; i < n; i++) {
|
||||||
{
|
|
||||||
if (i == rowToRemove) continue;
|
if (i == rowToRemove) continue;
|
||||||
|
|
||||||
c = 0;
|
c = 0;
|
||||||
for (int j = 0; j < n; j++)
|
for (int j = 0; j < n; j++) {
|
||||||
{
|
|
||||||
if (j == colToRemove) continue;
|
if (j == colToRemove) continue;
|
||||||
|
|
||||||
minor[r, c] = this.data[i, j];
|
minor[r, c] = this.data[i, j];
|
||||||
@ -560,8 +514,7 @@ namespace LinearAlgebra
|
|||||||
this.data = new float[size];
|
this.data = new float[size];
|
||||||
}
|
}
|
||||||
|
|
||||||
public Matrix1(float[] data)
|
public Matrix1(float[] data) {
|
||||||
{
|
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,16 +523,14 @@ namespace LinearAlgebra
|
|||||||
return new Matrix1(size);
|
return new Matrix1(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix1 FromVector2(Vector2Float v)
|
public static Matrix1 FromVector2(Vector2Float v) {
|
||||||
{
|
|
||||||
float[] result = new float[2];
|
float[] result = new float[2];
|
||||||
result[0] = v.x;
|
result[0] = v.x;
|
||||||
result[1] = v.y;
|
result[1] = v.y;
|
||||||
return new Matrix1(result);
|
return new Matrix1(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Matrix1 FromVector3(Vector3Float v)
|
public static Matrix1 FromVector3(Vector3Float v) {
|
||||||
{
|
|
||||||
float[] result = new float[3];
|
float[] result = new float[3];
|
||||||
result[0] = v.x;
|
result[0] = v.x;
|
||||||
result[1] = v.y;
|
result[1] = v.y;
|
||||||
@ -598,19 +549,15 @@ namespace LinearAlgebra
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public Vector2Float vector2
|
public Vector2Float vector2 {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this.size != 2)
|
if (this.size != 2)
|
||||||
throw new System.ArgumentException("Matrix1 must be of size 2");
|
throw new System.ArgumentException("Matrix1 must be of size 2");
|
||||||
return new Vector2Float(this.data[0], this.data[1]);
|
return new Vector2Float(this.data[0], this.data[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public Vector3Float vector3
|
public Vector3Float vector3 {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
if (this.size != 3)
|
if (this.size != 3)
|
||||||
throw new System.ArgumentException("Matrix1 must be of size 3");
|
throw new System.ArgumentException("Matrix1 must be of size 3");
|
||||||
return new Vector3Float(this.data[0], this.data[1], this.data[2]);
|
return new Vector3Float(this.data[0], this.data[1], this.data[2]);
|
||||||
@ -627,8 +574,7 @@ namespace LinearAlgebra
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public Matrix1 Clone()
|
public Matrix1 Clone() {
|
||||||
{
|
|
||||||
float[] data = new float[this.size];
|
float[] data = new float[this.size];
|
||||||
for (int rowIx = 0; rowIx < this.size; rowIx++)
|
for (int rowIx = 0; rowIx < this.size; rowIx++)
|
||||||
data[rowIx] = this.data[rowIx];
|
data[rowIx] = this.data[rowIx];
|
||||||
@ -636,32 +582,27 @@ namespace LinearAlgebra
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public float magnitude
|
public float magnitude {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
float sum = 0;
|
float sum = 0;
|
||||||
foreach (var elm in data)
|
foreach (var elm in data)
|
||||||
sum += elm;
|
sum += elm;
|
||||||
return sum / data.Length;
|
return sum / data.Length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static Matrix1 operator +(Matrix1 A, Matrix1 B)
|
public static Matrix1 operator +(Matrix1 A, Matrix1 B) {
|
||||||
{
|
|
||||||
if (A.size != B.size)
|
if (A.size != B.size)
|
||||||
throw new System.ArgumentException("Size of A must match size of B.");
|
throw new System.ArgumentException("Size of A must match size of B.");
|
||||||
|
|
||||||
float[] result = new float[A.size];
|
float[] result = new float[A.size];
|
||||||
|
|
||||||
for (int i = 0; i < A.size; i++)
|
for (int i = 0; i < A.size; i++) {
|
||||||
{
|
|
||||||
result[i] = A.data[i] + B.data[i];
|
result[i] = A.data[i] + B.data[i];
|
||||||
}
|
}
|
||||||
return new Matrix1(result);
|
return new Matrix1(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Matrix2 Transpose()
|
public Matrix2 Transpose() {
|
||||||
{
|
|
||||||
float[,] r = new float[1, this.size];
|
float[,] r = new float[1, this.size];
|
||||||
for (uint colIx = 0; colIx < this.size; colIx++)
|
for (uint colIx = 0; colIx < this.size; colIx++)
|
||||||
r[1, colIx] = this.data[colIx];
|
r[1, colIx] = this.data[colIx];
|
||||||
@ -669,14 +610,12 @@ namespace LinearAlgebra
|
|||||||
return new Matrix2(r);
|
return new Matrix2(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float Dot(Matrix1 a, Matrix1 b)
|
public static float Dot(Matrix1 a, Matrix1 b) {
|
||||||
{
|
|
||||||
if (a.size != b.size)
|
if (a.size != b.size)
|
||||||
throw new System.ArgumentException("Vectors must be of the same length.");
|
throw new System.ArgumentException("Vectors must be of the same length.");
|
||||||
|
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
for (int i = 0; i < a.size; i++)
|
for (int i = 0; i < a.size; i++) {
|
||||||
{
|
|
||||||
result += a.data[i] * b.data[i];
|
result += a.data[i] * b.data[i];
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -703,8 +642,7 @@ namespace LinearAlgebra
|
|||||||
|
|
||||||
return new Matrix1(result);
|
return new Matrix1(result);
|
||||||
}
|
}
|
||||||
public static Matrix1 operator *(float f, Matrix1 A)
|
public static Matrix1 operator *(float f, Matrix1 A) {
|
||||||
{
|
|
||||||
return A * f;
|
return A * f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -741,8 +679,7 @@ namespace LinearAlgebra
|
|||||||
|
|
||||||
return new Matrix1(result);
|
return new Matrix1(result);
|
||||||
}
|
}
|
||||||
public void UpdateSlice(Slice slice, Matrix1 v)
|
public void UpdateSlice(Slice slice, Matrix1 v) {
|
||||||
{
|
|
||||||
int vIx = 0;
|
int vIx = 0;
|
||||||
for (int ix = slice.start; ix < slice.stop; ix++, vIx++)
|
for (int ix = slice.start; ix < slice.stop; ix++, vIx++)
|
||||||
this.data[ix] = v.data[vIx];
|
this.data[ix] = v.data[vIx];
|
||||||
|
@ -1,38 +1,32 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace LinearAlgebra
|
namespace LinearAlgebra {
|
||||||
{
|
public class Quat32 {
|
||||||
public class Quat32
|
|
||||||
{
|
|
||||||
public float x;
|
public float x;
|
||||||
public float y;
|
public float y;
|
||||||
public float z;
|
public float z;
|
||||||
public float w;
|
public float w;
|
||||||
|
|
||||||
public Quat32()
|
public Quat32() {
|
||||||
{
|
|
||||||
this.x = 0;
|
this.x = 0;
|
||||||
this.y = 0;
|
this.y = 0;
|
||||||
this.z = 0;
|
this.z = 0;
|
||||||
this.w = 1;
|
this.w = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Quat32(float x, float y, float z, float w)
|
public Quat32(float x, float y, float z, float w) {
|
||||||
{
|
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
this.w = w;
|
this.w = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Quat32 FromSwingTwist(SwingTwist s)
|
public static Quat32 FromSwingTwist(SwingTwist s) {
|
||||||
{
|
|
||||||
Quat32 q32 = Quat32.Euler(-s.swing.vertical, s.swing.horizontal, s.twist);
|
Quat32 q32 = Quat32.Euler(-s.swing.vertical, s.swing.horizontal, s.twist);
|
||||||
return q32;
|
return q32;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Quat32 Euler(float yaw, float pitch, float roll)
|
public static Quat32 Euler(float yaw, float pitch, float roll) {
|
||||||
{
|
|
||||||
float rollOver2 = roll * Angle.Deg2Rad * 0.5f;
|
float rollOver2 = roll * Angle.Deg2Rad * 0.5f;
|
||||||
float sinRollOver2 = (float)Math.Sin((float)rollOver2);
|
float sinRollOver2 = (float)Math.Sin((float)rollOver2);
|
||||||
float cosRollOver2 = (float)Math.Cos((float)rollOver2);
|
float cosRollOver2 = (float)Math.Cos((float)rollOver2);
|
||||||
@ -42,8 +36,7 @@ namespace LinearAlgebra
|
|||||||
float yawOver2 = yaw * 0.5f;
|
float yawOver2 = yaw * 0.5f;
|
||||||
float sinYawOver2 = (float)Math.Sin((float)yawOver2);
|
float sinYawOver2 = (float)Math.Sin((float)yawOver2);
|
||||||
float cosYawOver2 = (float)Math.Cos((float)yawOver2);
|
float cosYawOver2 = (float)Math.Cos((float)yawOver2);
|
||||||
Quat32 result = new Quat32()
|
Quat32 result = new Quat32() {
|
||||||
{
|
|
||||||
w = cosYawOver2 * cosPitchOver2 * cosRollOver2 +
|
w = cosYawOver2 * cosPitchOver2 * cosRollOver2 +
|
||||||
sinYawOver2 * sinPitchOver2 * sinRollOver2,
|
sinYawOver2 * sinPitchOver2 * sinRollOver2,
|
||||||
x = sinYawOver2 * cosPitchOver2 * cosRollOver2 +
|
x = sinYawOver2 * cosPitchOver2 * cosRollOver2 +
|
||||||
@ -56,27 +49,23 @@ namespace LinearAlgebra
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ToAngles(out float right, out float up, out float forward)
|
public void ToAngles(out float right, out float up, out float forward) {
|
||||||
{
|
|
||||||
float test = this.x * this.y + this.z * this.w;
|
float test = this.x * this.y + this.z * this.w;
|
||||||
if (test > 0.499f)
|
if (test > 0.499f) { // singularity at north pole
|
||||||
{ // singularity at north pole
|
|
||||||
right = 0;
|
right = 0;
|
||||||
up = 2 * (float)Math.Atan2(this.x, this.w) * Angle.Rad2Deg;
|
up = 2 * (float)Math.Atan2(this.x, this.w) * Angle.Rad2Deg;
|
||||||
forward = 90;
|
forward = 90;
|
||||||
return;
|
return;
|
||||||
//return Vector3(0, 2 * (float)atan2(this.x, this.w) * Angle.Rad2Deg, 90);
|
//return Vector3(0, 2 * (float)atan2(this.x, this.w) * Angle.Rad2Deg, 90);
|
||||||
}
|
}
|
||||||
else if (test < -0.499f)
|
else if (test < -0.499f) { // singularity at south pole
|
||||||
{ // singularity at south pole
|
|
||||||
right = 0;
|
right = 0;
|
||||||
up = -2 * (float)Math.Atan2(this.x, this.w) * Angle.Rad2Deg;
|
up = -2 * (float)Math.Atan2(this.x, this.w) * Angle.Rad2Deg;
|
||||||
forward = -90;
|
forward = -90;
|
||||||
return;
|
return;
|
||||||
//return Vector3(0, -2 * (float)atan2(this.x, this.w) * Angle.Rad2Deg, -90);
|
//return Vector3(0, -2 * (float)atan2(this.x, this.w) * Angle.Rad2Deg, -90);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
float sqx = this.x * this.x;
|
float sqx = this.x * this.x;
|
||||||
float sqy = this.y * this.y;
|
float sqy = this.y * this.y;
|
||||||
float sqz = this.z * this.z;
|
float sqz = this.z * this.z;
|
||||||
|
@ -18,12 +18,11 @@ namespace LinearAlgebra {
|
|||||||
this.w = w;
|
this.w = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if UNITY_5_3_OR_NEWER
|
||||||
public static Quaternion Reflect(Quaternion q) {
|
public static Quaternion Reflect(Quaternion q) {
|
||||||
return new(-q.x, -q.y, -q.z, q.w);
|
return new(-q.x, -q.y, -q.z, q.w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if UNITY_5_3_OR_NEWER
|
|
||||||
public static Matrix2 ToRotationMatrix(Quaternion q) {
|
public static Matrix2 ToRotationMatrix(Quaternion q) {
|
||||||
float w = q.x, x = q.y, y = q.z, z = q.w;
|
float w = q.x, x = q.y, y = q.z, z = q.w;
|
||||||
|
|
||||||
|
@ -3,42 +3,92 @@ using System;
|
|||||||
using Vector3Float = UnityEngine.Vector3;
|
using Vector3Float = UnityEngine.Vector3;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace LinearAlgebra
|
namespace LinearAlgebra {
|
||||||
{
|
/// <summary>
|
||||||
public class Spherical
|
/// A spherical vector
|
||||||
{
|
/// </summary>
|
||||||
public float distance;
|
public class Spherical {
|
||||||
public Direction direction;
|
|
||||||
|
|
||||||
public static Spherical zero = new Spherical(0, 0, 0);
|
/// <summary>
|
||||||
public static Spherical forward = new Spherical(1, 0, 0);
|
/// Create a default vector with zero distance
|
||||||
|
/// </summary>
|
||||||
public Spherical(float distance, float horizontal, float vertical)
|
public Spherical() {
|
||||||
{
|
this.distance = 0;
|
||||||
this.distance = distance;
|
this.direction = new Direction();
|
||||||
this.direction = new Direction(horizontal, vertical);
|
|
||||||
}
|
}
|
||||||
public Spherical(float distance, Direction direction)
|
|
||||||
{
|
/// <summary>
|
||||||
|
/// Create a spherical vector
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="distance">The distance in meters</param>
|
||||||
|
/// <param name="direction">The direction of the vector</param>
|
||||||
|
public Spherical(float distance, Direction direction) {
|
||||||
this.distance = distance;
|
this.distance = distance;
|
||||||
this.direction = direction;
|
this.direction = direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Spherical FromVector3(Vector3Float v)
|
/// <summary>
|
||||||
{
|
/// Create spherical vector. All given angles are in degrees
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="distance">The distance in meters</param>
|
||||||
|
/// <param name="horizontal">The horizontal angle in degrees</param>
|
||||||
|
/// <param name="vertical">The vertical angle in degrees</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Spherical Degrees(float distance, float horizontal, float vertical) {
|
||||||
|
Direction direction = Direction.Degrees(horizontal, vertical);
|
||||||
|
Spherical s = new(distance, direction);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Spherical Radians(float distance, float horizontal, float vertical) {
|
||||||
|
Direction direction = Direction.Radians(horizontal, vertical);
|
||||||
|
Spherical s = new(distance, direction);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The distance in meters
|
||||||
|
/// </summary>
|
||||||
|
/// @remark The distance should never be negative
|
||||||
|
public float distance;
|
||||||
|
/// <summary>
|
||||||
|
/// The direction of the vector
|
||||||
|
/// </summary>
|
||||||
|
public Direction direction;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A spherical vector with zero degree angles and distance
|
||||||
|
/// </summary>
|
||||||
|
public readonly static Spherical zero = new(0, Direction.forward);
|
||||||
|
/// <summary>
|
||||||
|
/// A normalized forward-oriented vector
|
||||||
|
/// </summary>
|
||||||
|
public readonly static Spherical forward = new(1, Direction.forward);
|
||||||
|
|
||||||
|
|
||||||
|
public static Spherical FromVector3Float(Vector3Float v) {
|
||||||
float distance = v.magnitude;
|
float distance = v.magnitude;
|
||||||
if (distance == 0.0f)
|
if (distance == 0.0f)
|
||||||
return new Spherical(distance, 0, 0);
|
return Spherical.zero;
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
float verticalAngle = (float)((Angle.pi / 2 - Math.Acos(v.y / distance)) * Angle.Rad2Deg);
|
float verticalAngle = (float)((Angle.pi / 2 - Math.Acos(v.y / distance)) * Angle.Rad2Deg);
|
||||||
float horizontalAngle = (float)Math.Atan2(v.x, v.z) * Angle.Rad2Deg;
|
float horizontalAngle = (float)Math.Atan2(v.x, v.z) * Angle.Rad2Deg;
|
||||||
return new Spherical(distance, horizontalAngle, verticalAngle);
|
return Spherical.Degrees(distance, horizontalAngle, verticalAngle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3Float ToVector3()
|
public static Spherical FromVector3(Vector3 v) {
|
||||||
{
|
float distance = v.magnitude;
|
||||||
|
if (distance == 0.0f)
|
||||||
|
return Spherical.zero;
|
||||||
|
else {
|
||||||
|
float verticalAngle = (float)((Angle.pi / 2 - Math.Acos(v.y / distance)) * Angle.Rad2Deg);
|
||||||
|
float horizontalAngle = (float)Math.Atan2(v.x, v.z) * Angle.Rad2Deg;
|
||||||
|
return Spherical.Degrees(distance, horizontalAngle, verticalAngle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector3Float ToVector3Float() {
|
||||||
float verticalRad = (Angle.pi / 2) - this.direction.vertical * Angle.Deg2Rad;
|
float verticalRad = (Angle.pi / 2) - this.direction.vertical * Angle.Deg2Rad;
|
||||||
float horizontalRad = this.direction.horizontal * Angle.Deg2Rad;
|
float horizontalRad = this.direction.horizontal * Angle.Deg2Rad;
|
||||||
float cosVertical = (float)Math.Cos(verticalRad);
|
float cosVertical = (float)Math.Cos(verticalRad);
|
||||||
@ -50,8 +100,34 @@ namespace LinearAlgebra
|
|||||||
float y = this.distance * cosVertical;
|
float y = this.distance * cosVertical;
|
||||||
float z = this.distance * sinVertical * cosHorizontal;
|
float z = this.distance * sinVertical * cosHorizontal;
|
||||||
|
|
||||||
Vector3Float v = new Vector3Float(x, y, z);
|
Vector3Float v = new(x, y, z);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector3 ToVector3() {
|
||||||
|
float verticalRad = (Angle.pi / 2) - this.direction.vertical * Angle.Deg2Rad;
|
||||||
|
float horizontalRad = this.direction.horizontal * Angle.Deg2Rad;
|
||||||
|
float cosVertical = (float)Math.Cos(verticalRad);
|
||||||
|
float sinVertical = (float)Math.Sin(verticalRad);
|
||||||
|
float cosHorizontal = (float)Math.Cos(horizontalRad);
|
||||||
|
float sinHorizontal = (float)Math.Sin(horizontalRad);
|
||||||
|
|
||||||
|
float x = this.distance * sinVertical * sinHorizontal;
|
||||||
|
float y = this.distance * cosVertical;
|
||||||
|
float z = this.distance * sinVertical * cosHorizontal;
|
||||||
|
|
||||||
|
Vector3 v = new(x, y, z);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Spherical operator +(Spherical s1, Spherical s2) {
|
||||||
|
// let's do it the easy way...
|
||||||
|
Vector3 v1 = s1.ToVector3();
|
||||||
|
Vector3 v2 = s2.ToVector3();
|
||||||
|
Vector3 v = v1 + v2;
|
||||||
|
Spherical r = FromVector3(v);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,29 +3,24 @@ using System.Numerics;
|
|||||||
using Quaternion = UnityEngine.Quaternion;
|
using Quaternion = UnityEngine.Quaternion;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace LinearAlgebra
|
namespace LinearAlgebra {
|
||||||
{
|
|
||||||
|
|
||||||
public class SwingTwist
|
public class SwingTwist {
|
||||||
{
|
|
||||||
public Direction swing;
|
public Direction swing;
|
||||||
public float twist;
|
public float twist;
|
||||||
|
|
||||||
public static readonly SwingTwist zero = new SwingTwist(0, 0, 0);
|
public static readonly SwingTwist zero = new SwingTwist(0, 0, 0);
|
||||||
|
|
||||||
public SwingTwist(Direction swing, float twist)
|
public SwingTwist(Direction swing, float twist) {
|
||||||
{
|
|
||||||
this.swing = swing;
|
this.swing = swing;
|
||||||
this.twist = twist;
|
this.twist = twist;
|
||||||
}
|
}
|
||||||
public SwingTwist(float horizontalSwing, float verticalSwing, float twist)
|
public SwingTwist(float horizontalSwing, float verticalSwing, float twist) {
|
||||||
{
|
this.swing = Direction.Degrees(horizontalSwing, verticalSwing);
|
||||||
this.swing = new Direction(horizontalSwing, verticalSwing);
|
|
||||||
this.swing.Normalize();
|
this.swing.Normalize();
|
||||||
this.twist = twist;
|
this.twist = twist;
|
||||||
}
|
}
|
||||||
public static SwingTwist FromQuat32(Quat32 q32)
|
public static SwingTwist FromQuat32(Quat32 q32) {
|
||||||
{
|
|
||||||
// UnityEngine.Quaternion q = new(q32.x, q32.y, q32.z, q32.w);
|
// UnityEngine.Quaternion q = new(q32.x, q32.y, q32.z, q32.w);
|
||||||
// SwingTwist r = new(q.eulerAngles.y, q.eulerAngles.x, q.eulerAngles.z);
|
// SwingTwist r = new(q.eulerAngles.y, q.eulerAngles.x, q.eulerAngles.z);
|
||||||
q32.ToAngles(out float right, out float up, out float forward);
|
q32.ToAngles(out float right, out float up, out float forward);
|
||||||
|
@ -1,63 +1,50 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
|
||||||
namespace LinearAlgebra
|
namespace LinearAlgebra {
|
||||||
{
|
|
||||||
|
|
||||||
public class Vector2Of<T> where T : IComparable<T>
|
public class Vector2Of<T> where T : IComparable<T> {
|
||||||
{
|
|
||||||
public T x;
|
public T x;
|
||||||
public T y;
|
public T y;
|
||||||
|
|
||||||
public Vector2Of(T x, T y)
|
public Vector2Of(T x, T y) {
|
||||||
{
|
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Vector2Int : Vector2Of<int>
|
public class Vector2Int : Vector2Of<int> {
|
||||||
{
|
|
||||||
public Vector2Int(int x, int y) : base(x, y) { }
|
public Vector2Int(int x, int y) : base(x, y) { }
|
||||||
|
|
||||||
public static Vector2Int operator -(Vector2Int v1, Vector2Int v2)
|
public static Vector2Int operator -(Vector2Int v1, Vector2Int v2) {
|
||||||
{
|
|
||||||
return new Vector2Int(v1.x - v2.x, v1.y - v2.y);
|
return new Vector2Int(v1.x - v2.x, v1.y - v2.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float magnitude
|
public float magnitude {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
return (float)Math.Sqrt(this.x * this.x + this.y * this.y);
|
return (float)Math.Sqrt(this.x * this.x + this.y * this.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float Distance(Vector2Int v1, Vector2Int v2)
|
public static float Distance(Vector2Int v1, Vector2Int v2) {
|
||||||
{
|
|
||||||
return (v1 - v2).magnitude;
|
return (v1 - v2).magnitude;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Vector2Float : Vector2Of<float>
|
public class Vector2Float : Vector2Of<float> {
|
||||||
{
|
|
||||||
public Vector2Float(float x, float y) : base(x, y) { }
|
public Vector2Float(float x, float y) : base(x, y) { }
|
||||||
|
|
||||||
public static Vector2Float operator -(Vector2Float v1, Vector2Float v2)
|
public static Vector2Float operator -(Vector2Float v1, Vector2Float v2) {
|
||||||
{
|
|
||||||
return new Vector2Float(v1.x - v2.x, v1.y - v2.y);
|
return new Vector2Float(v1.x - v2.x, v1.y - v2.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float magnitude
|
public float magnitude {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
return (float)Math.Sqrt(this.x * this.x + this.y * this.y);
|
return (float)Math.Sqrt(this.x * this.x + this.y * this.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float Distance(Vector2Float v1, Vector2Float v2)
|
public static float Distance(Vector2Float v1, Vector2Float v2) {
|
||||||
{
|
|
||||||
return (v1 - v2).magnitude;
|
return (v1 - v2).magnitude;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,8 +52,7 @@ namespace LinearAlgebra
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 2-dimensional vectors
|
/// 2-dimensional vectors
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public struct Vector2 : IEquatable<Vector2>
|
public struct Vector2 : IEquatable<Vector2> {
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The right axis of the vector
|
/// The right axis of the vector
|
||||||
@ -83,8 +69,7 @@ namespace LinearAlgebra
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="x">x axis value</param>
|
/// <param name="x">x axis value</param>
|
||||||
/// <param name="y">y axis value</param>
|
/// <param name="y">y axis value</param>
|
||||||
public Vector2(float x, float y)
|
public Vector2(float x, float y) {
|
||||||
{
|
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
@ -129,10 +114,8 @@ namespace LinearAlgebra
|
|||||||
/// The squared length is computationally simpler than the real length.
|
/// The squared length is computationally simpler than the real length.
|
||||||
/// Think of Pythagoras A^2 + B^2 = C^2.
|
/// Think of Pythagoras A^2 + B^2 = C^2.
|
||||||
/// This leaves out the calculation of the squared root of C.
|
/// This leaves out the calculation of the squared root of C.
|
||||||
public float sqrMagnitude
|
public float sqrMagnitude {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
float d = x * x + y * y;
|
float d = x * x + y * y;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@ -142,10 +125,8 @@ namespace LinearAlgebra
|
|||||||
/// The length of this vector
|
/// The length of this vector
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The length of this vector</returns>
|
/// <returns>The length of this vector</returns>
|
||||||
public float magnitude
|
public float magnitude {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
float d = (float)Math.Sqrt(x * x + y * y);
|
float d = (float)Math.Sqrt(x * x + y * y);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@ -155,10 +136,8 @@ namespace LinearAlgebra
|
|||||||
/// Convert the vector to a length of a 1
|
/// Convert the vector to a length of a 1
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The vector with length 1</returns>
|
/// <returns>The vector with length 1</returns>
|
||||||
public Vector2 normalized
|
public Vector2 normalized {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
float l = magnitude;
|
float l = magnitude;
|
||||||
Vector2 v = zero;
|
Vector2 v = zero;
|
||||||
if (l > Float.epsilon)
|
if (l > Float.epsilon)
|
||||||
@ -173,8 +152,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="v1">The first vector</param>
|
/// <param name="v1">The first vector</param>
|
||||||
/// <param name="v2">The second vector</param>
|
/// <param name="v2">The second vector</param>
|
||||||
/// <returns>The result of adding the two vectors</returns>
|
/// <returns>The result of adding the two vectors</returns>
|
||||||
public static Vector2 operator +(Vector2 v1, Vector2 v2)
|
public static Vector2 operator +(Vector2 v1, Vector2 v2) {
|
||||||
{
|
|
||||||
Vector2 v = new Vector2(v1.x + v2.x, v1.y + v2.y);
|
Vector2 v = new Vector2(v1.x + v2.x, v1.y + v2.y);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -185,8 +163,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="v1">The first vector</param>
|
/// <param name="v1">The first vector</param>
|
||||||
/// <param name="v2">The second vector</param>
|
/// <param name="v2">The second vector</param>
|
||||||
/// <returns>The result of adding the two vectors</returns>
|
/// <returns>The result of adding the two vectors</returns>
|
||||||
public static Vector2 operator -(Vector2 v1, Vector2 v2)
|
public static Vector2 operator -(Vector2 v1, Vector2 v2) {
|
||||||
{
|
|
||||||
Vector2 v = new Vector2(v1.x - v2.x, v1.y - v2.y);
|
Vector2 v = new Vector2(v1.x - v2.x, v1.y - v2.y);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -197,8 +174,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="v1">The vector to negate</param>
|
/// <param name="v1">The vector to negate</param>
|
||||||
/// <returns>The negated vector</returns>
|
/// <returns>The negated vector</returns>
|
||||||
/// This will result in a vector pointing in the opposite direction
|
/// This will result in a vector pointing in the opposite direction
|
||||||
public static Vector2 operator -(Vector2 v1)
|
public static Vector2 operator -(Vector2 v1) {
|
||||||
{
|
|
||||||
Vector2 v = new Vector2(-v1.x, -v1.y);
|
Vector2 v = new Vector2(-v1.x, -v1.y);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -210,8 +186,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="f">The scaling factor</param>
|
/// <param name="f">The scaling factor</param>
|
||||||
/// <returns>The scaled vector</returns>
|
/// <returns>The scaled vector</returns>
|
||||||
/// Each component of the vector will be multipled with the same factor.
|
/// Each component of the vector will be multipled with the same factor.
|
||||||
public static Vector2 operator *(Vector2 v1, float f)
|
public static Vector2 operator *(Vector2 v1, float f) {
|
||||||
{
|
|
||||||
Vector2 v = new Vector2(v1.x * f, v1.y * f);
|
Vector2 v = new Vector2(v1.x * f, v1.y * f);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -223,8 +198,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="v1">The vector to scale</param>
|
/// <param name="v1">The vector to scale</param>
|
||||||
/// <returns>The scaled vector</returns>
|
/// <returns>The scaled vector</returns>
|
||||||
/// Each component of the vector will be multipled with the same factor.
|
/// Each component of the vector will be multipled with the same factor.
|
||||||
public static Vector2 operator *(float f, Vector2 v1)
|
public static Vector2 operator *(float f, Vector2 v1) {
|
||||||
{
|
|
||||||
Vector2 v = new Vector2(f * v1.x, f * v1.y);
|
Vector2 v = new Vector2(f * v1.x, f * v1.y);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -236,8 +210,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="f">The scaling factor</param>
|
/// <param name="f">The scaling factor</param>
|
||||||
/// <returns>The scaled vector</returns>
|
/// <returns>The scaled vector</returns>
|
||||||
/// Each component of the vector will be devided by the same factor.
|
/// Each component of the vector will be devided by the same factor.
|
||||||
public static Vector2 operator /(Vector2 v1, float f)
|
public static Vector2 operator /(Vector2 v1, float f) {
|
||||||
{
|
|
||||||
Vector2 v = new Vector2(v1.x / f, v1.y / f);
|
Vector2 v = new Vector2(v1.x / f, v1.y / f);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -254,8 +227,7 @@ namespace LinearAlgebra
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj">The object to compare to</param>
|
/// <param name="obj">The object to compare to</param>
|
||||||
/// <returns><em>false</em> when the object is not a Vector2 or does not have equal values</returns>
|
/// <returns><em>false</em> when the object is not a Vector2 or does not have equal values</returns>
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj) {
|
||||||
{
|
|
||||||
if (!(obj is Vector2 v))
|
if (!(obj is Vector2 v))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -271,8 +243,7 @@ namespace LinearAlgebra
|
|||||||
/// Note that this uses a Float equality check which cannot be not exact in all cases.
|
/// Note that this uses a Float equality check which cannot be not exact in all cases.
|
||||||
/// In most cases it is better to check if the Vector2.Distance between the vectors is smaller than Float.epsilon
|
/// In most cases it is better to check if the Vector2.Distance between the vectors is smaller than Float.epsilon
|
||||||
/// Or more efficient: (v1 - v2).sqrMagnitude < Float.sqrEpsilon
|
/// Or more efficient: (v1 - v2).sqrMagnitude < Float.sqrEpsilon
|
||||||
public static bool operator ==(Vector2 v1, Vector2 v2)
|
public static bool operator ==(Vector2 v1, Vector2 v2) {
|
||||||
{
|
|
||||||
return (v1.x == v2.x && v1.y == v2.y);
|
return (v1.x == v2.x && v1.y == v2.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,8 +256,7 @@ namespace LinearAlgebra
|
|||||||
/// Note that this uses a Float equality check which cannot be not exact in all case.
|
/// Note that this uses a Float equality check which cannot be not exact in all case.
|
||||||
/// In most cases it is better to check if the Vector2.Distance between the vectors is smaller than Float.epsilon.
|
/// In most cases it is better to check if the Vector2.Distance between the vectors is smaller than Float.epsilon.
|
||||||
/// Or more efficient: (v1 - v2).sqrMagnitude < Float.sqrEpsilon
|
/// Or more efficient: (v1 - v2).sqrMagnitude < Float.sqrEpsilon
|
||||||
public static bool operator !=(Vector2 v1, Vector2 v2)
|
public static bool operator !=(Vector2 v1, Vector2 v2) {
|
||||||
{
|
|
||||||
return (v1.x != v2.x || v1.y != v2.y);
|
return (v1.x != v2.x || v1.y != v2.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,8 +264,7 @@ namespace LinearAlgebra
|
|||||||
/// Get an hash code for the vector
|
/// Get an hash code for the vector
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The hash code</returns>
|
/// <returns>The hash code</returns>
|
||||||
public override int GetHashCode()
|
public override int GetHashCode() {
|
||||||
{
|
|
||||||
return (x, y).GetHashCode();
|
return (x, y).GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,8 +274,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="v1">The first vector</param>
|
/// <param name="v1">The first vector</param>
|
||||||
/// <param name="v2">The second vector</param>
|
/// <param name="v2">The second vector</param>
|
||||||
/// <returns>The distance between the two vectors</returns>
|
/// <returns>The distance between the two vectors</returns>
|
||||||
public static float Distance(Vector2 v1, Vector2 v2)
|
public static float Distance(Vector2 v1, Vector2 v2) {
|
||||||
{
|
|
||||||
float x = v1.x - v2.x;
|
float x = v1.x - v2.x;
|
||||||
float y = v1.y - v2.y;
|
float y = v1.y - v2.y;
|
||||||
float d = (float)Math.Sqrt(x * x + y * y);
|
float d = (float)Math.Sqrt(x * x + y * y);
|
||||||
@ -319,8 +287,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="v1">The first vector</param>
|
/// <param name="v1">The first vector</param>
|
||||||
/// <param name="v2">The second vector</param>
|
/// <param name="v2">The second vector</param>
|
||||||
/// <returns>The dot product of the two vectors</returns>
|
/// <returns>The dot product of the two vectors</returns>
|
||||||
public static float Dot(Vector2 v1, Vector2 v2)
|
public static float Dot(Vector2 v1, Vector2 v2) {
|
||||||
{
|
|
||||||
return v1.x * v2.x + v1.y * v2.y;
|
return v1.x * v2.x + v1.y * v2.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,8 +301,7 @@ namespace LinearAlgebra
|
|||||||
/// The factor f is unclamped. Value 0 matches the *v1* vector, Value 1
|
/// The factor f is unclamped. Value 0 matches the *v1* vector, Value 1
|
||||||
/// matches the *v2* vector Value -1 is *v1* vector minus the difference
|
/// matches the *v2* vector Value -1 is *v1* vector minus the difference
|
||||||
/// between *v1* and *v2* etc.
|
/// between *v1* and *v2* etc.
|
||||||
public static Vector2 Lerp(Vector2 v1, Vector2 v2, float f)
|
public static Vector2 Lerp(Vector2 v1, Vector2 v2, float f) {
|
||||||
{
|
|
||||||
Vector2 v = v1 + (v2 - v1) * f;
|
Vector2 v = v1 + (v2 - v1) * f;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@ -347,8 +313,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="to">The ending vector</param>
|
/// <param name="to">The ending vector</param>
|
||||||
/// <param name="axis">The axis to rotate around</param>
|
/// <param name="axis">The axis to rotate around</param>
|
||||||
/// <returns>The signed angle in degrees</returns>
|
/// <returns>The signed angle in degrees</returns>
|
||||||
public static float SignedAngle(Vector2 from, Vector2 to)
|
public static float SignedAngle(Vector2 from, Vector2 to) {
|
||||||
{
|
|
||||||
//float sign = Math.Sign(v1.y * v2.x - v1.x * v2.y);
|
//float sign = Math.Sign(v1.y * v2.x - v1.x * v2.y);
|
||||||
//return Vector2.Angle(v1, v2) * sign;
|
//return Vector2.Angle(v1, v2) * sign;
|
||||||
|
|
||||||
@ -371,15 +336,13 @@ namespace LinearAlgebra
|
|||||||
/// <param name="v1">The vector to rotate</param>
|
/// <param name="v1">The vector to rotate</param>
|
||||||
/// <param name="angle">The angle in degrees</param>
|
/// <param name="angle">The angle in degrees</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Vector2 Rotate(Vector2 v1, float angle)
|
public static Vector2 Rotate(Vector2 v1, float angle) {
|
||||||
{
|
|
||||||
float sin = (float)Math.Sin(angle * Angle.Deg2Rad);
|
float sin = (float)Math.Sin(angle * Angle.Deg2Rad);
|
||||||
float cos = (float)Math.Cos(angle * Angle.Deg2Rad);
|
float cos = (float)Math.Cos(angle * Angle.Deg2Rad);
|
||||||
|
|
||||||
float tx = v1.x;
|
float tx = v1.x;
|
||||||
float ty = v1.y;
|
float ty = v1.y;
|
||||||
Vector2 v = new Vector2()
|
Vector2 v = new Vector2() {
|
||||||
{
|
|
||||||
x = (cos * tx) - (sin * ty),
|
x = (cos * tx) - (sin * ty),
|
||||||
y = (sin * tx) + (cos * ty)
|
y = (sin * tx) + (cos * ty)
|
||||||
};
|
};
|
||||||
@ -393,8 +356,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="v2">The second vector</param>
|
/// <param name="v2">The second vector</param>
|
||||||
/// <returns>The resulting factor in interval [0..1]</returns>
|
/// <returns>The resulting factor in interval [0..1]</returns>
|
||||||
/// Vectors a and b must be normalized
|
/// Vectors a and b must be normalized
|
||||||
public static float ToFactor(Vector2 v1, Vector2 v2)
|
public static float ToFactor(Vector2 v1, Vector2 v2) {
|
||||||
{
|
|
||||||
return (1 - Vector2.Dot(v1, v2)) / 2;
|
return (1 - Vector2.Dot(v1, v2)) / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
#if !UNITY_5_3_OR_NEWER
|
#if !UNITY_5_3_OR_NEWER
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace LinearAlgebra
|
namespace LinearAlgebra {
|
||||||
{
|
public class Vector3Of<T> {
|
||||||
public class Vector3Of<T>
|
|
||||||
{
|
|
||||||
public T x;
|
public T x;
|
||||||
public T y;
|
public T y;
|
||||||
public T z;
|
public T z;
|
||||||
|
|
||||||
public Vector3Of(T x, T y, T z)
|
public Vector3Of(T x, T y, T z) {
|
||||||
{
|
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
@ -21,16 +18,13 @@ namespace LinearAlgebra
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Vector3Int : Vector3Of<int>
|
public class Vector3Int : Vector3Of<int> {
|
||||||
{
|
|
||||||
public Vector3Int(int x, int y, int z) : base(x, y, z) { }
|
public Vector3Int(int x, int y, int z) : base(x, y, z) { }
|
||||||
}
|
}
|
||||||
public class Vector3Float : Vector3Of<float>
|
public class Vector3Float : Vector3Of<float> {
|
||||||
{
|
|
||||||
public Vector3Float(float x, float y, float z) : base(x, y, z) { }
|
public Vector3Float(float x, float y, float z) : base(x, y, z) { }
|
||||||
|
|
||||||
public float magnitude
|
public float magnitude {
|
||||||
{
|
|
||||||
get => (float)Math.Sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
|
get => (float)Math.Sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,8 +33,7 @@ namespace LinearAlgebra
|
|||||||
/// 3-dimensional vectors
|
/// 3-dimensional vectors
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// This uses the right-handed coordinate system.
|
/// This uses the right-handed coordinate system.
|
||||||
public struct Vector3 : IEquatable<Vector3>
|
public struct Vector3 : IEquatable<Vector3> {
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The right axis of the vector
|
/// The right axis of the vector
|
||||||
@ -61,8 +54,7 @@ namespace LinearAlgebra
|
|||||||
/// <param name="x">x axis value</param>
|
/// <param name="x">x axis value</param>
|
||||||
/// <param name="y">y axis value</param>
|
/// <param name="y">y axis value</param>
|
||||||
/// <param name="z">z axis value</param>
|
/// <param name="z">z axis value</param>
|
||||||
public Vector3(float x, float y, float z)
|
public Vector3(float x, float y, float z) {
|
||||||
{
|
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
this.z = z;
|
this.z = z;
|
||||||
@ -101,19 +93,15 @@ namespace LinearAlgebra
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly Vector3 forward = new Vector3(0, 1, 0);
|
public static readonly Vector3 forward = new Vector3(0, 1, 0);
|
||||||
|
|
||||||
public float magnitude
|
public readonly float magnitude {
|
||||||
{
|
get {
|
||||||
get
|
float d = (float)Math.Sqrt(x * x + y * y + z * z);
|
||||||
{
|
|
||||||
float d = (float)Math.Sqrt(x * x + y * y);
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3 normalized
|
public Vector3 normalized {
|
||||||
{
|
get {
|
||||||
get
|
|
||||||
{
|
|
||||||
float l = magnitude;
|
float l = magnitude;
|
||||||
Vector3 v = zero;
|
Vector3 v = zero;
|
||||||
if (l > Float.epsilon)
|
if (l > Float.epsilon)
|
||||||
@ -122,79 +110,66 @@ namespace LinearAlgebra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3 operator +(Vector3 v1, Vector3 v2)
|
public static Vector3 operator +(Vector3 v1, Vector3 v2) {
|
||||||
{
|
|
||||||
Vector3 v = new Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
|
Vector3 v = new Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3 operator -(Vector3 v1, Vector3 v2)
|
public static Vector3 operator -(Vector3 v1, Vector3 v2) {
|
||||||
{
|
|
||||||
Vector3 v = new Vector3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
|
Vector3 v = new Vector3(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3 operator -(Vector3 v1)
|
public static Vector3 operator -(Vector3 v1) {
|
||||||
{
|
|
||||||
Vector3 v = new Vector3(-v1.x, -v1.y, -v1.z);
|
Vector3 v = new Vector3(-v1.x, -v1.y, -v1.z);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3 operator *(Vector3 v1, float d)
|
public static Vector3 operator *(Vector3 v1, float d) {
|
||||||
{
|
|
||||||
Vector3 v = new Vector3(v1.x * d, v1.y * d, v1.z * d);
|
Vector3 v = new Vector3(v1.x * d, v1.y * d, v1.z * d);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3 operator *(float d, Vector3 v1)
|
public static Vector3 operator *(float d, Vector3 v1) {
|
||||||
{
|
|
||||||
Vector3 v = new Vector3(d * v1.x, d * v1.y, d * v1.z);
|
Vector3 v = new Vector3(d * v1.x, d * v1.y, d * v1.z);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3 operator /(Vector3 v1, float d)
|
public static Vector3 operator /(Vector3 v1, float d) {
|
||||||
{
|
|
||||||
Vector3 v = new Vector3(v1.x / d, v1.y / d, v1.z / d);
|
Vector3 v = new Vector3(v1.x / d, v1.y / d, v1.z / d);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(Vector3 v) => (x == v.x && y == v.y && z == v.z);
|
public bool Equals(Vector3 v) => (x == v.x && y == v.y && z == v.z);
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj) {
|
||||||
{
|
|
||||||
if (!(obj is Vector3 v))
|
if (!(obj is Vector3 v))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return (x == v.x && y == v.y && z == v.z);
|
return (x == v.x && y == v.y && z == v.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator ==(Vector3 v1, Vector3 v2)
|
public static bool operator ==(Vector3 v1, Vector3 v2) {
|
||||||
{
|
|
||||||
return (v1.x == v2.x && v1.y == v2.y && v1.z == v2.z);
|
return (v1.x == v2.x && v1.y == v2.y && v1.z == v2.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator !=(Vector3 v1, Vector3 v2)
|
public static bool operator !=(Vector3 v1, Vector3 v2) {
|
||||||
{
|
|
||||||
return (v1.x != v2.x || v1.y != v2.y || v1.z != v2.z);
|
return (v1.x != v2.x || v1.y != v2.y || v1.z != v2.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode() {
|
||||||
{
|
|
||||||
return (x, y, z).GetHashCode();
|
return (x, y, z).GetHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float Distance(Vector3 v1, Vector3 v2)
|
public static float Distance(Vector3 v1, Vector3 v2) {
|
||||||
{
|
|
||||||
return (v2 - v1).magnitude;
|
return (v2 - v1).magnitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float Dot(Vector3 v1, Vector3 v2)
|
public static float Dot(Vector3 v1, Vector3 v2) {
|
||||||
{
|
|
||||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Vector3 Lerp(Vector3 v1, Vector3 v2, float f)
|
public static Vector3 Lerp(Vector3 v1, Vector3 v2, float f) {
|
||||||
{
|
|
||||||
Vector3 v = v1 + (v2 - v1) * f;
|
Vector3 v = v1 + (v2 - v1) * f;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace LinearAlgebra
|
namespace LinearAlgebra {
|
||||||
{
|
|
||||||
|
|
||||||
public class float16
|
public class float16 {
|
||||||
{
|
|
||||||
//
|
//
|
||||||
// FILE: float16.cpp
|
// FILE: float16.cpp
|
||||||
// AUTHOR: Rob Tillaart
|
// AUTHOR: Rob Tillaart
|
||||||
@ -16,14 +14,12 @@ namespace LinearAlgebra
|
|||||||
|
|
||||||
public float16() { _value = 0; }
|
public float16() { _value = 0; }
|
||||||
|
|
||||||
public float16(float f)
|
public float16(float f) {
|
||||||
{
|
|
||||||
//_value = f32tof16(f);
|
//_value = f32tof16(f);
|
||||||
_value = F32ToF16__(f);
|
_value = F32ToF16__(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float toFloat()
|
public float toFloat() {
|
||||||
{
|
|
||||||
return f16tof32(_value);
|
return f16tof32(_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,8 +153,7 @@ namespace LinearAlgebra
|
|||||||
//
|
//
|
||||||
// CORE CONVERSION
|
// CORE CONVERSION
|
||||||
//
|
//
|
||||||
float f16tof32(ushort _value)
|
float f16tof32(ushort _value) {
|
||||||
{
|
|
||||||
//ushort sgn;
|
//ushort sgn;
|
||||||
ushort man;
|
ushort man;
|
||||||
int exp;
|
int exp;
|
||||||
@ -173,13 +168,11 @@ namespace LinearAlgebra
|
|||||||
//Debug.Log($"{sgn} {exp} {man}");
|
//Debug.Log($"{sgn} {exp} {man}");
|
||||||
|
|
||||||
// ZERO
|
// ZERO
|
||||||
if ((_value & 0x7FFF) == 0)
|
if ((_value & 0x7FFF) == 0) {
|
||||||
{
|
|
||||||
return sgn ? -0 : 0;
|
return sgn ? -0 : 0;
|
||||||
}
|
}
|
||||||
// NAN & INF
|
// NAN & INF
|
||||||
if (exp == 0x001F)
|
if (exp == 0x001F) {
|
||||||
{
|
|
||||||
if (man == 0)
|
if (man == 0)
|
||||||
return sgn ? float.NegativeInfinity : float.PositiveInfinity; //-INFINITY : INFINITY;
|
return sgn ? float.NegativeInfinity : float.PositiveInfinity; //-INFINITY : INFINITY;
|
||||||
else
|
else
|
||||||
@ -193,50 +186,43 @@ namespace LinearAlgebra
|
|||||||
f = 1;
|
f = 1;
|
||||||
|
|
||||||
// PROCESS MANTISSE
|
// PROCESS MANTISSE
|
||||||
for (int i = 9; i >= 0; i--)
|
for (int i = 9; i >= 0; i--) {
|
||||||
{
|
|
||||||
f *= 2;
|
f *= 2;
|
||||||
if ((man & (1 << i)) != 0)
|
if ((man & (1 << i)) != 0)
|
||||||
f = f + 1;
|
f = f + 1;
|
||||||
}
|
}
|
||||||
//Debug.Log($"{f}");
|
//Debug.Log($"{f}");
|
||||||
f = f * (float)Math.Pow(2.0f, exp - 25);
|
f = f * (float)Math.Pow(2.0f, exp - 25);
|
||||||
if (exp == 0)
|
if (exp == 0) {
|
||||||
{
|
|
||||||
f = f * (float)Math.Pow(2.0f, -13); // 5.96046447754e-8;
|
f = f * (float)Math.Pow(2.0f, -13); // 5.96046447754e-8;
|
||||||
}
|
}
|
||||||
//Debug.Log($"{f}");
|
//Debug.Log($"{f}");
|
||||||
return sgn ? -f : f;
|
return sgn ? -f : f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint SingleToInt32Bits(float value)
|
public static uint SingleToInt32Bits(float value) {
|
||||||
{
|
|
||||||
byte[] bytes = BitConverter.GetBytes(value);
|
byte[] bytes = BitConverter.GetBytes(value);
|
||||||
if (BitConverter.IsLittleEndian)
|
if (BitConverter.IsLittleEndian)
|
||||||
Array.Reverse(bytes); // If the system is little-endian, reverse the byte order
|
Array.Reverse(bytes); // If the system is little-endian, reverse the byte order
|
||||||
return BitConverter.ToUInt32(bytes, 0);
|
return BitConverter.ToUInt32(bytes, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ushort F32ToF16__(float f)
|
public ushort F32ToF16__(float f) {
|
||||||
{
|
|
||||||
uint t = BitConverter.ToUInt32(BitConverter.GetBytes(f), 0);
|
uint t = BitConverter.ToUInt32(BitConverter.GetBytes(f), 0);
|
||||||
ushort man = (ushort)((t & 0x007FFFFF) >> 12);
|
ushort man = (ushort)((t & 0x007FFFFF) >> 12);
|
||||||
int exp = (int)((t & 0x7F800000) >> 23);
|
int exp = (int)((t & 0x7F800000) >> 23);
|
||||||
bool sgn = (t & 0x80000000) != 0;
|
bool sgn = (t & 0x80000000) != 0;
|
||||||
|
|
||||||
// handle 0
|
// handle 0
|
||||||
if ((t & 0x7FFFFFFF) == 0)
|
if ((t & 0x7FFFFFFF) == 0) {
|
||||||
{
|
|
||||||
return sgn ? (ushort)0x8000 : (ushort)0x0000;
|
return sgn ? (ushort)0x8000 : (ushort)0x0000;
|
||||||
}
|
}
|
||||||
// denormalized float32 does not fit in float16
|
// denormalized float32 does not fit in float16
|
||||||
if (exp == 0x00)
|
if (exp == 0x00) {
|
||||||
{
|
|
||||||
return sgn ? (ushort)0x8000 : (ushort)0x0000;
|
return sgn ? (ushort)0x8000 : (ushort)0x0000;
|
||||||
}
|
}
|
||||||
// handle infinity & NAN
|
// handle infinity & NAN
|
||||||
if (exp == 0x00FF)
|
if (exp == 0x00FF) {
|
||||||
{
|
|
||||||
if (man != 0)
|
if (man != 0)
|
||||||
return 0xFE00; // NAN
|
return 0xFE00; // NAN
|
||||||
return sgn ? (ushort)0xFC00 : (ushort)0x7C00; // -INF : INF
|
return sgn ? (ushort)0xFC00 : (ushort)0x7C00; // -INF : INF
|
||||||
@ -245,13 +231,11 @@ namespace LinearAlgebra
|
|||||||
// normal numbers
|
// normal numbers
|
||||||
exp = exp - 127 + 15;
|
exp = exp - 127 + 15;
|
||||||
// overflow does not fit => INF
|
// overflow does not fit => INF
|
||||||
if (exp > 30)
|
if (exp > 30) {
|
||||||
{
|
|
||||||
return sgn ? (ushort)0xFC00 : (ushort)0x7C00; // -INF : INF
|
return sgn ? (ushort)0xFC00 : (ushort)0x7C00; // -INF : INF
|
||||||
}
|
}
|
||||||
// subnormal numbers
|
// subnormal numbers
|
||||||
if (exp < -38)
|
if (exp < -38) {
|
||||||
{
|
|
||||||
return sgn ? (ushort)0x8000 : (ushort)0x0000; // -0 or 0 ? just 0 ?
|
return sgn ? (ushort)0x8000 : (ushort)0x0000; // -0 or 0 ? just 0 ?
|
||||||
}
|
}
|
||||||
if (exp <= 0) // subnormal
|
if (exp <= 0) // subnormal
|
||||||
@ -276,8 +260,7 @@ namespace LinearAlgebra
|
|||||||
}
|
}
|
||||||
|
|
||||||
//This function is faulty!!!!
|
//This function is faulty!!!!
|
||||||
ushort f32tof16(float f)
|
ushort f32tof16(float f) {
|
||||||
{
|
|
||||||
//uint t = *(uint*)&f;
|
//uint t = *(uint*)&f;
|
||||||
//uint t = (uint)BitConverter.SingleToInt32Bits(f);
|
//uint t = (uint)BitConverter.SingleToInt32Bits(f);
|
||||||
uint t = SingleToInt32Bits(f);
|
uint t = SingleToInt32Bits(f);
|
||||||
@ -287,18 +270,15 @@ namespace LinearAlgebra
|
|||||||
bool sgn = (t & 0x80000000) != 0;
|
bool sgn = (t & 0x80000000) != 0;
|
||||||
|
|
||||||
// handle 0
|
// handle 0
|
||||||
if ((t & 0x7FFFFFFF) == 0)
|
if ((t & 0x7FFFFFFF) == 0) {
|
||||||
{
|
|
||||||
return sgn ? (ushort)0x8000 : (ushort)0x0000;
|
return sgn ? (ushort)0x8000 : (ushort)0x0000;
|
||||||
}
|
}
|
||||||
// denormalized float32 does not fit in float16
|
// denormalized float32 does not fit in float16
|
||||||
if (exp == 0x00)
|
if (exp == 0x00) {
|
||||||
{
|
|
||||||
return sgn ? (ushort)0x8000 : (ushort)0x0000;
|
return sgn ? (ushort)0x8000 : (ushort)0x0000;
|
||||||
}
|
}
|
||||||
// handle infinity & NAN
|
// handle infinity & NAN
|
||||||
if (exp == 0x00FF)
|
if (exp == 0x00FF) {
|
||||||
{
|
|
||||||
if (man != 0)
|
if (man != 0)
|
||||||
return 0xFE00; // NAN
|
return 0xFE00; // NAN
|
||||||
return sgn ? (ushort)0xFC00 : (ushort)0x7C00; // -INF : INF
|
return sgn ? (ushort)0xFC00 : (ushort)0x7C00; // -INF : INF
|
||||||
@ -307,13 +287,11 @@ namespace LinearAlgebra
|
|||||||
// normal numbers
|
// normal numbers
|
||||||
exp = (short)(exp - 127 + 15);
|
exp = (short)(exp - 127 + 15);
|
||||||
// overflow does not fit => INF
|
// overflow does not fit => INF
|
||||||
if (exp > 30)
|
if (exp > 30) {
|
||||||
{
|
|
||||||
return sgn ? (ushort)0xFC00 : (ushort)0x7C00; // -INF : INF
|
return sgn ? (ushort)0xFC00 : (ushort)0x7C00; // -INF : INF
|
||||||
}
|
}
|
||||||
// subnormal numbers
|
// subnormal numbers
|
||||||
if (exp < -38)
|
if (exp < -38) {
|
||||||
{
|
|
||||||
return sgn ? (ushort)0x8000 : (ushort)0x0000; // -0 or 0 ? just 0 ?
|
return sgn ? (ushort)0x8000 : (ushort)0x0000; // -0 or 0 ? just 0 ?
|
||||||
}
|
}
|
||||||
if (exp <= 0) // subnormal
|
if (exp <= 0) // subnormal
|
||||||
|
@ -11,7 +11,7 @@ namespace LinearAlgebra.Test
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Test_Normalize()
|
public void Normalize()
|
||||||
{
|
{
|
||||||
float r = 0;
|
float r = 0;
|
||||||
|
|
||||||
|
28
LinearAlgebra/test/SphericalTest.cs
Normal file
28
LinearAlgebra/test/SphericalTest.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace LinearAlgebra.Test {
|
||||||
|
public class SphericalTest {
|
||||||
|
[SetUp]
|
||||||
|
public void Setup() {
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FromVector3() {
|
||||||
|
Vector3 v = new(0, 0, 1);
|
||||||
|
Spherical s = Spherical.FromVector3(v);
|
||||||
|
Assert.AreEqual(1.0f, s.distance, "s.distance 0 0 1");
|
||||||
|
Assert.AreEqual(0.0f, s.direction.horizontal, "s.hor 0 0 1");
|
||||||
|
Assert.AreEqual(0.0f, s.direction.vertical, "s.vert 0 0 1");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Addition() {
|
||||||
|
Spherical v1 = Spherical.Degrees(1, 45, 0);
|
||||||
|
Spherical v2 = Spherical.zero;
|
||||||
|
Spherical r = Spherical.zero;
|
||||||
|
|
||||||
|
r = v1 + v2;
|
||||||
|
Assert.AreEqual(v1.distance, r.distance, "Addition(0,0,0)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@ namespace RoboidControl {
|
|||||||
float distance = ReceiveFloat16(data, ref ix);
|
float distance = ReceiveFloat16(data, ref ix);
|
||||||
float horizontal = ReceiveAngle8(data, ref ix);
|
float horizontal = ReceiveAngle8(data, ref ix);
|
||||||
float vertical = ReceiveAngle8(data, ref ix);
|
float vertical = ReceiveAngle8(data, ref ix);
|
||||||
Spherical v = new Spherical(distance, horizontal, vertical);
|
Spherical v = Spherical.Degrees(distance, horizontal, vertical);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ namespace RoboidControl.test {
|
|||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Test_Participant() {
|
public void Test_Participant() {
|
||||||
LocalParticipant participant = new LocalParticipant("127.0.0.1", 7682);
|
ParticipantUDP participant = new ParticipantUDP("127.0.0.1", 7682);
|
||||||
|
|
||||||
ulong milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
ulong milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||||
ulong startTime = milliseconds;
|
ulong startTime = milliseconds;
|
||||||
@ -46,7 +46,7 @@ namespace RoboidControl.test {
|
|||||||
[Test]
|
[Test]
|
||||||
public void Test_SiteParticipant() {
|
public void Test_SiteParticipant() {
|
||||||
SiteServer siteServer = new SiteServer(7681);
|
SiteServer siteServer = new SiteServer(7681);
|
||||||
LocalParticipant participant = new LocalParticipant("127.0.0.1", 7681);
|
ParticipantUDP participant = new ParticipantUDP("127.0.0.1", 7681);
|
||||||
|
|
||||||
ulong milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
ulong milliseconds = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||||
ulong startTime = milliseconds;
|
ulong startTime = milliseconds;
|
||||||
@ -64,7 +64,7 @@ namespace RoboidControl.test {
|
|||||||
[Test]
|
[Test]
|
||||||
public void Test_ThingMsg() {
|
public void Test_ThingMsg() {
|
||||||
SiteServer siteServer = new SiteServer(7681);
|
SiteServer siteServer = new SiteServer(7681);
|
||||||
LocalParticipant participant = new LocalParticipant("127.0.0.1");
|
ParticipantUDP participant = new ParticipantUDP("127.0.0.1");
|
||||||
Thing thing = new Thing(participant) {
|
Thing thing = new Thing(participant) {
|
||||||
name = "First Thing",
|
name = "First Thing",
|
||||||
modelUrl = "https://passer.life/extras/ant.jpg"
|
modelUrl = "https://passer.life/extras/ant.jpg"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user