diff --git a/Angle.h b/Angle.h index 31fc88a..943be90 100644 --- a/Angle.h +++ b/Angle.h @@ -39,23 +39,7 @@ private: }; using Angle = AngleOf; -/* -class Angle { -public: - const static float Rad2Deg; - const static float Deg2Rad; - static float Normalize(float angle); - static float Clamp(float angle, float min, float max); - static float Difference(float a, float b); - static float MoveTowards(float fromAngle, float toAngle, float maxAngle); - - static float CosineRuleSide(float a, float b, float gamma); - static float CosineRuleAngle(float a, float b, float c); - - static float SineRuleAngle(float a, float beta, float c); -}; -*/ } // namespace Passer using namespace Passer; diff --git a/Matrix.cpp b/Matrix.cpp index 7a67504..b9b2eab 100644 --- a/Matrix.cpp +++ b/Matrix.cpp @@ -15,9 +15,9 @@ template <> MatrixOf::MatrixOf(unsigned int rows, unsigned int cols) { } template <> MatrixOf::MatrixOf(Vector3 v) : MatrixOf(3, 1) { - Set(0, 0, v.x); - Set(1, 0, v.y); - Set(2, 0, v.z); + Set(0, 0, v.Right()); + Set(1, 0, v.Up()); + Set(2, 0, v.Forward()); } template <> @@ -27,7 +27,7 @@ void MatrixOf::Multiply(const MatrixOf *m1, for (unsigned int colIx2 = 0; colIx2 < m2->cols; colIx2++) { unsigned int rDataIx = colIx2 * m2->cols + rowIx1; r->data[rDataIx] = 0.0F; - for (int kIx = 0; kIx < m2->rows; kIx++) { + for (unsigned int kIx = 0; kIx < m2->rows; kIx++) { unsigned int dataIx1 = rowIx1 * m1->cols + kIx; unsigned int dataIx2 = kIx * m2->cols + colIx2; r->data[rDataIx] += m1->data[dataIx1] * m2->data[dataIx2]; diff --git a/Quaternion.cpp b/Quaternion.cpp index 0389ab2..8f76a71 100644 --- a/Quaternion.cpp +++ b/Quaternion.cpp @@ -115,13 +115,21 @@ Vector3 Quaternion::operator*(const Vector3 &p) const { float num10 = this->w * num; float num11 = this->w * num2; float num12 = this->w * num3; - Vector3 result = Vector3::zero; - result.x = - (1 - (num5 + num6)) * p.x + (num7 - num12) * p.y + (num8 + num11) * p.z; - result.y = - (num7 + num12) * p.x + (1 - (num4 + num6)) * p.y + (num9 - num10) * p.z; - result.z = - (num8 - num11) * p.x + (num9 + num10) * p.y + (1 - (num4 + num5)) * p.z; + + float px = p.Right(); + float py = p.Up(); + float pz = p.Forward(); + // Vector3 result = Vector3::zero; + // result.x = + float rx = + (1 - (num5 + num6)) * px + (num7 - num12) * py + (num8 + num11) * pz; + // result.y = + float ry = + (num7 + num12) * px + (1 - (num4 + num6)) * py + (num9 - num10) * pz; + // result.z = + float rz = + (num8 - num11) * px + (num9 + num10) * py + (1 - (num4 + num5)) * pz; + Vector3 result = Vector3(rx, ry, rz); return result; } @@ -142,15 +150,15 @@ Quaternion Quaternion::LookRotation(const Vector3 &forward, const Vector3 &up) { Vector3 nForward = Vector3::Normalize(forward); Vector3 nRight = Vector3::Normalize(Vector3::Cross(up, nForward)); Vector3 nUp = Vector3::Cross(nForward, nRight); - float m00 = nRight.x; - float m01 = nRight.y; - float m02 = nRight.z; - float m10 = nUp.x; - float m11 = nUp.y; - float m12 = nUp.z; - float m20 = nForward.x; - float m21 = nForward.y; - float m22 = nForward.z; + float m00 = nRight.Right(); // x; + float m01 = nRight.Up(); // y; + float m02 = nRight.Forward(); // z; + float m10 = nUp.Right(); // x; + float m11 = nUp.Up(); // y; + float m12 = nUp.Forward(); // z; + float m20 = nForward.Right(); // x; + float m21 = nForward.Up(); // y; + float m22 = nForward.Forward(); // z; float num8 = (m00 + m11) + m22; Quaternion quaternion = Quaternion(); @@ -219,9 +227,9 @@ Quaternion Quaternion::AngleAxis(float angle, const Vector3 &axis) { radians *= 0.5f; Vector3 axis2 = axis * (float)sin(radians); - result.x = axis2.x; - result.y = axis2.y; - result.z = axis2.z; + result.x = axis2.Right(); // x; + result.y = axis2.Up(); // y; + result.z = axis2.Forward(); // z; result.w = (float)cos(radians); return Quaternion::Normalize(result); @@ -293,7 +301,8 @@ Quaternion Quaternion::SlerpUnclamped(const Quaternion &a, const Quaternion &b, blendB = t; } Vector3 v = axyz * blendA + b2.xyz() * blendB; - Quaternion result = Quaternion(v.x, v.y, v.z, blendA * a.w + blendB * b2.w); + Quaternion result = + Quaternion(v.Right(), v.Up(), v.Forward(), blendA * a.w + blendB * b2.w); if (result.GetLengthSquared() > 0.0f) return Quaternion::Normalize(result); else @@ -317,9 +326,9 @@ Quaternion Quaternion::Euler(Vector3 euler) { } Quaternion Quaternion::FromEulerRad(Vector3 euler) { - float yaw = euler.x; - float pitch = euler.y; - float roll = euler.z; + float yaw = euler.Right(); + float pitch = euler.Up(); + float roll = euler.Forward(); float rollOver2 = roll * 0.5f; float sinRollOver2 = (float)sin((float)rollOver2); float cosRollOver2 = (float)cos((float)rollOver2); @@ -348,9 +357,9 @@ Quaternion Quaternion::EulerXYZ(Vector3 euler) { return Quaternion::FromEulerRadXYZ(euler * Deg2Rad); } Quaternion Quaternion::FromEulerRadXYZ(Vector3 euler) { - float yaw = euler.x; - float pitch = euler.y; - float roll = euler.z; + float yaw = euler.Right(); // x; + float pitch = euler.Up(); // y; + float roll = euler.Forward(); // z; float rollOver2 = roll * 0.5f; float sinRollOver2 = (float)sin((float)rollOver2); float cosRollOver2 = (float)cos((float)rollOver2); @@ -389,7 +398,7 @@ Quaternion Quaternion::GetRotationAround(Vector3 axis, Quaternion rotation) { Vector3 ra = Vector3(rotation.x, rotation.y, rotation.z); // rotation axis Vector3 p = Vector3::Project( ra, axis); // return projection ra on to axis (parallel component) - Quaternion twist = Quaternion(p.x, p.y, p.z, rotation.w); + Quaternion twist = Quaternion(p.Right(), p.Up(), p.Forward(), rotation.w); twist = Quaternion::Normalize(twist); return twist; } diff --git a/Spherical.cpp b/Spherical.cpp index 699d01e..3e623b3 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -37,8 +37,8 @@ Spherical::Spherical(Vector3 v) { this->horizontalAngle = 0.0f; } else { this->verticalAngle = - (90.0f - acosf(v.y / this->distance) * Angle::Rad2Deg); - this->horizontalAngle = atan2f(v.x, v.z) * Angle::Rad2Deg; + (90.0f - acosf(v.Up() / this->distance) * Angle::Rad2Deg); + this->horizontalAngle = atan2f(v.Right(), v.Forward()) * Angle::Rad2Deg; } } diff --git a/Vector2.cpp b/Vector2.cpp index c5321ea..1ab580a 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -21,13 +21,13 @@ Vector2::Vector2(float _x, float _y) { x = _x; y = _y; } -Vector2::Vector2(Vec2 v) { - x = v.x; - y = v.y; -} +// Vector2::Vector2(Vec2 v) { +// x = v.x; +// y = v.y; +// } Vector2::Vector2(Vector3 v) { - x = v.x; - y = v.z; + x = v.Right(); // x; + y = v.Forward(); // z; } Vector2::Vector2(Polar p) { float horizontalRad = p.angle * Angle::Deg2Rad; @@ -53,11 +53,11 @@ bool Vector2::operator==(const Vector2 &v) { return (this->x == v.x && this->y == v.y); } -float Vector2::Magnitude(const Vector2 &a) { - return sqrtf(a.x * a.x + a.y * a.y); +float Vector2::Magnitude(const Vector2 &v) { + return sqrtf(v.x * v.x + v.y * v.y); } float Vector2::magnitude() const { return (float)sqrtf(x * x + y * y); } -float Vector2::SqrMagnitude(const Vector2 &a) { return a.x * a.x + a.y * a.y; } +float Vector2::SqrMagnitude(const Vector2 &v) { return v.x * v.x + v.y * v.y; } float Vector2::sqrMagnitude() const { return (x * x + y * y); } Vector2 Vector2::Normalize(const Vector2 &v) { @@ -79,21 +79,47 @@ Vector2 Vector2::normalized() const { Vector2 Vector2::operator-() { return Vector2(-this->x, -this->y); } -Vector2 Vector2::operator-(const Vector2 &v2) const { - return Vector2(this->x - v2.x, this->y - v2.y); +Vector2 Vector2::operator-(const Vector2 &v) const { + return Vector2(this->x - v.x, this->y - v.y); } -Vector2 Vector2::operator+(const Vector2 &v2) const { - return Vector2(this->x + v2.x, this->y + v2.y); +Vector2 Vector2::operator-=(const Vector2 &v) { + this->x -= v.x; + this->y -= v.y; + return *this; +} +Vector2 Vector2::operator+(const Vector2 &v) const { + return Vector2(this->x + v.x, this->y + v.y); +} +Vector2 Vector2::operator+=(const Vector2 &v) { + this->x += v.x; + this->y += v.y; + return *this; } -Vector2 Vector2::Scale(const Vector2 &p1, const Vector2 &p2) { - return Vector2(p1.x * p2.x, p1.y * p2.y); +Vector2 Vector2::Scale(const Vector2 &v1, const Vector2 &v2) { + return Vector2(v1.x * v2.x, v1.y * v2.y); } -Vector2 Vector2::operator*(float f) const { - return Vector2(this->x * f, this->y * f); +Vector2 Passer::operator*(const Vector2 &v, const float f) { + return Vector2(v.x * f, v.y * f); } -Vector2 Vector2::operator/(float f) const { - return Vector2(this->x / f, this->y / f); +Vector2 Passer::operator*(const float f, const Vector2 &v) { + return Vector2(v.x * f, v.y * f); +} +Vector2 Vector2::operator*=(const float f) { + this->x *= f; + this->y *= f; + return *this; +} +Vector2 Passer::operator/(const Vector2 &v, const float f) { + return Vector2(v.x / f, v.y / f); +} +Vector2 Passer::operator/(const float f, const Vector2 &v) { + return Vector2(v.x / f, v.y / f); +} +Vector2 Vector2::operator/=(const float f) { + this->x /= f; + this->y /= f; + return *this; } float Vector2::Dot(const Vector2 &v1, const Vector2 &v2) { @@ -120,8 +146,8 @@ float Vector2::SignedAngle(const Vector2 &v1, const Vector2 &v2) { return nanf(""); #endif - float angleFrom = atan2(v1.y, v1.x); - float angleTo = atan2(v2.y, v2.x); + float angleFrom = atan2f(v1.y, v1.x); + float angleTo = atan2f(v2.y, v2.x); return -(angleTo - angleFrom) * Angle::Rad2Deg; } diff --git a/Vector2.h b/Vector2.h index 63d3c08..055375a 100644 --- a/Vector2.h +++ b/Vector2.h @@ -35,16 +35,15 @@ struct Polar; /// @remark This uses the right=handed carthesian coordinate system. /// @note This implementation intentionally avoids the use of x and y struct Vector2 : Vec2 { + friend struct Vec2; + public: /// @brief A new 2-dimensional zero vector Vector2(); /// @brief A new 2-dimensional vector - /// @param sideward The sideward value - /// @param forward The forward value - Vector2(float sideward, float forward); - /// @brief A vector created from a C-style Vec2 - /// @param v The C-syle Vec2 - Vector2(Vec2 v); + /// @param right The distance in the right direction in meters + /// @param forward The distance in the forward direction in meters + Vector2(float right, float forward); /// @brief Convert a Vector3 to a Vector2 /// @param v The 3D vector /// @note This will project the vector to the horizontal plane @@ -64,18 +63,18 @@ public: const static Vector2 right; /// @brief A normalized left-oriented vector const static Vector2 left; - /// @brief A normalized up-oriented vector - /// @note This is equal to Vector2::forward - const static Vector2 up; - /// @brief A normalized down-oriented vector - /// @note This is equal to Vector2::down - const static Vector2 down; /// @brief A normalized forward-oriented vector /// @note This is equal to Vector2::up const static Vector2 forward; /// @brief A normalized back-oriented vector /// @note This is equal to Vector2::down const static Vector2 back; + /// @brief A normalized up-oriented vector + /// @note This is a convenience function which is equal to Vector2::forward + const static Vector2 up; + /// @brief A normalized down-oriented vector + /// @note This is a convenience function which is equal to Vector2::down + const static Vector2 down; /// @brief Check if this vector to the given vector /// @param v The vector to check against @@ -121,12 +120,14 @@ public: /// @param v The vector to subtract from this vector /// @return The result of the subtraction Vector2 operator-(const Vector2 &v) const; + Vector2 operator-=(const Vector2 &v); /// @brief Add a vector to this vector /// @param v The vector to add to this vector /// @return The result of the addition Vector2 operator+(const Vector2 &v) const; + Vector2 operator+=(const Vector2 &v); - /// @brief Scale a vector using another vector + /// @brief Scale the vector using another vector /// @param v1 The vector to scale /// @param v2 A vector with the scaling factors /// @return The scaled vector @@ -138,12 +139,16 @@ public: /// @return The scaled vector /// @remark Each component of the vector will be multipled with the same /// factor f. - Vector2 operator*(float f) const; + friend Vector2 operator*(const Vector2 &v, const float f); + friend Vector2 operator*(const float f, const Vector2 &v); + Vector2 operator*=(const float f); /// @brief Scale the vector uniformly down /// @param f The scaling factor /// @return The scaled vector /// @remark Each componet of the vector will be divided by the same factor. - Vector2 operator/(float f) const; + friend Vector2 operator/(const Vector2 &v, const float f); + friend Vector2 operator/(const float f, const Vector2 &v); + Vector2 operator/=(const float f); /// @brief The dot product of two vectors /// @param v1 The first vector diff --git a/Vector3.cpp b/Vector3.cpp index 3ee597e..2cf43f1 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -13,21 +13,21 @@ const float Rad2Deg = 57.29578F; const float epsilon = 1E-05f; Vector3::Vector3() { - x = 0; - y = 0; - z = 0; + this->x = 0; + this->y = 0; + this->z = 0; } -Vector3::Vector3(float _x, float _y, float _z) { - x = _x; - y = _y; - z = _z; +Vector3::Vector3(float right, float up, float forward) { + this->x = right; + this->y = up; + this->z = forward; } -Vector3::Vector3(Vec3 v) { - x = v.x; - y = v.y; - z = v.z; +Vector3::Vector3(Vector2 v) { + this->x = v.x; + this->y = 0.0f; + this->z = v.y; } Vector3::Vector3(Spherical s) { @@ -61,17 +61,17 @@ const Vector3 Vector3::back = Vector3(0, 0, -1); // inline float Vector3::Forward() { return z; } // inline float Vector3::Up() { return y; } // inline float Vector3::Right() { return x; } -Vector3 Vector3::FromHorizontal(const Vector2 &v) { - return Vector3(v.x, 0, v.y); -} +// Vector3 Vector3::FromHorizontal(const Vector2 &v) { +// return Vector3(v.x, 0, v.y); +// } -float Vector3::Magnitude(const Vector3 &a) { - return sqrtf(a.x * a.x + a.y * a.y + a.z * a.z); +float Vector3::Magnitude(const Vector3 &v) { + return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); } float Vector3::magnitude() const { return (float)sqrtf(x * x + y * y + z * z); } -float Vector3::SqrMagnitude(const Vector3 &a) { - return a.x * a.x + a.y * a.y + a.z * a.z; +float Vector3::SqrMagnitude(const Vector3 &v) { + return v.x * v.x + v.y * v.y + v.z * v.z; } float Vector3::sqrMagnitude() const { return (x * x + y * y + z * z); } @@ -92,26 +92,55 @@ Vector3 Vector3::normalized() const { return result; } -Vector3 Vector3::operator-(const Vector3 &v2) const { - return Vector3(this->x - v2.x, this->y - v2.y, this->z - v2.z); +Vector3 Vector3::operator-() const { + return Vector3(-this->x, -this->y, -this->z); } -Vector3 Vector3::operator-() { return Vector3(-this->x, -this->y, -this->z); } - -Vector3 Vector3::operator+(const Vector3 &v2) const { - return Vector3(this->x + v2.x, this->y + v2.y, this->z + v2.z); +Vector3 Vector3::operator-(const Vector3 &v) const { + return Vector3(this->x - v.x, this->y - v.y, this->z - v.z); +} +Vector3 Vector3::operator-=(const Vector3 &v) { + this->x -= v.x; + this->y -= v.y; + this->z -= v.z; + return *this; +} +Vector3 Vector3::operator+(const Vector3 &v) const { + return Vector3(this->x + v.x, this->y + v.y, this->z + v.z); +} +Vector3 Vector3::operator+=(const Vector3 &v) { + this->x += v.x; + this->y += v.y; + this->z += v.z; + return *this; } -Vector3 Vector3::Scale(const Vector3 &p1, const Vector3 &p2) { - return Vector3(p1.x * p2.x, p1.y * p2.y, p1.z * p2.z); +Vector3 Vector3::Scale(const Vector3 &v1, const Vector3 &v2) { + return Vector3(v1.x * v2.x, v1.y * v2.y, v1.z * v2.z); } - -Vector3 Vector3::operator*(float f) const { - return Vector3(this->x * f, this->y * f, this->z * f); +Vector3 Passer::operator*(const Vector3 &v, const float f) { + return Vector3(v.x * f, v.y * f, v.z * f); } - -Vector3 Vector3::operator/(float d) const { - return Vector3(this->x / d, this->y / d, this->z / d); +Vector3 Passer::operator*(const float f, const Vector3 &v) { + return Vector3(v.x * f, v.y * f, v.z * f); +} +Vector3 Vector3::operator*=(const float f) { + this->x *= f; + this->y *= f; + this->z *= f; + return *this; +} +Vector3 Passer::operator/(const Vector3 &v, const float f) { + return Vector3(v.x / f, v.y / f, v.z / f); +} +Vector3 Passer::operator/(const float f, const Vector3 &v) { + return Vector3(v.x / f, v.y / f, v.z / f); +} +Vector3 Vector3::operator/=(const float f) { + this->x /= f; + this->y /= f; + this->z /= f; + return *this; } float Vector3::Dot(const Vector3 &v1, const Vector3 &v2) { @@ -122,8 +151,8 @@ bool Vector3::operator==(const Vector3 &v) { return (this->x == v.x && this->y == v.y && this->z == v.z); } -float Vector3::Distance(const Vector3 &p1, const Vector3 &p2) { - return Magnitude(p1 - p2); +float Vector3::Distance(const Vector3 &v1, const Vector3 &v2) { + return Magnitude(v1 - v2); } Vector3 Vector3::Cross(const Vector3 &v1, const Vector3 &v2) { @@ -131,25 +160,19 @@ Vector3 Vector3::Cross(const Vector3 &v1, const Vector3 &v2) { v1.x * v2.y - v1.y * v2.x); } -Vector3 Vector3::Project(const Vector3 &vector, const Vector3 &onNormal) { - float sqrMagnitude = Dot(onNormal, onNormal); +Vector3 Vector3::Project(const Vector3 &v, const Vector3 &n) { + float sqrMagnitude = Dot(n, n); if (sqrMagnitude < epsilon) return Vector3::zero; else { - float dot = Dot(vector, onNormal); - Vector3 r = onNormal * dot / sqrMagnitude; + float dot = Dot(v, n); + Vector3 r = n * dot / sqrMagnitude; return r; } } -Vector3 Vector3::ProjectOnPlane(const Vector3 &vector, - const Vector3 &planeNormal) { - Vector3 r = vector - Project(vector, planeNormal); - return r; -} - -Vector2 Vector3::ProjectHorizontalPlane(const Vector3 &vector) { - Vector2 r = Vector2(vector.x, vector.z); +Vector3 Vector3::ProjectOnPlane(const Vector3 &v, const Vector3 &n) { + Vector3 r = v - Project(v, n); return r; } @@ -159,12 +182,12 @@ float clamp(float x, float lower, float upper) { return upperClamp; } -float Vector3::Angle(const Vector3 &from, const Vector3 &to) { - float denominator = sqrtf(from.sqrMagnitude() * to.sqrMagnitude()); +float Vector3::Angle(const Vector3 &v1, const Vector3 &v2) { + float denominator = sqrtf(v1.sqrMagnitude() * v2.sqrMagnitude()); if (denominator < epsilon) return 0; - float dot = Vector3::Dot(from, to); + float dot = Vector3::Dot(v1, v2); float fraction = dot / denominator; if (isnan(fraction)) return fraction; // short cut to returning NaN universally @@ -174,12 +197,12 @@ float Vector3::Angle(const Vector3 &from, const Vector3 &to) { return r; } -float Vector3::SignedAngle(const Vector3 &from, const Vector3 &to, +float Vector3::SignedAngle(const Vector3 &v1, const Vector3 &v2, const Vector3 &axis) { // angle in [0,180] - float angle = Vector3::Angle(from, to); + float angle = Vector3::Angle(v1, v2); - Vector3 cross = Vector3::Cross(from, to); + Vector3 cross = Vector3::Cross(v1, v2); float b = Vector3::Dot(axis, cross); float signd = b < 0 ? -1.0F : (b > 0 ? 1.0F : 0.0F); @@ -189,7 +212,7 @@ float Vector3::SignedAngle(const Vector3 &from, const Vector3 &to, return signed_angle; } -Vector3 Vector3::Lerp(const Vector3 &from, const Vector3 &to, float f) { - Vector3 v = from + (to - from) * f; +Vector3 Vector3::Lerp(const Vector3 &v1, const Vector3 &v2, float f) { + Vector3 v = v1 + (v2 - v1) * f; return v; -} \ No newline at end of file +} diff --git a/Vector3.h b/Vector3.h index fbc51e3..5c10bb6 100644 --- a/Vector3.h +++ b/Vector3.h @@ -18,6 +18,7 @@ extern "C" { /// This is a C-style implementation /// This uses the right-handed coordinate system. typedef struct Vec3 { +protected: /// /// The right axis of the vector /// @@ -34,247 +35,184 @@ typedef struct Vec3 { } Vec3; } -/// -/// A 3-dimensional vector -/// -/// This uses the right-handed coordinate system. +/// @brief A 3-dimensional vector +/// @remark This uses a right-handed carthesian coordinate system. +/// @note This implementation intentionally avoids the use of x, y and z values. struct Vector3 : Vec3 { + friend struct Vec3; + public: - /// - /// Create a new 3-dimensinal zero vector - /// + /// @brief A new 3-dimensional zero vector Vector3(); - /// - /// Create a new 3-dimensional vector - /// - /// x axis value - /// y axis value - /// z axis value - Vector3(float x, float y, float z); - /// - /// Create a vector from C-style Vec3 - /// - /// The C-style Vec - Vector3(Vec3 v); - /// - /// Vector3 destructor - /// - Vector3(Spherical s); + /// @brief A new 3-dimensional vector + /// @param right The distance in the right direction in meters + /// @param up The distance in the upward direction in meters + /// @param forward The distance in the forward direction in meters + Vector3(float right, float up, float forward); + /// @brief Convert a 2-dimenstional vector to a 3-dimensional vector + /// @param v The vector to convert + Vector3(Vector2 v); + /// @brief Convert vector in spherical coordinates to 3d carthesian + /// coordinates + /// @param v The vector to convert + Vector3(Spherical v); + + /// @brief Vector3 destructor ~Vector3(); - /// - /// A vector with zero for all axis - /// + /// @brief A vector with zero for all axis const static Vector3 zero; - /// - /// A vector with one for all axis - /// + /// @brief A vector with one for all axis const static Vector3 one; - /// - /// A normalized vector pointing in the right direction - /// + /// @brief A normalized right-oriented vector const static Vector3 right; - /// - /// A normalized vector pointing in the left direction - /// + /// @brief A normalized left-oriented vector const static Vector3 left; - /// - /// A normalized vector pointing in the upward direction - /// + /// @brief A normalized up-oriented vector const static Vector3 up; - /// - /// A normalized vector pointing in the downward direcion - /// + /// @brief A normalized down-oriented vector const static Vector3 down; - /// - /// A normalized vector pointing in the forward direction - /// + /// @brief A normalized forward-oriented vector const static Vector3 forward; - /// - /// A normalized vector pointing in the backward direction - /// + /// @brief A normalized back-oriented vector const static Vector3 back; - // Experimental Access functions which are intended to replace the use of XYZ - inline float Forward() { return z; }; - inline float Up() { return y; }; - inline float Right() { return x; }; - static Vector3 FromHorizontal(const Vector2 &vector); + // Access functions which are intended to replace the use of XYZ + inline float Forward() const { return z; }; + inline float Up() const { return y; }; + inline float Right() const { return x; }; - /// - /// The length of a vector - /// - /// The vector for which you need the length - /// The length of the given vector - static float Magnitude(const Vector3 &vector); - /// - /// The length of this vector - /// - /// The length of this vector + /// @brief Check if this vector to the given vector + /// @param v The vector to check against + /// @return true if it is identical to the given vector + /// @note This uses float comparison to check equality which may have strange + /// effects. Equality on floats should be avoided. + bool operator==(const Vector3 &v); + + /// @brief The vector length + /// @param v The vector for which you need the length + /// @return The vector length + static float Magnitude(const Vector3 &v); + /// @brief The vector length + /// @return The vector length float magnitude() const; - /// - /// The squared length of a vector - /// - /// The vector for which you need the squared - /// length The squatred length The squared length - /// is computationally simpler than the real length. Think of Pythagoras A^2 + - /// B^2 = C^2. This leaves out the calculation of the squared root of C. - static float SqrMagnitude(const Vector3 &vector); - /// - /// The squared length of this vector - /// - /// The squared length - /// The squared length is computationally simpler than the real length. - /// Think of Pythagoras A^2 + B^2 = C^2. - /// This leaves out the calculation of the squared root of C. + /// @brief The squared vector length + /// @param v The vector for which you need the length + /// @return The squared vector length + /// @remark The squared length is computationally simpler than the real + /// length. Think of Pythagoras A^2 + B^2 = C^2. This leaves out the + /// calculation of the squared root of C. + static float SqrMagnitude(const Vector3 &v); + /// @brief The squared vector length + /// @return The squared vector length + /// @remark The squared length is computationally simpler than the real + /// length. Think of Pythagoras A^2 + B^2 = C^2. This leaves out the + /// calculation of the squared root of C. float sqrMagnitude() const; - /// - /// Connvert a vector to a length of 1 - /// - /// The vector to convert - /// The vector with length 1 - static Vector3 Normalize(const Vector3 &vector); - /// - /// Convert the vector to a length of a - /// - /// The vector with length 1 + + /// @brief Convert the vector to a length of 1 + /// @param v The vector to convert + /// @return The vector normalized to a length of 1 + static Vector3 Normalize(const Vector3 &v); + /// @brief Convert the vector to a length of 1 + /// @return The vector normalized to a length of 1 Vector3 normalized() const; - /// - /// Negate the vector - /// - /// The negated vector - /// This will result in a vector pointing in the opposite direction - Vector3 operator-(); - /// - /// Subtract a vector from this vector - /// - /// The vector to subtract from this vector - /// The result of the subtraction - Vector3 operator-(const Vector3 &vector) const; + /// @brief Negate te vector such that it points in the opposite direction + /// @return The negated vector + Vector3 operator-() const; - /// - /// Add another vector to this vector - /// - /// The vector to add - /// The result of adding the vector - Vector3 operator+(const Vector3 &vector2) const; + /// @brief Subtract a vector from this vector + /// @param v The vector to subtract from this vector + /// @return The result of this subtraction + Vector3 operator-(const Vector3 &v) const; + Vector3 operator-=(const Vector3 &v); + /// @brief Add a vector to this vector + /// @param v The vector to add to this vector + /// @return The result of the addition + Vector3 operator+(const Vector3 &v) const; + Vector3 operator+=(const Vector3 &v); - /// - /// Scale a vector using another vector - /// - /// The vector to scale - /// A vector with scaling factors - /// The scaled vector - /// Each component of the vector v1 will be multiplied with the - /// component from the scaling vector v2. - static Vector3 Scale(const Vector3 &vector1, const Vector3 &vector2); - /// - /// Scale a vector uniformly up - /// - /// The scaling factor - /// The scaled vector - /// Each component of the vector will be multipled with the same factor. - Vector3 operator*(const float factor) const; - /// - /// Scale a vector uniformy down - /// - /// The scaling factor - /// The scaled vector - /// Each componet of the vector will be divided by the same factor. - Vector3 operator/(const float factor) const; + /// @brief Scale the vector using another vector + /// @param v1 The vector to scale + /// @param v2 A vector with the scaling factors + /// @return The scaled vector + /// @remark Each component of the vector v1 will be multiplied with the + /// matching component from the scaling vector v2. + static Vector3 Scale(const Vector3 &v1, const Vector3 &v2); + /// @brief Scale the vector uniformly up + /// @param f The scaling factor + /// @return The scaled vector + /// @remark Each component of the vector will be multipled with the same + /// factor f. + friend Vector3 operator*(const Vector3 &v, const float f); + friend Vector3 operator*(const float f, const Vector3 &v); + Vector3 operator*=(const float f); + /// @brief Scale the vector uniformly down + /// @param f The scaling factor + /// @return The scaled vector + /// @remark Each componet of the vector will be divided by the same factor. + friend Vector3 operator/(const Vector3 &v, const float f); + friend Vector3 operator/(const float f, const Vector3 &v); + Vector3 operator/=(const float f); - /// - /// The dot product of two vectors - /// - /// The first vector - /// The second vector - /// The dot product of the two vectors - static float Dot(const Vector3 &vector1, const Vector3 &vector2); + /// @brief The distance between two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The distance between the two vectors + static float Distance(const Vector3 &v1, const Vector3 &v2); - /// - /// Check is this vector is equal to the given vector - /// - /// The vector to check against - /// True if it is identical to the given vector - /// Note this uses float comparison to check equality which - /// may have strange effects. Equality on float should be avoided. - bool operator==(const Vector3 &vector); + /// @brief The dot product of two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The dot product of the two vectors + static float Dot(const Vector3 &v1, const Vector3 &v2); - /// - /// The distance between two vectors - /// - /// The first vector - /// The second vectors - /// The distance between the two vectors - static float Distance(const Vector3 &vector1, const Vector3 &vector2); + /// @brief The cross product of two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The cross product of the two vectors + static Vector3 Cross(const Vector3 &v1, const Vector3 &v2); - /// - /// The cross product of two vectors - /// - /// The first vector - /// The second vector - /// The cross product of the two vectors - static Vector3 Cross(const Vector3 &vector1, const Vector3 &vector2); - - /// - /// Project a vector on another vector - /// - /// The vector to project - /// The normal vector to project on - /// The projected vector - static Vector3 Project(const Vector3 &vector, const Vector3 &onNormal); - /// - /// Projects a vector onto a plane defined by a normal orthogonal to the + /// @brief Project the vector on another vector + /// @param v The vector to project + /// @param n The normal vecto to project on + /// @return The projected vector + static Vector3 Project(const Vector3 &v, const Vector3 &n); + /// @brief Project the vector on a plane defined by a normal orthogonal to the /// plane. - /// - /// The vector to project - /// The normal of the plane to project on - /// - static Vector3 ProjectOnPlane(const Vector3 &vector, - const Vector3 &planeNormal); + /// @param v The vector to project + /// @param n The normal of the plane to project on + /// @return Teh projected vector + static Vector3 ProjectOnPlane(const Vector3 &v, const Vector3 &n); - /// - /// Projects a vector onto the horizontal plane. - /// - /// The vector to project - /// A 2D carthesian vector with the coordinates in the horizontal - /// plane. - static Vector2 ProjectHorizontalPlane(const Vector3 &vector); - - /// - /// Calculate the angle between two vectors - /// - /// The first vector - /// The second vector - /// - /// This reterns an unsigned angle which is the shortest distance - /// between the two vectors. Use Vector3::SignedAngle if a - /// signed angle is needed. - static float Angle(const Vector3 &vector1, const Vector3 &vector2); - - /// - /// Calculate the angle between two vectors rotation around an axis. - /// - /// The starting vector - /// The ending vector - /// The axis to rotate around - /// The signed angle - static float SignedAngle(const Vector3 &from, const Vector3 &to, + /// @brief The angle between two vectors + /// @param v1 The first vector + /// @param v2 The second vector + /// @return The angle between the two vectors + /// @remark This reterns an unsigned angle which is the shortest distance + /// between the two vectors. Use Vector3::SignedAngle if a signed angle is + /// needed. + static float Angle(const Vector3 &v1, const Vector3 &v2); + /// @brief The signed angle between two vectors + /// @param v1 The starting vector + /// @param v2 The ending vector + /// @param axis The axis to rotate around + /// @return The signed angle between the two vectors + static float SignedAngle(const Vector3 &v1, const Vector3 &v2, const Vector3 &axis); - /// - /// Lerp between two vectors - /// - /// The from vector - /// The to vector - /// The interpolation distance (0..1) - /// The lerped vector - /// The factor f is unclamped. Value 0 matches the *from* vector, Value 1 - /// matches the *to* vector Value -1 is *from* vector minus the difference - /// between *from* and *to* etc. - static Vector3 Lerp(const Vector3 &from, const Vector3 &to, float f); + /// @brief Lerp (linear interpolation) between two vectors + /// @param v1 The starting vector + /// @param v2 The ending vector + /// @param f The interpolation distance + /// @return The lerped vector + /// @remark The factor f is unclamped. Value 0 matches the vector *v1*, Value + /// 1 matches vector *v2*. Value -1 is vector *v1* minus the difference + /// between *v1* and *v2* etc. + static Vector3 Lerp(const Vector3 &v1, const Vector3 &v2, float f); }; + } // namespace Passer using namespace Passer; diff --git a/test/Spherical_test.cc b/test/Spherical_test.cc index 2740804..df8f18a 100644 --- a/test/Spherical_test.cc +++ b/test/Spherical_test.cc @@ -77,9 +77,9 @@ TEST(Spherical, Incident1) { EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-02); Vector3 r = Vector3(sr); - EXPECT_NEAR(r.x, v.x, 1.0e-02) << "toVector3.x 1 0 0"; - EXPECT_NEAR(r.y, v.y, 1.0e-02) << "toVector3.y 1 0 0"; - EXPECT_NEAR(r.z, v.z, 1.0e-02) << "toVector3.z 1 0 0"; + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-02) << "toVector3.x 1 0 0"; + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-02) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-02) << "toVector3.z 1 0 0"; } TEST(Spherical, Incident2) { @@ -92,9 +92,9 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); Vector3 r = Vector3(sr); - EXPECT_NEAR(r.x, v.x, 1.0e-06); - EXPECT_NEAR(r.y, v.y, 1.0e-06); - EXPECT_NEAR(r.z, v.z, 1.0e-06); + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(0.0f, 1.0f, 1.0f); s = Spherical(v); @@ -105,9 +105,9 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(s.verticalAngle, sr.verticalAngle, 1.0e-05); r = Vector3(sr); - EXPECT_NEAR(r.x, v.x, 1.0e-06); - EXPECT_NEAR(r.y, v.y, 1.0e-06); - EXPECT_NEAR(r.z, v.z, 1.0e-06); + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); v = Vector3(1.0f, 1.0f, 1.0f); s = Spherical(v); @@ -117,9 +117,9 @@ TEST(Spherical, Incident2) { EXPECT_NEAR(s.horizontalAngle, 45.0F, 1.0e-02); EXPECT_NEAR(s.verticalAngle, 35.26F, 1.0e-02); - EXPECT_NEAR(r.x, v.x, 1.0e-06); - EXPECT_NEAR(r.y, v.y, 1.0e-06); - EXPECT_NEAR(r.z, v.z, 1.0e-06); + EXPECT_NEAR(r.Right(), v.Right(), 1.0e-06); + EXPECT_NEAR(r.Up(), v.Up(), 1.0e-06); + EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-06); // s = Spherical(10, 45, 45); // r = s.ToVector3(); diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc index f08c252..ba61ec6 100644 --- a/test/Vector2_test.cc +++ b/test/Vector2_test.cc @@ -168,11 +168,17 @@ TEST(Vector2, Subtract) { v2 = Vector2(4, 5); v = v1 - v2; EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 - 4 5"; + v = v1; + v -= v2; + EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 - 4 5"; v2 = Vector2(0, 0); v = v1 - v2; EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 - 0 0"; + v -= v2; + EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 - 0 0"; + if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); v = v1 - v2; @@ -197,10 +203,15 @@ TEST(Vector2, Addition) { v2 = Vector2(-1, -2); v = v1 + v2; EXPECT_TRUE(v == Vector2(3, 3)) << "4 5 + -1 -2"; + v = v1; + v += v2; + EXPECT_TRUE(v == Vector2(3, 3)) << "4 5 + -1 -2"; v2 = Vector2(0, 0); v = v1 + v2; EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 + 0 0"; + v += v2; + EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 + 0 0"; if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); diff --git a/test/Vector3_test.cc b/test/Vector3_test.cc index 483cbdb..4e5003c 100644 --- a/test/Vector3_test.cc +++ b/test/Vector3_test.cc @@ -12,25 +12,25 @@ TEST(Vector3, FromSpherical) { Spherical s = Spherical(v); Vector3 r = Vector3(s); - EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 0 1"; - EXPECT_NEAR(r.y, 0.0F, 1.0e-06) << "toVector3.y 0 0 1"; - EXPECT_FLOAT_EQ(r.z, 1.0F) << "toVector3.z 0 0 1"; + EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 0 1"; + EXPECT_NEAR(r.Up(), 0.0F, 1.0e-06) << "toVector3.y 0 0 1"; + EXPECT_FLOAT_EQ(r.Forward(), 1.0F) << "toVector3.z 0 0 1"; v = Vector3(0, 1, 0); s = Spherical(v); r = Vector3(s); - EXPECT_FLOAT_EQ(r.x, 0.0F) << "toVector3.x 0 1 0"; - EXPECT_FLOAT_EQ(r.y, 1.0F) << "toVector3.y 0 1 0"; - EXPECT_NEAR(r.z, 0.0F, 1.0e-06) << "toVector3.z 0 1 0"; + EXPECT_FLOAT_EQ(r.Right(), 0.0F) << "toVector3.x 0 1 0"; + EXPECT_FLOAT_EQ(r.Up(), 1.0F) << "toVector3.y 0 1 0"; + EXPECT_NEAR(r.Forward(), 0.0F, 1.0e-06) << "toVector3.z 0 1 0"; v = Vector3(1, 0, 0); s = Spherical(v); r = Vector3(s); - EXPECT_FLOAT_EQ(r.x, 1.0F) << "toVector3.x 1 0 0"; - EXPECT_NEAR(r.y, 0.0F, 1.0e-06) << "toVector3.y 1 0 0"; - EXPECT_NEAR(r.z, 0.0F, 1.0e-06) << "toVector3.z 1 0 0"; + EXPECT_FLOAT_EQ(r.Right(), 1.0F) << "toVector3.x 1 0 0"; + EXPECT_NEAR(r.Up(), 0.0F, 1.0e-06) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.Forward(), 0.0F, 1.0e-06) << "toVector3.z 1 0 0"; } TEST(Vector3, Magnitude) { @@ -118,12 +118,12 @@ TEST(Vector3, Normalize) { if (std::numeric_limits::is_iec559) { v1 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v = v1.normalized(); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "v.normalized INFINITY INFINITY INFINITY"; v1 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); v = v1.normalized(); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "v.normalized -INFINITY -INFINITY -INFINITY"; } } @@ -409,12 +409,12 @@ TEST(Vector3, Cross) { if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v = Vector3::Cross(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "Cross(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); v = Vector3::Cross(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "Cross(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } @@ -442,12 +442,12 @@ TEST(Vector3, Project) { if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v = Vector3::Project(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "Project(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); v = Vector3::Project(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "Project(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } @@ -475,12 +475,12 @@ TEST(Vector3, ProjectOnPlane) { if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v = Vector3::ProjectOnPlane(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); v = Vector3::ProjectOnPlane(v1, v2); - r = isnan(v.x) && isnan(v.y) && isnan(v.z); + r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, -INFINITY -INFINITY -INFINITY)"; } }