|
|
|
@@ -4,22 +4,27 @@
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
#include <functional>
|
|
|
|
|
// TODO: Make GLM redundant, and remove it thereafter.
|
|
|
|
|
#include <glm/glm.hpp>
|
|
|
|
|
#include <glm/ext/scalar_constants.hpp>
|
|
|
|
|
|
|
|
|
|
// TODO: SIMD operations for GPU math (parallelization!!)
|
|
|
|
|
|
|
|
|
|
// Dawsh Linear Algebra Library - Everything you need for 3D math
|
|
|
|
|
namespace LinearAlgebra {
|
|
|
|
|
class Vector2;
|
|
|
|
|
class Vector3;
|
|
|
|
|
class Vector4;
|
|
|
|
|
class Angle2D;
|
|
|
|
|
class EulerAngle;
|
|
|
|
|
class AxisAngle;
|
|
|
|
|
class CoordinateFrame;
|
|
|
|
|
class Vector2; // A type representing a position in a 2-dimensional coordinate space.
|
|
|
|
|
class Vector3; // A type representing a position in a 3-dimensional coordinate space.
|
|
|
|
|
class Vector4; // A type representing a position in a 4-dimensional coordinate space.
|
|
|
|
|
class Angle2D; // Uses x,y components to represent a 2D rotation.
|
|
|
|
|
class EulerAngle; // Uses pitch,yaw,roll components to represent a 3D orientation.
|
|
|
|
|
class AxisAngle; //
|
|
|
|
|
class CoordinateFrame; //
|
|
|
|
|
class Matrix2x2;
|
|
|
|
|
class Matrix3x3;
|
|
|
|
|
class Matrix4x4;
|
|
|
|
|
class Transform2D;
|
|
|
|
|
class Transform3D;
|
|
|
|
|
class Quaternion;
|
|
|
|
|
inline float lerp(float a, float b, float t);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -31,9 +36,8 @@ namespace LinearAlgebra {
|
|
|
|
|
// But mathematically, a vector or matrix is defined by it's size, and values.
|
|
|
|
|
// Changing the value of one axis fundamentally changes the definition of the vector/matrix.
|
|
|
|
|
// So we enforce this conceptually at code level...
|
|
|
|
|
// If you're wondering how it remains performant, it only allocates a tiny space (4*n bytes for vectors) (4*n*m bytes for matrices) on the ~heap~
|
|
|
|
|
// If you're wondering how it remains performant, it only heap-allocates a tiny space (4*n bytes for vectors) (4*n*m bytes for matrices)
|
|
|
|
|
// Just Trust Me Bro - Josjh
|
|
|
|
|
|
|
|
|
|
#define MUTABLE true // Toggle This For: Ugly math, ugly code, and an ugly genital infection!
|
|
|
|
|
|
|
|
|
|
#if MUTABLE
|
|
|
|
@@ -45,9 +49,9 @@ namespace LinearAlgebra
|
|
|
|
|
|
|
|
|
|
class Vector2 {
|
|
|
|
|
public:
|
|
|
|
|
Vector2() : x(0), y(0) {}
|
|
|
|
|
Vector2(float X, float Y) : x(X), y(Y) {}
|
|
|
|
|
Vector2(const Vector2& rhs): x(rhs.x), y(rhs.y) {}
|
|
|
|
|
Vector2();
|
|
|
|
|
Vector2(float X, float Y);
|
|
|
|
|
Vector2(const Vector2& rhs);
|
|
|
|
|
Vector2(Vector2&&) = default; // Move Constructor
|
|
|
|
|
float getX() const { return x; }
|
|
|
|
|
float getY() const { return y; }
|
|
|
|
@@ -68,14 +72,16 @@ public:
|
|
|
|
|
Vector2 min(const Vector2& min) const;
|
|
|
|
|
Vector2 max(const Vector2& max) const;
|
|
|
|
|
Vector2 clamp(const Vector2& min, const Vector2& max) const;
|
|
|
|
|
|
|
|
|
|
// Returns the magnitude between the two vectors.
|
|
|
|
|
float distance(const Vector2& to) const;
|
|
|
|
|
float length() const;
|
|
|
|
|
float lengthSquared() const;
|
|
|
|
|
// Returns the length of the vector, which is sqrt(x^2 + y^2)
|
|
|
|
|
float magnitude() const;
|
|
|
|
|
// Returns a float value equal to the magnitudes of the two vectors multiplied together and then multiplied by the cosine of the angle between them.
|
|
|
|
|
// For normalized vectors, dot returns 1 if they point in exactly the same direction,
|
|
|
|
|
// -1 if they point in completely opposite directions,
|
|
|
|
|
// and 0 if the vectors are perpendicular.
|
|
|
|
|
// -1 if they point in completely opposite directions, and 0 if the vectors are perpendicular.
|
|
|
|
|
static float dot(const Vector2& lhs, const Vector2& rhs) { return lhs.dot(rhs); }
|
|
|
|
|
float dot(const Vector2& rhs) const;
|
|
|
|
|
// Projects one vector onto another and returns the result. (IDK)
|
|
|
|
@@ -120,8 +126,8 @@ public:
|
|
|
|
|
|
|
|
|
|
class Vector3 {
|
|
|
|
|
public:
|
|
|
|
|
Vector3() : x(0), y(0), z(0) {}
|
|
|
|
|
Vector3(float X, float Y, float Z): x(X), y(Y), z(Z) {}
|
|
|
|
|
Vector3();
|
|
|
|
|
Vector3(float X, float Y, float Z);
|
|
|
|
|
Vector3(const Vector3& rhs);
|
|
|
|
|
Vector3(Vector3&&) = default;
|
|
|
|
|
Vector3& operator=(const Vector3& rhs);
|
|
|
|
@@ -144,11 +150,22 @@ public:
|
|
|
|
|
float distance(const Vector3& to) const;
|
|
|
|
|
float length() const;
|
|
|
|
|
float lengthSquared() const;
|
|
|
|
|
// Returns the length of the vector, which is sqrt(x^2 + y^2 + z^2)
|
|
|
|
|
float magnitude() const;
|
|
|
|
|
// Returns a float value equal to the magnitudes of the two vectors multiplied together and then multiplied by the cosine of the angle between them.
|
|
|
|
|
// For normalized vectors, dot returns 1 if they point in exactly the same direction,
|
|
|
|
|
// -1 if they point in completely opposite directions, and 0 if the vectors are perpendicular.
|
|
|
|
|
float dot(const Vector3& rhs) const;
|
|
|
|
|
Vector3 project(const Vector3& rhs) const;
|
|
|
|
|
// The cross product of two vectors results in a third vector which is perpendicular to the two input vectors.
|
|
|
|
|
// The result's magnitude is equal to the magnitudes of the two inputs multiplied together and then multiplied by the sine of the angle between the inputs.
|
|
|
|
|
Vector3 cross(const Vector3& rhs) const;
|
|
|
|
|
// Returns a copy of this vector, resized to have a magnitude of 1, while preserving "direction"
|
|
|
|
|
Vector3 normalize() const;
|
|
|
|
|
// Linearly interpolates between two points.
|
|
|
|
|
// Interpolates between the points and b by the interpolant t.
|
|
|
|
|
// The parameter is (TODO: SHOULD BE!) clamped to the range[0, 1].
|
|
|
|
|
// This is most commonly used to find a point some fraction of the wy along a line between two endpoints (eg. to move an object gradually between those points).
|
|
|
|
|
Vector3 lerp(const Vector3& goal, float alpha) const;
|
|
|
|
|
Vector3 operator+(const Vector3& rhs) const;
|
|
|
|
|
Vector3 operator-(const Vector3& rhs) const;
|
|
|
|
@@ -170,8 +187,8 @@ public:
|
|
|
|
|
|
|
|
|
|
class Vector4 {
|
|
|
|
|
public:
|
|
|
|
|
Vector4() : x(0), y(0), z(0), w(0) {}
|
|
|
|
|
Vector4(float X, float Y, float Z, float W) : x(X),y(Y),z(Z),w(W) { }
|
|
|
|
|
Vector4();
|
|
|
|
|
Vector4(float X, float Y, float Z, float W);
|
|
|
|
|
Vector4(const Vector4& copy) = default;
|
|
|
|
|
Vector4(Vector4&& move) = default;
|
|
|
|
|
float getX() const;
|
|
|
|
@@ -224,8 +241,85 @@ public:
|
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class Quaternion : Vector4
|
|
|
|
|
class Quaternion : public Vector4
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
Quaternion() {}
|
|
|
|
|
Quaternion(const Quaternion& rhs) = default;
|
|
|
|
|
explicit Quaternion(Matrix3x3& rotationMtrx) {}
|
|
|
|
|
explicit Quaternion(Matrix4x4& rotationMtrx) {}
|
|
|
|
|
// @note The input data is not normalized after construction, this has to be done manually.
|
|
|
|
|
Quaternion(float x, float y, float z, float w);
|
|
|
|
|
// Constructs this quaternion by specifying a rotation axis and the amount of rotation to be performed about that axis
|
|
|
|
|
// @param rotationAxis The normalized rotation axis to rotate about. If using Vector4 version of the constructor, the w component of this vector must be 0.
|
|
|
|
|
Quaternion(const Vector3& rotationAxis, float rotationAngleBetween) { SetFromAxisAngle(rotationAxis, rotationAngleBetween); }
|
|
|
|
|
Quaternion(const Vector4& rotationAxis, float rotationAngleBetween) { SetFromAxisAngle(rotationAxis, rotationAngleBetween); }
|
|
|
|
|
//void Inverse();
|
|
|
|
|
Quaternion Inverse() const;
|
|
|
|
|
//void Normalize();
|
|
|
|
|
Quaternion Normalize() const;
|
|
|
|
|
Vector3 GetWorldX() const { return Transform(1.f, 0.f, 0.f); }
|
|
|
|
|
Vector3 GetWorldY() const { return Transform(0.f, 1.f, 0.f); }
|
|
|
|
|
Vector3 GetWorldZ() const { return Transform(0.f, 0.f, 1.f); }
|
|
|
|
|
|
|
|
|
|
Matrix3x3 ToMatrix3x3() const;
|
|
|
|
|
|
|
|
|
|
Vector3 Transform(const Vector3& vec) const
|
|
|
|
|
{
|
|
|
|
|
Matrix3x3 mat = this->ToMatrix3x3();
|
|
|
|
|
return mat * vec;
|
|
|
|
|
}
|
|
|
|
|
Vector3 Transform(float X, float Y, float Z) const
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
Vector4 Transform(const Vector4& vec) const
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
Vector4 Transform(float X, float Y, float Z, float W) const
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Quaternion GetInverse() const;
|
|
|
|
|
Quaternion Lerp(const Quaternion& b, float t) const
|
|
|
|
|
{
|
|
|
|
|
float angle = this->dot(b);
|
|
|
|
|
if (angle >= 0.f) // Make sure we rotate the shorter arc
|
|
|
|
|
return (*this * (1.f - t) + b * t).Normalize();
|
|
|
|
|
else
|
|
|
|
|
return (*this * (t - 1.f) + b * t).Normalize();
|
|
|
|
|
}
|
|
|
|
|
Quaternion Slerp(const Quaternion& target) const;
|
|
|
|
|
|
|
|
|
|
void SetFromAxisAngle(const Vector3& axis, float angle)
|
|
|
|
|
{
|
|
|
|
|
float sinz, cosz;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SetFromAxisAngle(const Vector4& axis, float angle)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static Quaternion LookAt(const Vector3& position, const Vector3& direction, const Vector3& axisUp);
|
|
|
|
|
|
|
|
|
|
// Multiplies two quaternions together.
|
|
|
|
|
// The product q1 * q2 returns a quaternion that concatenates the two orientation rotations.
|
|
|
|
|
// The rotation q2 is applied first before q1.
|
|
|
|
|
Quaternion operator * (const Quaternion& rhs) const;
|
|
|
|
|
|
|
|
|
|
// Transforms the given vector by this Quaternion.
|
|
|
|
|
Vector3 operator * (const Vector3& rhs) const;
|
|
|
|
|
Vector4 operator * (const Vector4& rhs) const;
|
|
|
|
|
|
|
|
|
|
// Divides a quaternion by another. Divison "a / b" results in a quaternion that rotates the orientation b to coincide with orientation of
|
|
|
|
|
Quaternion operator / (const Quaternion& rhs) const;
|
|
|
|
|
|
|
|
|
|
Quaternion operator +() const { return *this; }
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@@ -235,6 +329,7 @@ class Quaternion : Vector4
|
|
|
|
|
class EulerAngle {
|
|
|
|
|
public:
|
|
|
|
|
EulerAngle();
|
|
|
|
|
EulerAngle(float pitch, float yaw, float roll);
|
|
|
|
|
static EulerAngle FromRadians(float radians);
|
|
|
|
|
static EulerAngle FromDegrees(float degrees);
|
|
|
|
|
// TODO: Implement separate upper and lower bounds
|
|
|
|
@@ -340,7 +435,9 @@ protected:
|
|
|
|
|
public:
|
|
|
|
|
Transform2D Translate(const Vector2& offset) const;
|
|
|
|
|
Transform2D Translate(float x, float y) const;
|
|
|
|
|
Transform2D Scale();
|
|
|
|
|
Transform2D Scale(float scale); // Perform Uniform Scale
|
|
|
|
|
Transform2D Scale(float x, float y); // Perform Nonunform Scale
|
|
|
|
|
Transform2D Scale(const Vector2& scales); // Perform Nonuniform Scale
|
|
|
|
|
Transform2D Rotate();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@@ -357,6 +454,8 @@ struct Movement {
|
|
|
|
|
EulerAngle angle;
|
|
|
|
|
Position position;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
inline namespace VectorMath {
|
|
|
|
|
inline float distance(Position sP, Position eP) {
|
|
|
|
|
return sqrt(pow(eP.x - sP.x, 2) + pow(eP.y - sP.y, 2) + pow(eP.z - sP.z, 2));
|
|
|
|
@@ -370,4 +469,6 @@ inline namespace VectorMath {
|
|
|
|
|
return {static_cast<float>((-(asinf((eP.y - sP.y) / distance(sP, eP)) * 180.0f / pi ))),static_cast<float>((atan2f(eP.x - sP.x,eP.z - sP.z) / pi * 180.0f)),0};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|