Implement Vector4 data type
This commit is contained in:
@@ -11,7 +11,6 @@ inline float lerp(float a, float b, float t) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Note: Josh Linear Algebra Types are designed as Immutable Data Types
|
||||
// x, y, z, w, etc. values should not and can not be set directly.
|
||||
// rather, you just construct a new type and assign it.
|
||||
@@ -127,6 +126,62 @@ public:
|
||||
#endif
|
||||
};
|
||||
|
||||
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(const Vector4& copy) = default;
|
||||
Vector4(Vector4&& move) = default;
|
||||
float getX() const;
|
||||
float getY() const;
|
||||
float getZ() const;
|
||||
float getW() const;
|
||||
#if MUTABLE
|
||||
void setX(float newX);
|
||||
void setY(float newY);
|
||||
void setZ(float newZ);
|
||||
void setW(float newW);
|
||||
#endif
|
||||
float operator[](int index) const;
|
||||
bool IsWithinMarginOfError(const Vector4& rhs, float margin=0.0001f) const;
|
||||
bool operator==(const Vector4& rhs) const;
|
||||
bool operator!=(const Vector4& rhs) const;
|
||||
Vector4 min(const Vector4& min) const;
|
||||
Vector4 max(const Vector4& max) const;
|
||||
Vector4 clamp(const Vector4& min, const Vector4& max) const;
|
||||
float distance(const Vector4& to) const;
|
||||
float length() const;
|
||||
float lengthSquared() const;
|
||||
float magnitude() const;
|
||||
float dot(const Vector4& rhs) const;
|
||||
Vector4 project(const Vector4& rhs) const;
|
||||
// While it is feasable to compute a cross-product in four dimensions
|
||||
// the cross product only has the orthogonality property in 3 and 7 dimensions
|
||||
// You should consider instead looking at Gram-Schmidt Orthogonalization
|
||||
// to find orthonormal vectors.
|
||||
Vector4 cross(const Vector4& rhs) const;
|
||||
Vector4 normalize() const;
|
||||
Vector4 lerp(const Vector4& goal, float alpha) const;
|
||||
Vector4 operator+(const Vector4& rhs) const;
|
||||
Vector4 operator-(const Vector4& rhs) const;
|
||||
Vector4 operator*(float rhs) const;
|
||||
Vector4 operator/(float rhs) const;
|
||||
Vector4 operator+() const;
|
||||
Vector4 operator-() const;
|
||||
public:
|
||||
#if MUTABLE
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
float w = 0;
|
||||
#else
|
||||
const float x = 0;
|
||||
const float y = 0;
|
||||
const float z = 0;
|
||||
const float w = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
// Essential Reading:
|
||||
// http://www.essentialmath.com/GDC2012/GDC2012_JMV_Rotations.pdf
|
||||
class Angle {
|
||||
@@ -186,47 +241,6 @@ class AxisAngle {
|
||||
|
||||
using Position = Vector3;
|
||||
|
||||
/*class Position : public vector3 {
|
||||
public:
|
||||
bool operator==(const Position& p) const {
|
||||
return (x == p.x) && (y == p.y) && (z == p.z);
|
||||
}
|
||||
|
||||
|
||||
void set(Position p) {
|
||||
this->x = p.x;
|
||||
this->y = p.y;
|
||||
this->z = p.z;
|
||||
}
|
||||
|
||||
void set(Position* p) {
|
||||
this->x = p->x;
|
||||
this->y = p->y;
|
||||
this->z = p->z;
|
||||
}
|
||||
|
||||
void set(vector3 v) {
|
||||
this->x = v.x;
|
||||
this->y = v.y;
|
||||
this->z = v.z;
|
||||
}
|
||||
|
||||
void set(vector3* v) {
|
||||
this->x = v->x;
|
||||
this->y = v->y;
|
||||
this->z = v->z;
|
||||
}
|
||||
void set(float x, float y, float z) {
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
float distanceFrom(Position p) {
|
||||
return sqrt(pow(this->x - p.x, 2) + pow(this->y - p.y, 2) + pow(this->z - p.z, 2));
|
||||
}
|
||||
};*/
|
||||
|
||||
// The CFrame is fundamentally 4 vectors (position, forward, right, up vector)
|
||||
class CoordinateFrame
|
||||
{
|
||||
@@ -243,6 +257,8 @@ class Matrix2x2 {
|
||||
public:
|
||||
static const Matrix2x2 Zero;
|
||||
static const Matrix2x2 Identity;
|
||||
Vector2 GetRow() const;
|
||||
Vector2 GetColumn() const;
|
||||
|
||||
protected:
|
||||
float elems[2][2];
|
||||
@@ -251,16 +267,39 @@ class Matrix3x3 {
|
||||
public:
|
||||
static const Matrix3x3 Zero;
|
||||
static const Matrix3x3 Identity;
|
||||
Vector3 GetRow() const;
|
||||
Vector3 GetColumn() const;
|
||||
float At(int x, int y) const;
|
||||
|
||||
// Creates a new M3x3 that rotates about the given axis by the given angle
|
||||
static Matrix3x3 RotateAxisAngle(const Vector3 );
|
||||
static Matrix3x3 RotateAxisAngle(const Vector3& rhs);
|
||||
protected:
|
||||
float elems[3][3];
|
||||
};
|
||||
|
||||
/// A 4-by-4 matrix for affine transformations and perspective projections of 3D geometry.
|
||||
/* This matrix can represent the most generic form of transformations for 3D objects,
|
||||
* including perspective projections, which a 4-by-3 cannot store,
|
||||
* and translations, which a 3-by-3 cannot represent.
|
||||
* The elements of this matrix are
|
||||
* m_00, m_01, m_02, m_03
|
||||
* m_10, m_11, m_12, m_13
|
||||
* m_20, m_21, m_22, m_23,
|
||||
* m_30, m_31, m_32, m_33
|
||||
*
|
||||
* The element m_yx is the value on the row y and column x.
|
||||
* You can access m_yx using the double-bracket notation m[y][x]
|
||||
*/
|
||||
class Matrix4x4 {
|
||||
public:
|
||||
static const Matrix4x4 Zero;
|
||||
static const Matrix4x4 Identity;
|
||||
|
||||
Vector3 GetTranslationComponent() const;
|
||||
Matrix3x3 GetRotationComponent() const;
|
||||
|
||||
Vector4 GetRow() const;
|
||||
Vector4 GetColumn() const;
|
||||
protected:
|
||||
float elems[4][4];
|
||||
};
|
||||
|
@@ -162,6 +162,7 @@ Vector3 Vector3::operator-() const
|
||||
return {-x, -y, -z};
|
||||
}
|
||||
|
||||
|
||||
Vector3::Vector3(const Vector3& rhs)
|
||||
{
|
||||
this->x = rhs.x;
|
||||
@@ -253,8 +254,8 @@ float Vector3::dot(const Vector3& rhs) const
|
||||
auto a = this->normalize();
|
||||
auto b = rhs.normalize();
|
||||
return a.x * b.x +
|
||||
a.y * b.y +
|
||||
a.z * b.z;
|
||||
a.y * b.y +
|
||||
a.z * b.z;
|
||||
}
|
||||
|
||||
Vector3 Vector3::project(const Vector3& rhs) const
|
||||
@@ -289,4 +290,114 @@ Vector3 Vector3::lerp(const Vector3& goal, float alpha) const
|
||||
return this->operator*(1.0f - alpha) + (goal * alpha);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
#pragma endregion
|
||||
|
||||
#pragma region vector4
|
||||
|
||||
|
||||
bool Vector4::operator==(const Vector4& rhs) const
|
||||
{
|
||||
return this->IsWithinMarginOfError(rhs);
|
||||
}
|
||||
|
||||
bool Vector4::operator!=(const Vector4& rhs) const
|
||||
{
|
||||
return this->IsWithinMarginOfError(rhs) == false;
|
||||
}
|
||||
|
||||
Vector4 Vector4::min(const Vector4& min) const
|
||||
{
|
||||
return {
|
||||
std::min(this->x, min.x),
|
||||
std::min(this->y, min.y),
|
||||
std::min(this->z, min.z),
|
||||
std::min(this->w, min.w)
|
||||
};
|
||||
}
|
||||
|
||||
Vector4 Vector4::max(const Vector4& max) const
|
||||
{
|
||||
return {
|
||||
std::max(this->x, max.x),
|
||||
std::max(this->y, max.y),
|
||||
std::max(this->z, max.z),
|
||||
std::max(this->w, max.w)
|
||||
};
|
||||
}
|
||||
|
||||
Vector4 Vector4::clamp(const Vector4& min, const Vector4& max) const
|
||||
{
|
||||
return {
|
||||
std::clamp(this->x, min.x, max.x),
|
||||
std::clamp(this->y, min.y, max.y),
|
||||
std::clamp(this->z, min.z, max.z),
|
||||
std::clamp(this->w, min.w, max.w)
|
||||
};
|
||||
}
|
||||
|
||||
float Vector4::distance(const Vector4& to) const
|
||||
{
|
||||
return ( (*this) - to ).magnitude();
|
||||
}
|
||||
|
||||
float Vector4::length() const
|
||||
{
|
||||
return std::sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
float Vector4::lengthSquared() const
|
||||
{
|
||||
return (x*x + y*y + z*z + w*w);
|
||||
}
|
||||
|
||||
float Vector4::magnitude() const
|
||||
{
|
||||
return std::sqrt(x*x + y*y + z*z + w*w);
|
||||
}
|
||||
|
||||
float Vector4::dot(const Vector4& rhs) const
|
||||
{
|
||||
auto a = this->normalize();
|
||||
auto b = rhs.normalize();
|
||||
|
||||
return a.x * b.x +
|
||||
a.y * b.y +
|
||||
a.z * b.z +
|
||||
a.w * b.w;
|
||||
}
|
||||
|
||||
Vector4 Vector4::project(const Vector4& rhs) const
|
||||
{
|
||||
float scalar = this->dot(rhs) / (rhs.magnitude()* rhs.magnitude());
|
||||
return rhs * scalar;
|
||||
}
|
||||
|
||||
Vector4 Vector4::normalize() const
|
||||
{
|
||||
if (length() > 0)
|
||||
return {
|
||||
x / length(),
|
||||
y / length(),
|
||||
z / length(),
|
||||
w / length()
|
||||
};
|
||||
else
|
||||
return {0,0,0,0};
|
||||
}
|
||||
|
||||
Vector4 Vector4::lerp(const Vector4& goal, float alpha) const
|
||||
{
|
||||
return this->operator*(1.0f - alpha) + (goal * alpha);
|
||||
}
|
||||
|
||||
Vector4 Vector4::operator+(const Vector4& rhs) const
|
||||
{
|
||||
return {x+rhs.x, y+rhs.y, z+rhs.z, w+rhs.w};
|
||||
}
|
||||
|
||||
Vector4 Vector4::operator-(const Vector4& rhs) const
|
||||
{
|
||||
return {x-rhs.x, y-rhs.y, z-rhs.z, w-rhs.w};
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
Reference in New Issue
Block a user