110 lines
3.9 KiB
C#

using System;
#if UNITY_5_3_OR_NEWER
using Vector3Float = UnityEngine.Vector3;
#endif
namespace LinearAlgebra {
/// <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 vertical;
public Direction() {
horizontal = 0;
vertical = 0;
}
public Direction(Angle horizontal, Angle vertical) {
this.horizontal = horizontal.inDegrees;
this.vertical = vertical.inDegrees;
this.Normalize();
}
public static Direction Degrees(float horizontal, float vertical) {
Direction d = new() {
horizontal = horizontal,
vertical = vertical
};
d.Normalize();
return d;
}
public static Direction Radians(float horizontal, float vertical) {
Direction d = new() {
horizontal = horizontal * Angle.Rad2Deg,
vertical = vertical * Angle.Rad2Deg
};
d.Normalize();
return d;
}
public readonly static Direction forward = Degrees(0, 0);
public readonly static Direction backward = Degrees(-180, 0);
public readonly static Direction up = Degrees(0, 90);
public readonly static Direction down = Degrees(0, -90);
public readonly static Direction left = Degrees(-90, 0);
public readonly static Direction right = Degrees(90, 0);
public void Normalize() {
this.vertical = Angles.Normalize(this.vertical);
if (this.vertical > 90 || this.vertical < -90) {
this.horizontal += 180;
this.vertical = 180 - this.vertical;
}
this.horizontal = Angles.Normalize(this.horizontal);
}
public Vector3Float ToVector3() {
float verticalRad = ((float)Math.PI / 2) - this.vertical * Angle.Deg2Rad;
float horizontalRad = this.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 = sinVertical * sinHorizontal;
float y = cosVertical;
float z = sinVertical * cosHorizontal;
Vector3Float v = new(x, y, z);
return v;
}
public static bool operator ==(Direction d1, Direction d2) {
bool horizontalEq = d1.horizontal == d2.horizontal;
bool verticalEq = d1.vertical == d2.vertical;
return horizontalEq && verticalEq;
}
public static bool operator !=(Direction d1, Direction d2) {
bool horizontalNEq = d1.horizontal != d2.horizontal;
bool verticalNEq = d1.vertical != d2.vertical;
return horizontalNEq || verticalNEq;
}
public override bool Equals(object obj) {
if (obj is not Direction d)
return false;
bool horizontalEq = this.horizontal == d.horizontal;
bool verticalEq = this.vertical == d.vertical;
return horizontalEq && verticalEq;
}
public override int GetHashCode() {
return (this.horizontal, this.vertical).GetHashCode();
}
}
}