diff --git a/Direction.cpp b/Direction.cpp index 86fa77c..e4541ca 100644 --- a/Direction.cpp +++ b/Direction.cpp @@ -43,24 +43,22 @@ const DirectionOf DirectionOf::right = DirectionOf(AngleOf::Degrees(90), AngleOf()); template -Vector3 DirectionOf::ToVector3() const { +Vector3Of DirectionOf::ToVector3() const { Quaternion q = Quaternion::Euler(-this->vertical.InDegrees(), this->horizontal.InDegrees(), 0); - Vector3 v = q * Vector3::forward; + Vector3Of v = q * Vector3Of::forward; return v; } template -DirectionOf DirectionOf::FromVector3(Vector3 vector) { +DirectionOf DirectionOf::FromVector3(Vector3Of vector) { DirectionOf d; d.horizontal = AngleOf::Atan2( - vector.Right(), - vector - .Forward()); // AngleOf::Radians(atan2f(v.Right(), v.Forward())); - d.vertical = - AngleOf::Degrees(-90) - - AngleOf::Acos( - vector.Up()); // AngleOf::Radians(-(0.5f * pi) - acosf(v.Up())); + vector.horizontal, + vector.depth); // AngleOf::Radians(atan2f(v.Right(), v.Forward())); + d.vertical = AngleOf::Degrees(-90) - + AngleOf::Acos(vector.vertical); // AngleOf::Radians(-(0.5f + // * pi) - acosf(v.Up())); d.Normalize(); return d; } @@ -101,4 +99,4 @@ void DirectionOf::Normalize() { template class LinearAlgebra::DirectionOf; template class LinearAlgebra::DirectionOf; -} \ No newline at end of file +} // namespace LinearAlgebra \ No newline at end of file diff --git a/Direction.h b/Direction.h index c9472de..2224e2e 100644 --- a/Direction.h +++ b/Direction.h @@ -9,7 +9,9 @@ namespace LinearAlgebra { -struct Vector3; +//struct Vector3; +template +class Vector3Of; /// @brief A direction using angles in various representations /// @tparam T The implementation type used for the representation of the angles @@ -38,13 +40,13 @@ class DirectionOf { /// @brief Convert the direction into a carthesian vector /// @return The carthesian vector corresponding to this direction. - Vector3 ToVector3() const; + Vector3Of ToVector3() const; /// @brief Convert a carthesian vector into a direction /// @param v The carthesian vector /// @return The direction. /// @note Information about the length of the carthesian vector is not /// included in this transformation. - static DirectionOf FromVector3(Vector3 vector); + static DirectionOf FromVector3(Vector3Of vector); /// @brief Create a direction using angle values in degrees /// @param horizontal The horizontal angle in degrees diff --git a/Polar.cpp b/Polar.cpp index 46c1842..2ad7967 100644 --- a/Polar.cpp +++ b/Polar.cpp @@ -36,11 +36,11 @@ PolarOf PolarOf::Radians(float distance, float radians) { return PolarOf(distance, AngleOf::Radians(radians)); } -template -PolarOf PolarOf::FromVector2(Vector2Of v) { +template <> +PolarOf PolarOf::FromVector2(Vector2Of v) { float distance = v.Magnitude(); - AngleOf angle = Vector2Of::SignedAngle(Vector2Of::forward, v); - PolarOf p = PolarOf(distance, angle); + AngleOf angle = Vector2Of::SignedAngle(Vector2Of::forward, v); + PolarOf p = PolarOf(distance, angle); return p; } template @@ -175,4 +175,4 @@ PolarOf PolarOf::Rotate(const PolarOf& v, AngleOf angle) { } template class LinearAlgebra::PolarOf; -template class LinearAlgebra::PolarOf; \ No newline at end of file +template class LinearAlgebra::PolarOf; diff --git a/Polar.h b/Polar.h index 728f9f2..4638c99 100644 --- a/Polar.h +++ b/Polar.h @@ -56,7 +56,7 @@ class PolarOf { /// @brief Convert a vector from 2D carthesian coordinates to polar /// coordinates /// @param v The vector to convert - static PolarOf FromVector2(Vector2Of v); + static PolarOf FromVector2(Vector2Of v); /// @brief Convert a vector from spherical coordinates to polar coordinates /// @param s The vector to convert /// @note The resulting vector will be projected on the horizontal plane diff --git a/Quaternion.cpp b/Quaternion.cpp index 5bae6c2..50459e4 100644 --- a/Quaternion.cpp +++ b/Quaternion.cpp @@ -44,8 +44,8 @@ Quaternion::~Quaternion() {} const Quaternion Quaternion::identity = Quaternion(0, 0, 0, 1); -Vector3 Quaternion::xyz() const { - return Vector3(x, y, z); +Vector3Of Quaternion::xyz() const { + return Vector3Of(x, y, z); } float Quaternion::GetLength() const { @@ -78,18 +78,18 @@ float Quaternion::Dot(Quaternion a, Quaternion b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } -Vector3 Quaternion::ToAngles(const Quaternion& q1) { +Vector3Of Quaternion::ToAngles(const Quaternion& q1) { float test = q1.x * q1.y + q1.z * q1.w; if (test > 0.499f) { // singularity at north pole - return Vector3(0, 2 * (float)atan2(q1.x, q1.w) * Rad2Deg, 90); + return Vector3Of(0, 2 * (float)atan2(q1.x, q1.w) * Rad2Deg, 90); } else if (test < -0.499f) { // singularity at south pole - return Vector3(0, -2 * (float)atan2(q1.x, q1.w) * Rad2Deg, -90); + return Vector3Of(0, -2 * (float)atan2(q1.x, q1.w) * Rad2Deg, -90); } else { float sqx = q1.x * q1.x; float sqy = q1.y * q1.y; float sqz = q1.z * q1.z; - return Vector3( + return Vector3Of( atan2f(2 * q1.x * q1.w - 2 * q1.y * q1.z, 1 - 2 * sqx - 2 * sqz) * Rad2Deg, atan2f(2 * q1.y * q1.w - 2 * q1.x * q1.z, 1 - 2 * sqy - 2 * sqz) * @@ -128,7 +128,7 @@ Quaternion Quaternion::operator*(const Quaternion& r2) const { -this->x * r2.x - this->y * r2.y - this->z * r2.z + this->w * r2.w); }; -Vector3 Quaternion::operator*(const Vector3& p) const { +Vector3Of Quaternion::operator*(const Vector3Of& p) const { float num = this->x * 2; float num2 = this->y * 2; float num3 = this->z * 2; @@ -142,9 +142,9 @@ Vector3 Quaternion::operator*(const Vector3& p) const { float num11 = this->w * num2; float num12 = this->w * num3; - float px = p.Right(); - float py = p.Up(); - float pz = p.Forward(); + float px = p.horizontal; + float py = p.vertical; + float pz = p.depth; // Vector3 result = Vector3::zero; // result.x = float rx = @@ -155,7 +155,7 @@ Vector3 Quaternion::operator*(const Vector3& p) const { // result.z = float rz = (num8 - num11) * px + (num9 + num10) * py + (1 - (num4 + num5)) * pz; - Vector3 result = Vector3(rx, ry, rz); + Vector3Of result = Vector3Of(rx, ry, rz); return result; } @@ -168,23 +168,23 @@ Quaternion Quaternion::Inverse(Quaternion r) { return Quaternion(-r.x / n, -r.y / n, -r.z / n, r.w / n); } -Quaternion Quaternion::LookRotation(const Vector3& forward) { - Vector3 up = Vector3(0, 1, 0); +Quaternion Quaternion::LookRotation(const Vector3Of& forward) { + Vector3Of up = Vector3Of(0, 1, 0); return LookRotation(forward, up); } -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.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; +Quaternion Quaternion::LookRotation(const Vector3Of& forward, const Vector3Of& up) { + Vector3Of nForward = Vector3Of::Normalize(forward); + Vector3Of nRight = Vector3Of::Normalize(Vector3Of::Cross(up, nForward)); + Vector3Of nUp = Vector3Of::Cross(nForward, nRight); + float m00 = nRight.horizontal; // x; + float m01 = nRight.vertical; // y; + float m02 = nRight.depth; // z; + float m10 = nUp.horizontal; // x; + float m11 = nUp.vertical; // y; + float m12 = nUp.depth; // z; + float m20 = nForward.horizontal; // x; + float m21 = nForward.vertical; // y; + float m22 = nForward.depth; // z; float num8 = (m00 + m11) + m22; Quaternion quaternion = Quaternion(); @@ -224,11 +224,11 @@ Quaternion Quaternion::LookRotation(const Vector3& forward, const Vector3& up) { return quaternion; } -Quaternion Quaternion::FromToRotation(Vector3 fromDirection, - Vector3 toDirection) { - Vector3 axis = Vector3::Cross(fromDirection, toDirection); - axis = Vector3::Normalize(axis); - AngleOf angle = Vector3::SignedAngle(fromDirection, toDirection, axis); +Quaternion Quaternion::FromToRotation(Vector3Of fromDirection, + Vector3Of toDirection) { + Vector3Of axis = Vector3Of::Cross(fromDirection, toDirection); + axis = Vector3Of::Normalize(axis); + AngleOf angle = Vector3Of::SignedAngle(fromDirection, toDirection, axis); Quaternion rotation = Quaternion::AngleAxis(angle.InDegrees(), axis); return rotation; } @@ -244,18 +244,18 @@ Quaternion Quaternion::RotateTowards(const Quaternion& from, return SlerpUnclamped(from, to, t); } -Quaternion Quaternion::AngleAxis(float angle, const Vector3& axis) { - if (Vector3::SqrMagnitude(axis) == 0.0f) +Quaternion Quaternion::AngleAxis(float angle, const Vector3Of& axis) { + if (Vector3Of::SqrMagnitudeOf(axis) == 0.0f) return Quaternion(); Quaternion result = Quaternion(); float radians = angle * Deg2Rad; radians *= 0.5f; - Vector3 axis2 = axis * (float)sin(radians); - result.x = axis2.Right(); // x; - result.y = axis2.Up(); // y; - result.z = axis2.Forward(); // z; + Vector3Of axis2 = axis * (float)sin(radians); + result.x = axis2.horizontal; // x; + result.y = axis2.vertical; // y; + result.z = axis2.depth; // z; result.w = (float)cos(radians); return Quaternion::Normalize(result); @@ -266,23 +266,23 @@ float Quaternion::Angle(Quaternion a, Quaternion b) { return (float)acos(fmin(fabs(f), 1)) * 2 * Rad2Deg; } -void Quaternion::ToAngleAxis(float* angle, Vector3* axis) { +void Quaternion::ToAngleAxis(float* angle, Vector3Of* axis) { Quaternion::ToAxisAngleRad(*this, axis, angle); *angle *= Rad2Deg; } void Quaternion::ToAxisAngleRad(const Quaternion& q, - Vector3* const axis, + Vector3Of* const axis, float* angle) { Quaternion q1 = (fabs(q.w) > 1.0f) ? Quaternion::Normalize(q) : q; *angle = 2.0f * acosf(q1.w); // angle float den = sqrtf(1.0F - q1.w * q1.w); if (den > 0.0001f) { - *axis = Vector3::Normalize(q1.xyz() / den); + *axis = Vector3Of::Normalize(q1.xyz() / den); } else { // This occurs when the angle is zero. // Not a problem: just set an arbitrary normalized axis. - *axis = Vector3(1, 0, 0); + *axis = Vector3Of(1, 0, 0); } } Quaternion Quaternion::SlerpUnclamped(const Quaternion& a, @@ -298,9 +298,9 @@ Quaternion Quaternion::SlerpUnclamped(const Quaternion& a, return a; } - const Vector3 axyz = a.xyz(); - const Vector3 bxyz = b.xyz(); - float cosHalfAngle = a.w * b.w + Vector3::Dot(axyz, bxyz); + const Vector3Of axyz = a.xyz(); + const Vector3Of bxyz = b.xyz(); + float cosHalfAngle = a.w * b.w + Vector3Of::Dot(axyz, bxyz); Quaternion b2 = b; if (cosHalfAngle >= 1.0f || cosHalfAngle <= -1.0f) { @@ -328,9 +328,9 @@ Quaternion Quaternion::SlerpUnclamped(const Quaternion& a, blendA = 1.0f - t; blendB = t; } - Vector3 v = axyz * blendA + b2.xyz() * blendB; + Vector3Of v = axyz * blendA + b2.xyz() * blendB; Quaternion result = - Quaternion(v.Right(), v.Up(), v.Forward(), blendA * a.w + blendB * b2.w); + Quaternion(v.horizontal, v.vertical, v.depth, blendA * a.w + blendB * b2.w); if (result.GetLengthSquared() > 0.0f) return Quaternion::Normalize(result); else @@ -348,16 +348,16 @@ Quaternion Quaternion::Slerp(const Quaternion& a, } Quaternion Quaternion::Euler(float x, float y, float z) { - return Quaternion::Euler(Vector3(x, y, z)); + return Quaternion::Euler(Vector3Of(x, y, z)); } -Quaternion Quaternion::Euler(Vector3 euler) { +Quaternion Quaternion::Euler(Vector3Of euler) { return Quaternion::FromEulerRad(euler * Deg2Rad); } -Quaternion Quaternion::FromEulerRad(Vector3 euler) { - float yaw = euler.Right(); - float pitch = euler.Up(); - float roll = euler.Forward(); +Quaternion Quaternion::FromEulerRad(Vector3Of euler) { + float yaw = euler.horizontal; + float pitch = euler.vertical; + float roll = euler.depth; float rollOver2 = roll * 0.5f; float sinRollOver2 = (float)sin((float)rollOver2); float cosRollOver2 = (float)cos((float)rollOver2); @@ -380,15 +380,15 @@ Quaternion Quaternion::FromEulerRad(Vector3 euler) { } Quaternion Quaternion::EulerXYZ(float x, float y, float z) { - return Quaternion::EulerXYZ(Vector3(x, y, z)); + return Quaternion::EulerXYZ(Vector3Of(x, y, z)); } -Quaternion Quaternion::EulerXYZ(Vector3 euler) { +Quaternion Quaternion::EulerXYZ(Vector3Of euler) { return Quaternion::FromEulerRadXYZ(euler * Deg2Rad); } -Quaternion Quaternion::FromEulerRadXYZ(Vector3 euler) { - float yaw = euler.Right(); // x; - float pitch = euler.Up(); // y; - float roll = euler.Forward(); // z; +Quaternion Quaternion::FromEulerRadXYZ(Vector3Of euler) { + float yaw = euler.horizontal; // x; + float pitch = euler.vertical; // y; + float roll = euler.depth; // z; float rollOver2 = roll * 0.5f; float sinRollOver2 = (float)sin((float)rollOver2); float cosRollOver2 = (float)cos((float)rollOver2); @@ -410,29 +410,29 @@ Quaternion Quaternion::FromEulerRadXYZ(Vector3 euler) { return result; } -float Quaternion::GetAngleAround(Vector3 axis, Quaternion rotation) { +float Quaternion::GetAngleAround(Vector3Of axis, Quaternion rotation) { Quaternion secondaryRotation = GetRotationAround(axis, rotation); float rotationAngle; - Vector3 rotationAxis; + Vector3Of rotationAxis; secondaryRotation.ToAngleAxis(&rotationAngle, &rotationAxis); // Do the axis point in opposite directions? - if (Vector3::Dot(axis, rotationAxis) < 0) + if (Vector3Of::Dot(axis, rotationAxis) < 0) rotationAngle = -rotationAngle; return rotationAngle; } -Quaternion Quaternion::GetRotationAround(Vector3 axis, Quaternion rotation) { - Vector3 ra = Vector3(rotation.x, rotation.y, rotation.z); // rotation axis - Vector3 p = Vector3::Project( +Quaternion Quaternion::GetRotationAround(Vector3Of axis, Quaternion rotation) { + Vector3Of ra = Vector3Of(rotation.x, rotation.y, rotation.z); // rotation axis + Vector3Of p = Vector3Of::Project( ra, axis); // return projection ra on to axis (parallel component) - Quaternion twist = Quaternion(p.Right(), p.Up(), p.Forward(), rotation.w); + Quaternion twist = Quaternion(p.horizontal, p.vertical, p.depth, rotation.w); twist = Quaternion::Normalize(twist); return twist; } -void Quaternion::GetSwingTwist(Vector3 axis, +void Quaternion::GetSwingTwist(Vector3Of axis, Quaternion rotation, Quaternion* swing, Quaternion* twist) { diff --git a/Quaternion.h b/Quaternion.h index 1687dc9..6c2d8e2 100644 --- a/Quaternion.h +++ b/Quaternion.h @@ -89,7 +89,7 @@ struct Quaternion : Quat { /// The quaternion to convert /// A vector containing euler angles /// The euler angles performed in the order: Z, X, Y - static Vector3 ToAngles(const Quaternion& q); + static Vector3Of ToAngles(const Quaternion& q); Matrix2 ToRotationMatrix(); @@ -98,7 +98,7 @@ struct Quaternion : Quat { /// /// The vector to rotate /// The rotated vector - Vector3 operator*(const Vector3& vector) const; + Vector3Of operator*(const Vector3Of& vector) const; /// /// Multiply this quaternion with another quaternion /// @@ -132,8 +132,8 @@ struct Quaternion : Quat { /// The look direction /// The up direction /// The look rotation - static Quaternion LookRotation(const Vector3& forward, - const Vector3& upwards); + static Quaternion LookRotation(const Vector3Of& forward, + const Vector3Of& upwards); /// /// Creates a quaternion with the given forward direction with up = /// Vector3::up @@ -143,7 +143,7 @@ struct Quaternion : Quat { /// For the rotation, Vector::up is used for the up direction. /// Note: if the forward direction == Vector3::up, the result is /// Quaternion::identity - static Quaternion LookRotation(const Vector3& forward); + static Quaternion LookRotation(const Vector3Of& forward); /// /// Calculat the rotation from on vector to another @@ -151,7 +151,7 @@ struct Quaternion : Quat { /// The from direction /// The to direction /// The rotation from the first to the second vector - static Quaternion FromToRotation(Vector3 fromDirection, Vector3 toDirection); + static Quaternion FromToRotation(Vector3Of fromDirection, Vector3Of toDirection); /// /// Rotate form one orientation to anther with a maximum amount of degrees @@ -170,13 +170,13 @@ struct Quaternion : Quat { /// The angle /// The axis /// The resulting quaternion - static Quaternion AngleAxis(float angle, const Vector3& axis); + static Quaternion AngleAxis(float angle, const Vector3Of& axis); /// /// Convert this quaternion to angle/axis representation /// /// A pointer to the angle for the result /// A pointer to the axis for the result - void ToAngleAxis(float* angle, Vector3* axis); + void ToAngleAxis(float* angle, Vector3Of* axis); /// /// Get the angle between two orientations @@ -225,7 +225,7 @@ struct Quaternion : Quat { /// Vector with the euler angles /// The resulting quaternion /// Rotation are appied in the order Z, X, Y. - static Quaternion Euler(Vector3 eulerAngles); + static Quaternion Euler(Vector3Of eulerAngles); /// /// Create a rotation from euler angles @@ -242,7 +242,7 @@ struct Quaternion : Quat { /// Vector with the euler angles /// The resulting quaternion /// Rotation are appied in the order X, Y, Z. - static Quaternion EulerXYZ(Vector3 eulerAngles); + static Quaternion EulerXYZ(Vector3Of eulerAngles); /// /// Returns the angle of around the give axis for a rotation @@ -250,14 +250,14 @@ struct Quaternion : Quat { /// The axis around which the angle should be /// computed The source rotation /// The signed angle around the axis - static float GetAngleAround(Vector3 axis, Quaternion rotation); + static float GetAngleAround(Vector3Of axis, Quaternion rotation); /// /// Returns the rotation limited around the given axis /// /// The axis which which the rotation should be /// limited The source rotation /// The rotation around the given axis - static Quaternion GetRotationAround(Vector3 axis, Quaternion rotation); + static Quaternion GetRotationAround(Vector3Of axis, Quaternion rotation); /// /// Swing-twist decomposition of a rotation /// @@ -266,7 +266,7 @@ struct Quaternion : Quat { /// A pointer to the quaternion for the swing /// result A pointer to the quaternion for the /// twist result - static void GetSwingTwist(Vector3 axis, + static void GetSwingTwist(Vector3Of axis, Quaternion rotation, Quaternion* swing, Quaternion* twist); @@ -284,11 +284,11 @@ struct Quaternion : Quat { float GetLengthSquared() const; static float GetLengthSquared(const Quaternion& q); - void ToAxisAngleRad(const Quaternion& q, Vector3* const axis, float* angle); - static Quaternion FromEulerRad(Vector3 euler); - static Quaternion FromEulerRadXYZ(Vector3 euler); + void ToAxisAngleRad(const Quaternion& q, Vector3Of* const axis, float* angle); + static Quaternion FromEulerRad(Vector3Of euler); + static Quaternion FromEulerRadXYZ(Vector3Of euler); - Vector3 xyz() const; + Vector3Of xyz() const; }; } // namespace LinearAlgebra diff --git a/Spherical.cpp b/Spherical.cpp index 0371f92..5311bf2 100644 --- a/Spherical.cpp +++ b/Spherical.cpp @@ -64,15 +64,15 @@ SphericalOf SphericalOf::FromPolar(PolarOf polar) { } template -SphericalOf SphericalOf::FromVector3(Vector3 v) { - float distance = v.magnitude(); +SphericalOf SphericalOf::FromVector3(Vector3Of v) { + float distance = v.Magnitude(); if (distance == 0.0f) { return SphericalOf(distance, AngleOf(), AngleOf()); } else { AngleOf verticalAngle = - AngleOf::Radians((pi / 2 - acosf(v.Up() / distance))); + AngleOf::Radians((pi / 2 - acosf(v.vertical / distance))); AngleOf horizontalAngle = - AngleOf::Radians(atan2f(v.Right(), v.Forward())); + AngleOf::Radians(atan2f(v.horizontal, v.depth)); return SphericalOf(distance, horizontalAngle, verticalAngle); } } @@ -89,7 +89,7 @@ SphericalOf SphericalOf::FromVector3(Vector3 v) { * @return Vector3 The 3D vector representation of the spherical coordinates. */ template -Vector3 SphericalOf::ToVector3() const { +Vector3Of SphericalOf::ToVector3() const { float verticalRad = (pi / 2) - this->direction.vertical.InRadians(); float horizontalRad = this->direction.horizontal.InRadians(); @@ -102,7 +102,7 @@ Vector3 SphericalOf::ToVector3() const { float y = this->distance * cosVertical; float z = this->distance * sinVertical * cosHorizontal; - Vector3 v = Vector3(x, y, z); + Vector3Of v = Vector3Of(x, y, z); return v; } @@ -145,9 +145,9 @@ SphericalOf SphericalOf::operator-() const { template SphericalOf SphericalOf::operator-(const SphericalOf& s2) const { // let's do it the easy way... - Vector3 v1 = this->ToVector3(); - Vector3 v2 = s2.ToVector3(); - Vector3 v = v1 - v2; + Vector3Of v1 = this->ToVector3(); + Vector3Of v2 = s2.ToVector3(); + Vector3Of v = v1 - v2; SphericalOf r = SphericalOf::FromVector3(v); return r; } @@ -160,9 +160,9 @@ SphericalOf SphericalOf::operator-=(const SphericalOf& v) { template SphericalOf SphericalOf::operator+(const SphericalOf& s2) const { // let's do it the easy way... - Vector3 v1 = this->ToVector3(); - Vector3 v2 = s2.ToVector3(); - Vector3 v = v1 + v2; + Vector3Of v1 = this->ToVector3(); + Vector3Of v2 = s2.ToVector3(); + Vector3Of v = v1 + v2; SphericalOf r = SphericalOf::FromVector3(v); return r; /* @@ -240,9 +240,9 @@ float SphericalOf::DistanceBetween(const SphericalOf& v1, const SphericalOf& v2) { // SphericalOf difference = v1 - v2; // return difference.distance; - Vector3 vec1 = v1.ToVector3(); - Vector3 vec2 = v2.ToVector3(); - float distance = Vector3::Distance(vec1, vec2); + Vector3Of vec1 = v1.ToVector3(); + Vector3Of vec2 = v2.ToVector3(); + float distance = Vector3Of::Distance(vec1, vec2); return distance; } @@ -253,8 +253,8 @@ AngleOf SphericalOf::AngleBetween(const SphericalOf& v1, // if (denominator < epsilon) // return 0.0f; - Vector3 v1_3 = v1.ToVector3(); - Vector3 v2_3 = v2.ToVector3(); + Vector3Of v1_3 = v1.ToVector3(); + Vector3Of v2_3 = v2.ToVector3(); // float dot = Vector3::Dot(v1_3, v2_3); // float fraction = dot / denominator; // if (isnan(fraction)) @@ -262,7 +262,7 @@ AngleOf SphericalOf::AngleBetween(const SphericalOf& v1, // float cdot = Float::Clamp(fraction, -1.0, 1.0); // float r = ((float)acos(cdot)) * Rad2Deg; - AngleSingle r = Vector3::Angle(v1_3, v2_3); + AngleSingle r = Vector3Of::UnsignedAngle(v1_3, v2_3); return AngleOf::Degrees(r.InDegrees()); } @@ -270,10 +270,10 @@ template AngleOf SphericalOf::SignedAngleBetween(const SphericalOf& v1, const SphericalOf& v2, const SphericalOf& axis) { - Vector3 v1_vector = v1.ToVector3(); - Vector3 v2_vector = v2.ToVector3(); - Vector3 axis_vector = axis.ToVector3(); - AngleSingle r = Vector3::SignedAngle(v1_vector, v2_vector, axis_vector); + Vector3Of v1_vector = v1.ToVector3(); + Vector3Of v2_vector = v2.ToVector3(); + Vector3Of axis_vector = axis.ToVector3(); + AngleSingle r = Vector3Of::SignedAngle(v1_vector, v2_vector, axis_vector); return AngleOf::Degrees(r.InDegrees()); } diff --git a/Spherical.h b/Spherical.h index 309db03..91038a0 100644 --- a/Spherical.h +++ b/Spherical.h @@ -59,10 +59,10 @@ class SphericalOf { /// @brief Create a Spherical coordinate from a Vector3 coordinate /// @param v The vector coordinate /// @return The spherical coordinate - static SphericalOf FromVector3(Vector3 v); + static SphericalOf FromVector3(Vector3Of v); /// @brief Convert the spherical coordinate to a Vector3 coordinate /// @return The vector coordinate - Vector3 ToVector3() const; + Vector3Of ToVector3() const; /// @brief A spherical vector with zero degree angles and distance const static SphericalOf zero; diff --git a/SwingTwist.cpp b/SwingTwist.cpp index deca73c..f26e49e 100644 --- a/SwingTwist.cpp +++ b/SwingTwist.cpp @@ -69,9 +69,9 @@ Quaternion SwingTwistOf::ToQuaternion() const { template SwingTwistOf SwingTwistOf::FromQuaternion(Quaternion q) { - Vector3 angles = Quaternion::ToAngles(q); + Vector3Of angles = Quaternion::ToAngles(q); SwingTwistOf r = - SwingTwistOf::Degrees(angles.Up(), angles.Right(), angles.Forward()); + SwingTwistOf::Degrees(angles.vertical, angles.horizontal, angles.depth); r.Normalize(); return r; } @@ -80,7 +80,7 @@ template SphericalOf SwingTwistOf::ToAngleAxis() const { Quaternion q = this->ToQuaternion(); float angle; - Vector3 axis; + Vector3Of axis; q.ToAngleAxis(&angle, &axis); DirectionOf direction = DirectionOf::FromVector3(axis); @@ -90,7 +90,7 @@ SphericalOf SwingTwistOf::ToAngleAxis() const { template SwingTwistOf SwingTwistOf::FromAngleAxis(SphericalOf aa) { - Vector3 vectorAxis = aa.direction.ToVector3(); + Vector3Of vectorAxis = aa.direction.ToVector3(); Quaternion q = Quaternion::AngleAxis(aa.distance, vectorAxis); return SwingTwistOf(); } @@ -139,7 +139,7 @@ SwingTwistOf SwingTwistOf::Inverse(SwingTwistOf rotation) { template SwingTwistOf SwingTwistOf::AngleAxis(float angle, const DirectionOf& axis) { - Vector3 axis_vector = axis.ToVector3(); + Vector3Of axis_vector = axis.ToVector3(); Quaternion q = Quaternion::AngleAxis(angle, axis_vector); SwingTwistOf r = SwingTwistOf::FromQuaternion(q); return r; diff --git a/Vector2.cpp b/Vector2.cpp index f703900..ccf62ac 100644 --- a/Vector2.cpp +++ b/Vector2.cpp @@ -7,181 +7,7 @@ #include "FloatSingle.h" #include "Vector3.h" -// #if defined(AVR) -// #include -// #else #include -// #endif - -/* -Vector2::Vector2() { - x = 0; - y = 0; -} -Vector2::Vector2(float _x, float _y) { - x = _x; - y = _y; -} -// Vector2::Vector2(Vec2 v) { -// x = v.x; -// y = v.y; -// } -Vector2::Vector2(Vector3 v) { - x = v.Right(); // x; - y = v.Forward(); // z; -} -Vector2::Vector2(PolarSingle p) { - float horizontalRad = p.angle.InDegrees() * Deg2Rad; - float cosHorizontal = cosf(horizontalRad); - float sinHorizontal = sinf(horizontalRad); - - x = p.distance * sinHorizontal; - y = p.distance * cosHorizontal; -} - -Vector2::~Vector2() {} - -const Vector2 Vector2::zero = Vector2(0, 0); -const Vector2 Vector2::one = Vector2(1, 1); -const Vector2 Vector2::right = Vector2(1, 0); -const Vector2 Vector2::left = Vector2(-1, 0); -const Vector2 Vector2::up = Vector2(0, 1); -const Vector2 Vector2::down = Vector2(0, -1); -const Vector2 Vector2::forward = Vector2(0, 1); -const Vector2 Vector2::back = Vector2(0, -1); - -bool Vector2::operator==(const Vector2& v) { - return (this->x == v.x && this->y == v.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& 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) { - float num = Vector2::Magnitude(v); - Vector2 result = Vector2::zero; - if (num > Float::epsilon) { - result = v / num; - } - return result; -} -Vector2 Vector2::normalized() const { - float num = this->magnitude(); - Vector2 result = Vector2::zero; - if (num > Float::epsilon) { - result = ((Vector2) * this) / num; - } - return result; -} - -Vector2 Vector2::operator-() { - return Vector2(-this->x, -this->y); -} - -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::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& v1, const Vector2& v2) { - return Vector2(v1.x * v2.x, v1.y * v2.y); -} -// Vector2 Passer::LinearAlgebra::operator*(const Vector2 &v, float f) { -// return Vector2(v.x * f, v.y * f); -// } -// Vector2 Passer::LinearAlgebra::operator*(float f, const Vector2 &v) { -// return Vector2(v.x * f, v.y * f); -// } -Vector2 Vector2::operator*=(float f) { - this->x *= f; - this->y *= f; - return *this; -} -// Vector2 Passer::LinearAlgebra::operator/(const Vector2 &v, float f) { -// return Vector2(v.x / f, v.y / f); -// } -// Vector2 Passer::LinearAlgebra::operator/(float f, const Vector2 &v) { -// return Vector2(v.x / f, v.y / f); -// } -Vector2 Vector2::operator/=(float f) { - this->x /= f; - this->y /= f; - return *this; -} - -float Vector2::Dot(const Vector2& v1, const Vector2& v2) { - return v1.x * v2.x + v1.y * v2.y; -} - -float Vector2::Distance(const Vector2& v1, const Vector2& v2) { - return Magnitude(v1 - v2); -} - -float Vector2::Angle(const Vector2& v1, const Vector2& v2) { - return (float)fabs(SignedAngle(v1, v2)); -} -float Vector2::SignedAngle(const Vector2& v1, const Vector2& v2) { - float sqrMagFrom = v1.sqrMagnitude(); - float sqrMagTo = v2.sqrMagnitude(); - - if (sqrMagFrom == 0 || sqrMagTo == 0) - return 0; - if (!isfinite(sqrMagFrom) || !isfinite(sqrMagTo)) -#if defined(AVR) - return NAN; -#else - return nanf(""); -#endif - - float angleFrom = atan2f(v1.y, v1.x); - float angleTo = atan2f(v2.y, v2.x); - return -(angleTo - angleFrom) * Rad2Deg; -} - -Vector2 Vector2::Rotate(const Vector2& v, AngleSingle a) { - float angleRad = a.InDegrees() * Deg2Rad; -#if defined(AVR) - float sinValue = sin(angleRad); - float cosValue = cos(angleRad); // * Angle::Deg2Rad); -#else - float sinValue = (float)sinf(angleRad); - float cosValue = (float)cosf(angleRad); -#endif - - float tx = v.x; - float ty = v.y; - Vector2 r = Vector2((cosValue * tx) - (sinValue * ty), - (sinValue * tx) + (cosValue * ty)); - return r; -} - -Vector2 Vector2::Lerp(const Vector2& v1, const Vector2& v2, float f) { - Vector2 v = v1 + (v2 - v1) * f; - return v; -} - */ #pragma region Vector2Of @@ -193,10 +19,9 @@ Vector2Of::Vector2Of(T horizontal, T vertical) : horizontal(horizontal), vertical(vertical) {} template -Vector2Of Vector2Of::FromPolar(PolarOf p) { - float horizontalRad = p.angle.InDegrees() * Deg2Rad; - float cosHorizontal = cosf(horizontalRad); - float sinHorizontal = sinf(horizontalRad); +Vector2Of Vector2Of::FromPolar(PolarOf p) { + float cosHorizontal = AngleOf::Cos(p.angle); + float sinHorizontal = AngleOf::Sin(p.angle); Vector2Of v; v.horizontal = p.distance * sinHorizontal; @@ -226,7 +51,8 @@ template float Vector2Of::Magnitude() const { T sqr = this->horizontal * this->horizontal + this->vertical * this->vertical; float sqrFloat = static_cast(sqr); - return sqrtf(sqrFloat); + float r = sqrtf(sqrFloat); + return r; } template @@ -241,6 +67,13 @@ float Vector2Of::SqrMagnitude() const { return static_cast(sqr); } +template +float Vector2Of::Distance(const Vector2Of& v1, const Vector2Of& v2) { + Vector2Of delta = v1 - v2; + float r = MagnitudeOf(delta); + return r; +} + template Vector2Of Vector2Of::operator-() { return Vector2Of(-this->horizontal, -this->vertical); @@ -289,11 +122,6 @@ T Vector2Of::Dot(const Vector2Of& v1, const Vector2Of& v2) { return v1.horizontal * v2.horizontal + v1.vertical * v2.vertical; } -template -float Vector2Of::Distance(const Vector2Of& v1, const Vector2Of& v2) { - return MagnitudeOf(v1 - v2); -} - template Vector2Of Vector2Of::Normalize(const Vector2Of& v) { float num = Vector2Of::MagnitudeOf(v); @@ -305,68 +133,50 @@ Vector2Of Vector2Of::Normalize(const Vector2Of& v) { } template -AngleOf Vector2Of::UnsignedAngle(const Vector2Of& v1, - const Vector2Of& v2) { - return AngleOf::Abs(SignedAngle(v1, v2)); +AngleOf Vector2Of::UnsignedAngle(const Vector2Of& v1, + const Vector2Of& v2) { + return AngleOf::Abs(SignedAngle(v1, v2)); } template -AngleOf Vector2Of::SignedAngle(const Vector2Of& v1, const Vector2Of& v2) { +AngleOf Vector2Of::SignedAngle(const Vector2Of& v1, + const Vector2Of& v2) { float sqrMagFrom = v1.SqrMagnitude(); float sqrMagTo = v2.SqrMagnitude(); if (sqrMagFrom == 0 || sqrMagTo == 0) - return AngleOf::zero; + return AngleOf::zero; if (!isfinite(sqrMagFrom) || !isfinite(sqrMagTo)) - return AngleOf::zero; // Angle does not support NaN... + return AngleOf::zero; // Angle does not support NaN... - AngleOf angleFrom = AngleOf::Atan2(static_cast(v1.vertical), - static_cast(v1.horizontal)); - AngleOf angleTo = AngleOf::Atan2(static_cast(v2.vertical), - static_cast(v2.horizontal)); + AngleOf angleFrom = AngleOf::Atan2( + static_cast(v1.vertical), static_cast(v1.horizontal)); + AngleOf angleTo = AngleOf::Atan2( + static_cast(v2.vertical), static_cast(v2.horizontal)); return -(angleTo - angleFrom); } template -Vector2Of Vector2Of::Rotate(const Vector2Of& v, AngleOf a) { - float sinValue = AngleOf::Sin(a); - float cosValue = AngleOf::Cos(a); +Vector2Of Vector2Of::Rotate(const Vector2Of& v, AngleOf a) { + float sinValue = AngleOf::Sin(a); + float cosValue = AngleOf::Cos(a); float tx = static_cast(v.horizontal); float ty = static_cast(v.vertical); Vector2Of r = Vector2Of((cosValue * tx) - (sinValue * ty), - (sinValue * tx) + (cosValue * ty)); + (sinValue * tx) + (cosValue * ty)); return r; } template Vector2Of Vector2Of::Lerp(const Vector2Of& v1, - const Vector2Of& v2, - float f) { - Vector2Of v = v1 + static_cast>(v2 - v1) * f; - return v; + const Vector2Of& v2, + float f) { + Vector2Of v1f = (Vector2Of)v1; + Vector2Of delta = v2 - v1; + Vector2Of r = v1f + delta * f; + return r; } -// float Vector2::Angle(const Vector2& v1, const Vector2& v2) { -// return (float)fabs(SignedAngle(v1, v2)); -// } -// float Vector2::SignedAngle(const Vector2& v1, const Vector2& v2) { -// float sqrMagFrom = v1.sqrMagnitude(); -// float sqrMagTo = v2.sqrMagnitude(); - -// if (sqrMagFrom == 0 || sqrMagTo == 0) -// return 0; -// if (!isfinite(sqrMagFrom) || !isfinite(sqrMagTo)) -// #if defined(AVR) -// return NAN; -// #else -// return nanf(""); -// #endif - -// float angleFrom = atan2f(v1.y, v1.x); -// float angleTo = atan2f(v2.y, v2.x); -// return -(angleTo - angleFrom) * Rad2Deg; -// } - template Vector2Of Vector2Of::Normalized() const { float num = Vector2Of::MagnitudeOf(*this); @@ -379,6 +189,7 @@ Vector2Of Vector2Of::Normalized() const { // Explicit instantiation for int template class Vector2Of; +template class Vector2Of; template class Vector2Of; #pragma endregion Vector2Of \ No newline at end of file diff --git a/Vector2.h b/Vector2.h index 6267660..b6a3ab3 100644 --- a/Vector2.h +++ b/Vector2.h @@ -216,8 +216,6 @@ class Vector2Of { /// up = positive Vector2Of(T horizontal, T vertical); - static Vector2Of FromPolar(PolarOf v); - /// @brief Converting constructor: allow Vector2Of -> Vector2Of /// @tparam U /// @param other @@ -226,10 +224,13 @@ class Vector2Of { : horizontal(static_cast(other.horizontal)), vertical(static_cast(other.vertical)) {} + static Vector2Of FromPolar(PolarOf v); + template constexpr Vector2Of& operator=(const Vector2Of& other) noexcept { - this.horizontal = static_cast(other.horizontal); - this.vertical = static_cast(other.vertical); + this->horizontal = static_cast(other.horizontal); + this->vertical = static_cast(other.vertical); + return *this; } /// @brief A vector with zero for all axis @@ -266,6 +267,12 @@ class Vector2Of { /// of the squared root of C. float SqrMagnitude() const; + /// @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 Vector2Of& v1, const Vector2Of& v2); + /// @brief Negate the vector such that it points in the opposite direction /// @return The negated vector Vector2Of operator-(); @@ -315,12 +322,6 @@ class Vector2Of { /// @return The dot product of the two vectors static T Dot(const Vector2Of& v1, const Vector2Of& v2); - /// @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 Vector2Of& v1, const Vector2Of& v2); - static Vector2Of Normalize(const Vector2Of& v); /// @brief Convert the vector to a length 1 /// @return The vector normalized to a length of 1 @@ -333,18 +334,18 @@ class Vector2Of { /// @remark This reterns an unsigned angle which is the shortest distance /// between the two vectors. Use Vector2::SignedAngle if a signed angle is /// needed. - static AngleOf UnsignedAngle(const Vector2Of& v1, const Vector2Of& v2); + static AngleOf UnsignedAngle(const Vector2Of& v1, const Vector2Of& v2); /// @brief The signed angle between two vectors /// @param v1 The starting vector /// @param v2 The ending vector /// @return The signed angle between the two vectors - static AngleOf SignedAngle(const Vector2Of& v1, const Vector2Of& v2); + static AngleOf SignedAngle(const Vector2Of& v1, const Vector2Of& v2); /// @brief Rotate the vector /// @param v The vector to rotate /// @param a The angle in degrees to rotate /// @return The rotated vector - static Vector2Of Rotate(const Vector2Of& v, AngleOf a); + static Vector2Of Rotate(const Vector2Of& v, AngleOf a); /// @brief Lerp (linear interpolation) between two vectors /// @param v1 The starting vector @@ -354,7 +355,9 @@ class Vector2Of { /// @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 Vector2Of Lerp(const Vector2Of& v1, const Vector2Of& v2, float f); + static Vector2Of Lerp(const Vector2Of& v1, + const Vector2Of& v2, + float f); }; #pragma region friend functions diff --git a/Vector3.cpp b/Vector3.cpp index 35bde51..80eae7a 100644 --- a/Vector3.cpp +++ b/Vector3.cpp @@ -4,8 +4,9 @@ #include "Vector3.h" #include "Angle.h" +#include "FloatSingle.h" #include "Spherical.h" -//#include "TypeTraits.h" +// #include "TypeTraits.h" #include @@ -13,6 +14,7 @@ const float Deg2Rad = 0.0174532924F; const float Rad2Deg = 57.29578F; const float epsilon = 1E-05f; +/* Vector3::Vector3() { this->x = 0; this->y = 0; @@ -161,7 +163,8 @@ float Vector3::Distance(const Vector3& v1, const Vector3& v2) { } Vector3 Vector3::Cross(const Vector3& v1, const Vector3& v2) { - return Vector3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * v2.y - v1.y * v2.x); + return Vector3(v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, v1.x * +v2.y - v1.y * v2.x); } Vector3 Vector3::Project(const Vector3& v, const Vector3& n) { @@ -194,14 +197,16 @@ AngleOf Vector3::Angle(const Vector3& v1, const Vector3& v2) { float dot = Vector3::Dot(v1, v2); float fraction = dot / denominator; if (isnan(fraction)) - return AngleOf::Degrees(fraction); // short cut to returning NaN universally + return AngleOf::Degrees(fraction); // short cut to returning NaN +universally float cdot = clamp(fraction, -1.0, 1.0); float r = ((float)acos(cdot)); return AngleOf::Radians(r); } -AngleOf Vector3::SignedAngle(const Vector3& v1, const Vector3& v2, const Vector3& axis) { +AngleOf Vector3::SignedAngle(const Vector3& v1, const Vector3& v2, const +Vector3& axis) { // angle in [0,180] AngleOf angle = Vector3::Angle(v1, v2); @@ -219,6 +224,7 @@ Vector3 Vector3::Lerp(const Vector3& v1, const Vector3& v2, float f) { Vector3 v = v1 + (v2 - v1) * f; return v; } +*/ #pragma region Vector3Of @@ -232,44 +238,47 @@ Vector3Of::Vector3Of(T horizontal, T vertical, T depth) : horizontal(horizontal), vertical(vertical), depth(depth) {} template -Vector3Of::Vector3Of(Vector2Of v) : horizontal(v.horizontal), vertical(v.vertical) {} - -template -Vector3Of::Vector3Of(SphericalOf v) { - float cosVertical = AngleOf::Cos(v.direction.vertical); - float sinVertical = AngleOf::Sin(v.direction.vertical); - float cosHorizontal = AngleOf::Cos(v.direction.horizontal); - float sinHorizontal = AngleOf::Sin(v.direction.horizontal); - - horizontal = v.distance * sinVertical * sinHorizontal; - vertical = v.distance * cosVertical; - depth = v.distance * sinVertical * cosHorizontal; -} - -template -Vector3Of::Vector3Of(Vector3 v) : horizontal(v.x), vertical(v.y), depth(v.z) {} - -template -Vector3 Vector3Of::ToVector3() { - return Vector3(this->horizontal, this->vertical, this->depth); -} +Vector3Of::Vector3Of(Vector2Of v) + : horizontal(v.horizontal), vertical(v.vertical) {} template Vector3Of::~Vector3Of() {} +template <> +Vector3Of Vector3Of::FromSpherical(SphericalOf v) { + AngleOf vertical = AngleOf::Degrees(90) - v.direction.vertical; + AngleOf horizontal = v.direction.horizontal; + float cosVertical = AngleOf::Cos(vertical); + float sinVertical = AngleOf::Sin(vertical); + float cosHorizontal = AngleOf::Cos(horizontal); + float sinHorizontal = AngleOf::Sin(horizontal); + + Vector3Of r = Vector3Of(); + r.horizontal = v.distance * sinVertical * sinHorizontal; + r.vertical = v.distance * cosVertical; + r.depth = v.distance * sinVertical * cosHorizontal; + return r; +} + template const Vector3Of Vector3Of::zero = Vector3Of(T{}, T{}, T{}); template <> const Vector3Of Vector3Of::unit = Vector3Of(1, 1, 1); template <> -const Vector3Of Vector3Of::unit = Vector3Of(1.0f, 1.0f, 1.0f); +const Vector3Of Vector3Of::unit = + Vector3Of(1.0f, 1.0f, 1.0f); template <> -const Vector3Of Vector3Of::unit = Vector3Of(1.0f, 1.0f, 1.0f); +const Vector3Of Vector3Of::unit = + Vector3Of(1.0f, 1.0f, 1.0f); + +template +const Vector3Of Vector3Of::forward = Vector3Of(T{}, T{}, 1); // template // const Vector3Of Vector3Of::unit = -// Vector3Of(TypeTraits::unit(), TypeTraits::unit(), TypeTraits::unit()); +// Vector3Of(TypeTraits::unit(), TypeTraits::unit(), +// TypeTraits::unit()); // const Vector3Of Vector3Of::right = Vector3Of(1, 0, 0); // const Vector3Of Vector3Of::left = Vector3Of(-1, 0, 0); // const Vector3Of Vector3Of::up = Vector3Of(0, 1, 0); @@ -278,18 +287,26 @@ const Vector3Of Vector3Of::unit = Vector3Of(1.0f, 1.0f, // const Vector3Of Vector3Of::back = Vector3Of(0, 0, -1); template -T Vector3Of::MagnitudeOf(const Vector3Of& v) { - return sqrtf(v.horizontal * v.horizontal + v.vertical * v.vertical + v.depth * v.depth); +bool Vector3Of::operator==(const Vector3Of& v) const { + return (this->horizontal == v.horizontal && this->vertical == v.vertical && + this->depth == v.depth); +} + +template +float Vector3Of::MagnitudeOf(const Vector3Of& v) { + return sqrtf(v.horizontal * v.horizontal + v.vertical * v.vertical + + v.depth * v.depth); } template -T Vector3Of::Magnitude() const { - return (T)sqrtf(this->horizontal * this->horizontal + this->vertical * this->vertical + - this->depth * this->depth); +float Vector3Of::Magnitude() const { + return sqrtf(this->horizontal * this->horizontal + + this->vertical * this->vertical + this->depth * this->depth); } template float Vector3Of::SqrMagnitudeOf(const Vector3Of& v) { - return v.horizontal * v.horizontal + v.vertical * v.vertical + v.depth * v.depth; + return v.horizontal * v.horizontal + v.vertical * v.vertical + + v.depth * v.depth; } template float Vector3Of::SqrMagnitude() const { @@ -311,14 +328,18 @@ Vector3Of Vector3Of::Normalized() const { float num = this->Magnitude(); Vector3Of result = Vector3Of::zero; if (num > epsilon) { - result = ((Vector3Of) * this) / num; + result = ((Vector3Of)*this) / num; } return result; } template +Vector3Of Vector3Of::operator-() const { + return Vector3Of(-this->horizontal, -this->vertical, -this->depth); +} +template Vector3Of Vector3Of::operator-(const Vector3Of& v) const { - return Vector3(this->horizontal - v.horizontal, this->vertical - v.vertical, - this->depth - v.depth); + return Vector3Of(this->horizontal - v.horizontal, + this->vertical - v.vertical, this->depth - v.depth); } template @@ -331,8 +352,8 @@ Vector3Of Vector3Of::operator-=(const Vector3Of& v) { template Vector3Of Vector3Of::operator+(const Vector3Of& v) const { - return Vector3(this->horizontal + v.horizontal, this->vertical + v.vertical, - this->depth + v.depth); + return Vector3Of(this->horizontal + v.horizontal, + this->vertical + v.vertical, this->depth + v.depth); } template @@ -343,6 +364,12 @@ Vector3Of Vector3Of::operator+=(const Vector3Of& v) { return *this; } +template +Vector3Of Vector3Of::Scale(const Vector3Of& v1, const Vector3Of& v2) { + return Vector3Of(v1.horizontal * v2.horizontal, v1.vertical * v2.vertical, + v1.depth * v2.depth); +} + template Vector3Of Vector3Of::operator*=(float f) { this->horizontal *= f; @@ -360,12 +387,64 @@ Vector3Of Vector3Of::operator/=(float f) { } template -float Vector3Of::Dot(const Vector3Of& v1, const Vector3Of& v2) { - return v1.horizontal * v2.horizontal + v1.vertical * v2.vertical + v1.depth * v2.depth; +float Vector3Of::Distance(const Vector3Of& v1, const Vector3Of& v2) { + return MagnitudeOf(v1 - v2); } template -AngleOf Vector3Of::UnsignedAngle(const Vector3Of& v1, const Vector3Of& v2) { +T Vector3Of::Dot(const Vector3Of& v1, const Vector3Of& v2) { + return v1.horizontal * v2.horizontal + v1.vertical * v2.vertical + + v1.depth * v2.depth; +} + +template +Vector3Of Vector3Of::Cross(const Vector3Of& v1, const Vector3Of& v2) { + return Vector3Of( + v1.vertical * v2.depth - v1.depth * v2.vertical, + v1.depth * v2.horizontal - v1.horizontal * v2.depth, + v1.horizontal * v2.vertical - v1.vertical * v2.horizontal); +} + +template +Vector3Of Vector3Of::Project(const Vector3Of& v, const Vector3Of& n) { + T sqrMagnitude = Dot(n, n); + if (sqrMagnitude < epsilon) + return Vector3Of::zero; + else { + T dot = Dot(v, n); + Vector3Of r = n * dot; + r /= sqrMagnitude; + return r; + } +} + +template +Vector3Of Vector3Of::ProjectOnPlane(const Vector3Of& v, + const Vector3Of& n) { + Vector3Of r = (Vector3Of)v - Project(v, n); + return r; +} + +template +AngleOf Vector3Of::SignedAngle(const Vector3Of& v1, + const Vector3Of& v2, + const Vector3Of& axis) { + // angle in [0,180] + AngleOf angle = Vector3Of::UnsignedAngle(v1, v2); + + Vector3Of cross = Vector3Of::Cross(v1, v2); + float b = Vector3Of::Dot(axis, cross); + float signd = b < 0 ? -1.0F : (b > 0 ? 1.0F : 0.0F); + + // angle in [-179,180] + AngleOf signed_angle = angle * signd; + + return AngleOf(signed_angle); +} + +template +AngleOf Vector3Of::UnsignedAngle(const Vector3Of& v1, + const Vector3Of& v2) { float denominator = sqrtf(v1.SqrMagnitude() * v2.SqrMagnitude()); if (denominator < epsilon) return AngleOf(); @@ -373,14 +452,26 @@ AngleOf Vector3Of::UnsignedAngle(const Vector3Of& v1, const Vector3Of& float dot = Vector3Of::Dot(v1, v2); float fraction = dot / denominator; if (isnan(fraction)) - return AngleOf::Degrees(fraction); // short cut to returning NaN universally + return AngleOf::Degrees( + fraction); // short cut to returning NaN universally - float cdot = clamp(fraction, -1.0, 1.0); + float cdot = Float::Clamp(fraction, -1.0, 1.0); float r = ((float)acos(cdot)); return AngleOf::Radians(r); } +template +Vector3Of Vector3Of::Lerp(const Vector3Of& v1, + const Vector3Of& v2, + float f) { + Vector3Of v1f = v1; + Vector3Of delta = v2 - v1; + Vector3Of r = v1f + delta * f; + return r; +} + template class Vector3Of; +template class Vector3Of; } // namespace LinearAlgebra diff --git a/Vector3.h b/Vector3.h index 6621933..b32d7d8 100644 --- a/Vector3.h +++ b/Vector3.h @@ -7,7 +7,7 @@ #include "Vector2.h" - +/* extern "C" { /// /// 3-dimensional Vector representation (C-style) @@ -31,12 +31,14 @@ typedef struct Vec3 { } Vec3; } +*/ namespace LinearAlgebra { template class SphericalOf; +/* /// @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. @@ -147,8 +149,8 @@ struct Vector3 : Vec3 { /// @return The scaled vector /// @remark Each component of the vector will be multipled with the same /// factor f. - friend Vector3 operator*(const Vector3& v, float f) { return Vector3(v.x * f, v.y * f, v.z * f); } - friend Vector3 operator*(float f, const Vector3& v) { + friend Vector3 operator*(const Vector3& v, float f) { return Vector3(v.x * f, +v.y * f, v.z * f); } friend Vector3 operator*(float f, const Vector3& v) { // return Vector3(f * v.x, f * v.y, f * v.z); return Vector3(v.x * f, v.y * f, v.z * f); } @@ -157,8 +159,8 @@ struct Vector3 : Vec3 { /// @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, float f) { return Vector3(v.x / f, v.y / f, v.z / f); } - friend Vector3 operator/(float f, const Vector3& v) { + friend Vector3 operator/(const Vector3& v, float f) { return Vector3(v.x / f, +v.y / f, v.z / f); } friend Vector3 operator/(float f, const Vector3& v) { // return Vector3(f / v.x, f / v.y, f / v.z); return Vector3(v.x / f, v.y / f, v.z / f); } @@ -207,7 +209,8 @@ struct Vector3 : Vec3 { /// @param v2 The ending vector /// @param axis The axis to rotate around /// @return The signed angle between the two vectors - static AngleOf SignedAngle(const Vector3& v1, const Vector3& v2, const Vector3& axis); + static AngleOf SignedAngle(const Vector3& v1, const Vector3& v2, const +Vector3& axis); /// @brief Lerp (linear interpolation) between two vectors /// @param v1 The starting vector @@ -219,57 +222,86 @@ struct Vector3 : Vec3 { /// between *v1* and *v2* etc. static Vector3 Lerp(const Vector3& v1, const Vector3& v2, float f); }; +*/ /// @brief A 3-dimensional vector /// @remark This uses a right-handed carthesian coordinate system. /// @remark No default unit (for instance, meters) is specified /// @note This implementation intentionally avoids the use of x, y and z values. -/// @tparam T The type of the paramters used to measure distance. Typical values are float and int +/// @tparam T The type of the paramters used to measure distance. Typical values +/// are float and int template class Vector3Of { public: - /// @brief The distance in the horizontal direction, left = negative, right = positive + /// @brief The distance in the horizontal direction, left = negative, right = + /// positive T horizontal = T{}; - /// @brief The distance in the vertical direction, down = negative, up = positive + /// @brief The distance in the vertical direction, down = negative, up = + /// positive T vertical = T{}; - /// @brief The distance in the depth direction, backward = negative, forward = positive + /// @brief The distance in the depth direction, backward = negative, forward = + /// positive T depth = T{}; /// @brief A new 3-dimensional zero vector Vector3Of(); /// @brief A new 3-dimensional vector - /// @param horizontal The distance in the horizontal direction, left = negative, right = - /// positive - /// @param vertical The distance in the vertical direction, down = negative, up = - /// positive - /// @param depth The distance in the depth direction, backward = negative, forward = - /// positive + /// @param horizontal The distance in the horizontal direction, left = + /// negative, right = positive + /// @param vertical The distance in the vertical direction, down = negative, + /// up = positive + /// @param depth The distance in the depth direction, backward = negative, + /// forward = positive Vector3Of(T horizontal, T vertical, T depth); Vector3Of(Vector2Of v); - Vector3Of(SphericalOf v); - Vector3Of(Vector3 v); - - Vector3 ToVector3(); + // Vector3Of(SphericalOf v); /// @brief Vector3 destructor ~Vector3Of(); + /// @brief Converting constructor: allow Vector2Of -> Vector2Of + /// @tparam U + /// @param other + template + constexpr Vector3Of(const Vector3Of& other) noexcept + : horizontal(static_cast(other.horizontal)), + vertical(static_cast(other.vertical)), + depth(static_cast(other.depth)) {} + + static Vector3Of FromSpherical(SphericalOf v); + /// @brief A vector with zero for all axis const static Vector3Of zero; /// @brief A vector with unit for all axis const static Vector3Of unit; - // const Vector3Of Vector3Of::unit(1, 1, 1); // Hardcoded unit vector for int - // const Vector3Of Vector3Of::unit(1.0f, 1.0f, 1.0f); // Hardcoded unit vector for - // float + /// @brief A normalized forward-oriented vector + const static Vector3Of forward; + /// @brief A normalized back-oriented vector + const static Vector3Of back; + /// @brief A normalized right-oriented vector + const static Vector3Of right; + /// @brief A normalized left-oriented vector + const static Vector3Of left; + /// @brief A normalized up-oriented vector + const static Vector3Of up; + /// @brief A normalized down-oriented vector + const static Vector3Of down; + + /// @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 Vector3Of& v) const; /// @brief The vector length /// @param v The vector for which you need the length /// @return The vector length - static T MagnitudeOf(const Vector3Of& v); + static float MagnitudeOf(const Vector3Of& v); /// @brief The vector length /// @return The vector length - T Magnitude() const; + float Magnitude() const; /// @brief The squared vector length /// @param v The vector for which you need the length @@ -293,6 +325,10 @@ class Vector3Of { /// @return The vector normalized to a length of 1 Vector3Of Normalized() const; + /// @brief Negate te vector such that it points in the opposite direction + /// @return The negated vector + Vector3Of operator-() const; + /// @brief Subtract a vector from this vector /// @param v The vector to subtract from this vector /// @return The result of this subtraction @@ -305,6 +341,14 @@ class Vector3Of { Vector3Of operator+(const Vector3Of& v) const; Vector3Of operator+=(const Vector3Of& v); + /// @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 Vector3Of Scale(const Vector3Of& v1, const Vector3Of& v2); + /// @brief Scale the vector uniformly up /// @param f The scaling factor /// @return The scaled vector @@ -315,7 +359,7 @@ class Vector3Of { } friend Vector3Of operator*(float f, const Vector3Of& v) { return Vector3Of(f * v.horizontal, f * v.vertical, f * v.depth); -// return Vector3Of(v.horizontal * f, v.vertical * f, v.depth * f); + // return Vector3Of(v.horizontal * f, v.vertical * f, v.depth * f); } Vector3Of operator*=(float f); @@ -328,15 +372,39 @@ class Vector3Of { } friend Vector3Of operator/(float f, const Vector3Of& v) { return Vector3Of(f / v.horizontal, f / v.vertical, f / v.depth); -// return Vector3Of(v.horizontal / f, v.vertical / f, v.depth / f); + // return Vector3Of(v.horizontal / f, v.vertical / f, v.depth / f); } Vector3Of operator/=(float f); + /// @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 Vector3Of& v1, const Vector3Of& v2); + /// @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 Vector3Of& v1, const Vector3Of& v2); + static T Dot(const Vector3Of& v1, const Vector3Of& v2); + + /// @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 Vector3Of Cross(const Vector3Of& v1, const Vector3Of& v2); + + /// @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 Vector3Of Project(const Vector3Of& v, const Vector3Of& n); + /// @brief Project the vector on a plane defined by a normal orthogonal to the + /// plane. + /// @param v The vector to project + /// @param n The normal of the plane to project on + /// @return Teh projected vector + static Vector3Of ProjectOnPlane(const Vector3Of& v, const Vector3Of& n); /// @brief The angle between two vectors /// @param v1 The first vector @@ -346,6 +414,26 @@ class Vector3Of { /// between the two vectors. Use Vector3::SignedAngle if a signed angle is /// needed. static AngleOf UnsignedAngle(const Vector3Of& v1, const Vector3Of& 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 AngleOf SignedAngle(const Vector3Of& v1, + const Vector3Of& v2, + const Vector3Of& axis); + + /// @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 Vector3Of Lerp(const Vector3Of& v1, + const Vector3Of& v2, + float f); }; using Vector3Int = Vector3Of; diff --git a/test/Angle_test.cc b/test/Angle_test.cc index e1ac3a6..4062df9 100644 --- a/test/Angle_test.cc +++ b/test/Angle_test.cc @@ -10,7 +10,6 @@ using namespace LinearAlgebra; #define FLOAT_INFINITY std::numeric_limits::infinity() -//using AngleTypes = ::testing::Types, AngleOf, AngleOf>; using BaseTypes = ::testing::Types; template diff --git a/test/Polar_test.cc b/test/Polar_test.cc index 0bbd207..0905aef 100644 --- a/test/Polar_test.cc +++ b/test/Polar_test.cc @@ -1,128 +1,151 @@ #if GTEST #include -#include #include #include +#include #include "Polar.h" #include "Spherical.h" #define FLOAT_INFINITY std::numeric_limits::infinity() -using Vector2 = Vector2Of; +using BaseTypes = ::testing::Types; + +template +class PolarTests : public ::testing::Test {}; +TYPED_TEST_SUITE(PolarTests, BaseTypes); + +TYPED_TEST(PolarTests, FromVector2) { + using T = TypeParam; + using Vector2 = Vector2Of; + using Polar = PolarOf; -TEST(Polar, FromVector2) { Vector2 v = Vector2(0, 1); - PolarSingle p = PolarSingle::FromVector2(v); + Polar p = Polar::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 0 1"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "s.angle 0 0 1"; v = Vector2(1, 0); - p = PolarSingle::FromVector2(v); + p = Polar::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance 1 0"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 90.0F) << "s.angle 1 0"; v = Vector2(-1, 1); - p = PolarSingle::FromVector2(v); + p = Polar::FromVector2(v); EXPECT_FLOAT_EQ(p.distance, sqrt(2.0F)) << "p.distance -1 1"; EXPECT_NEAR(p.angle.InDegrees(), -45.0F, 1.0e-05) << "s.angle -1 1"; } -TEST(Polar, FromSpherical) { - SphericalSingle s; - PolarSingle p; +TYPED_TEST(PolarTests, FromSpherical) { + using T = TypeParam; + using Spherical = SphericalOf; + using Polar = PolarOf; + using Angle = AngleOf; - s = SphericalSingle(1, DirectionSingle::forward); - p = PolarSingle::FromSpherical(s); + Spherical s; + Polar p; + + s = Spherical(1, DirectionOf::forward); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(1 0 0)"; - s = SphericalSingle(1, AngleSingle::Degrees(45), AngleSingle::Degrees(0)); - p = PolarSingle::FromSpherical(s); + s = Spherical(1, AngleOf::Degrees(45), AngleOf::Degrees(0)); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 45 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 45.0F) << "p.angle FromSpherical(1 45 0)"; - s = SphericalSingle(1, AngleSingle::Degrees(-45), AngleSingle::Degrees(0)); - p = PolarSingle::FromSpherical(s); + s = Spherical(1, Angle::Degrees(-45), Angle::Degrees(0)); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(1 -45 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), -45.0F) << "p.angle FromSpherical(1 -45 0)"; - s = SphericalSingle(0, AngleSingle::Degrees(0), AngleSingle::Degrees(0)); - p = PolarSingle::FromSpherical(s); + s = Spherical(0, Angle::Degrees(0), Angle::Degrees(0)); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(0 0 0)"; - s = SphericalSingle(-1, AngleSingle::Degrees(0), AngleSingle::Degrees(0)); - p = PolarSingle::FromSpherical(s); + s = Spherical(-1, Angle::Degrees(0), Angle::Degrees(0)); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 1.0F) << "p.distance FromSpherical(-1 0 0)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), -180.0F) << "p.angle FromSpherical(-1 0 0)"; - s = SphericalSingle(0, AngleSingle::Degrees(0), AngleSingle::Degrees(90)); - p = PolarSingle::FromSpherical(s); + s = Spherical(0, Angle::Degrees(0), Angle::Degrees(90)); + p = Polar::FromSpherical(s); EXPECT_FLOAT_EQ(p.distance, 0.0F) << "p.distance FromSpherical(0 0 90)"; EXPECT_FLOAT_EQ(p.angle.InDegrees(), 0.0F) << "p.angle FromSpherical(0 0 90)"; } -TEST(Polar, Negation) { - PolarSingle v = PolarSingle(2, AngleSingle::Degrees(45)); - PolarSingle r = PolarSingle::zero; +TYPED_TEST(PolarTests, Negation) { + using T = TypeParam; + using Polar = PolarOf; + using Angle = AngleOf; + + Polar v = Polar(2, Angle::Degrees(45)); + Polar r = Polar::zero; r = -v; EXPECT_FLOAT_EQ(r.distance, 2); EXPECT_FLOAT_EQ(r.angle.InDegrees(), -135); - EXPECT_TRUE(r == PolarSingle(2, AngleSingle::Degrees(-135))) - << "Negate(2 45)"; + EXPECT_TRUE(r == Polar(2, Angle::Degrees(-135))) << "Negate(2 45)"; - v = PolarSingle::Deg(2, -45); + v = Polar::Deg(2, -45); r = -v; - EXPECT_TRUE(r == PolarSingle(2, AngleSingle::Degrees(135))) - << "Negate(2 -45)"; + EXPECT_TRUE(r == Polar(2, Angle::Degrees(135))) << "Negate(2 -45)"; - v = PolarSingle::Degrees(2, 0); + v = Polar::Degrees(2, 0); r = -v; - EXPECT_TRUE(r == PolarSingle(2, AngleSingle::Degrees(180))) << "Negate(2 0)"; + EXPECT_TRUE(r == Polar(2, Angle::Degrees(180))) << "Negate(2 0)"; - v = PolarSingle(0, AngleSingle::Degrees(0)); + v = Polar(0, Angle::Degrees(0)); r = -v; EXPECT_FLOAT_EQ(r.distance, 0.0f); EXPECT_FLOAT_EQ(r.angle.InDegrees(), 0.0f); - EXPECT_TRUE(r == PolarSingle(0, AngleSingle::Degrees(0))) << "Negate(0 0)"; + EXPECT_TRUE(r == Polar(0, Angle::Degrees(0))) << "Negate(0 0)"; } -TEST(Polar, Subtraction) { - PolarSingle v1 = PolarSingle(4, AngleSingle::Degrees(45)); - PolarSingle v2 = PolarSingle(1, AngleSingle::Degrees(-90)); - PolarSingle r = PolarSingle::zero; +TYPED_TEST(PolarTests, Subtraction) { + using T = TypeParam; + using Polar = PolarOf; + using Angle = AngleOf; + + Polar v1 = Polar(4, Angle::Degrees(45)); + Polar v2 = Polar(1, Angle::Degrees(-90)); + Polar r = Polar::zero; r = v1 - v2; // don't know what to expect yet - v2 = PolarSingle::zero; + v2 = Polar::zero; r = v1 - v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Subtraction(0 0)"; } -TEST(Polar, Addition) { - PolarSingle v1 = PolarSingle(1, AngleSingle::Degrees(45)); - PolarSingle v2 = PolarSingle(1, AngleSingle::Degrees(-90)); - PolarSingle r = PolarSingle::zero; +TYPED_TEST(PolarTests, Addition) { + using T = TypeParam; + using Polar = PolarOf; + using Angle = AngleOf; + + Polar v1 = Polar(1, Angle::Degrees(45)); + Polar v2 = Polar(1, Angle::Degrees(-90)); + Polar r = Polar::zero; r = v1 - v2; // don't know what to expect yet - v2 = PolarSingle::zero; + v2 = Polar::zero; r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)"; @@ -130,15 +153,19 @@ TEST(Polar, Addition) { r += v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0)"; - v2 = PolarSingle(1, AngleSingle::Degrees(-45)); + v2 = Polar(1, Angle::Degrees(-45)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(0 0 0)"; EXPECT_FLOAT_EQ(r.angle.InDegrees(), 0) << "Addition(0 0 0)"; } -TEST(Polar, Scale_Multiply) { - PolarSingle v1 = PolarSingle(4, AngleSingle::Degrees(45)); - PolarSingle r = PolarSingle::zero; +TYPED_TEST(PolarTests, Scale_Multiply) { + using T = TypeParam; + using Polar = PolarOf; + using Angle = AngleOf; + + Polar v1 = Polar(4, Angle::Degrees(45)); + Polar r = Polar::zero; r = v1 * 2.0f; EXPECT_FLOAT_EQ(r.distance, v1.distance * 2) << "ScaleMult(4 45, 2)"; @@ -146,9 +173,13 @@ TEST(Polar, Scale_Multiply) { << "ScaleMult(4 45, 2)"; } -TEST(Polar, Scale_Divide) { - PolarSingle v1 = PolarSingle(4, AngleSingle::Degrees(45)); - PolarSingle r = PolarSingle::zero; +TYPED_TEST(PolarTests, Scale_Divide) { + using T = TypeParam; + using Polar = PolarOf; + using Angle = AngleOf; + + Polar v1 = Polar(4, Angle::Degrees(45)); + Polar r = Polar::zero; r = v1 / 2.0f; EXPECT_FLOAT_EQ(r.distance, v1.distance / 2) << "ScaleDiv(4 45, 2)"; @@ -156,31 +187,39 @@ TEST(Polar, Scale_Divide) { << "ScaleDiv(4 45, 2)"; } -TEST(Polar, Distance) { - PolarSingle v1 = PolarSingle(4, AngleSingle::Degrees(45)); - PolarSingle v2 = PolarSingle(1, AngleSingle::Degrees(-90)); +TYPED_TEST(PolarTests, Distance) { + using T = TypeParam; + using Polar = PolarOf; + using Angle = AngleOf; + + Polar v1 = Polar(4, Angle::Degrees(45)); + Polar v2 = Polar(1, Angle::Degrees(-90)); float d = 0; - d = PolarSingle::Distance(v1, v2); + d = Polar::Distance(v1, v2); // don't know what to expect yet - v2 = PolarSingle::zero; - d = PolarSingle::Distance(v1, v2); + v2 = Polar::zero; + d = Polar::Distance(v1, v2); EXPECT_FLOAT_EQ(d, v1.distance) << "Distance(4 45, zero)"; } -TEST(Polar, Rotate) { - PolarSingle v = PolarSingle(4, AngleSingle::Degrees(45)); - PolarSingle r = PolarSingle::zero; +TYPED_TEST(PolarTests, Rotate) { + using T = TypeParam; + using Polar = PolarOf; + using Angle = AngleOf; - r = PolarSingle::Rotate(v, AngleSingle::Degrees(45)); + Polar v = Polar(4, Angle::Degrees(45)); + Polar r = Polar::zero; + + r = Polar::Rotate(v, Angle::Degrees(45)); EXPECT_FLOAT_EQ(r.distance, v.distance) << "Rotate(4 45, 45)"; EXPECT_FLOAT_EQ(r.angle.InDegrees(), 90.0f) << "Rotate(4 45, 45)"; } // Performance Test -TEST(PolarOfTest, PerformanceTest) { - const int numIterations = 1000000; // Number of instances to test +TYPED_TEST(PolarTests, PerformanceTest) { + const int numIterations = 1000000; // Number of instances to test std::vector> polarObjects; // Measure time for creating a large number of PolarOf objects @@ -188,11 +227,11 @@ TEST(PolarOfTest, PerformanceTest) { for (int i = 0; i < numIterations; ++i) { float distance = - static_cast(rand() % 100); // Random distance from 0 to 100 - AngleOf angle = AngleOf::Degrees( - static_cast(rand() % 360)); // Random angle from 0 to 360 degrees + static_cast(rand() % 100); // Random distance from 0 to 100 + AngleOf angle = AngleOf::Degrees(static_cast( + rand() % 360)); // Random angle from 0 to 360 degrees PolarOf p = PolarOf(distance, angle); - polarObjects.emplace_back(p); // Create and store the object + polarObjects.emplace_back(p); // Create and store the object } auto end = std::chrono::high_resolution_clock::now(); @@ -202,7 +241,7 @@ TEST(PolarOfTest, PerformanceTest) { << std::endl; // Test completion with a message - ASSERT_GE(duration.count(), 0); // Ensure duration is non-negative + ASSERT_GE(duration.count(), 0); // Ensure duration is non-negative // Assert that the duration is less than or equal to 1 second ASSERT_LE(duration.count(), 1.0) @@ -210,26 +249,27 @@ TEST(PolarOfTest, PerformanceTest) { } // Edge Case 1: Testing with distance = 0 and angle = 45 -TEST(PolarOfTest, TestDistanceZero) { +TYPED_TEST(PolarTests, TestDistanceZero) { PolarOf p1(0.0f, AngleOf::Degrees(45.0f)); - EXPECT_EQ(p1.distance, 0.0f); // Ensure distance is 0 - EXPECT_EQ(p1.angle.InDegrees(), 0.0f); // Ensure angle is 0 when distance is 0 + EXPECT_EQ(p1.distance, 0.0f); // Ensure distance is 0 + EXPECT_EQ(p1.angle.InDegrees(), + 0.0f); // Ensure angle is 0 when distance is 0 } // Edge Case 2: Testing with negative distance, angle should be adjusted -TEST(PolarOfTest, TestNegativeDistance) { +TYPED_TEST(PolarTests, TestNegativeDistance) { PolarOf p2(-10.0f, AngleOf::Degrees(90.0f)); - EXPECT_EQ(p2.distance, 10.0f); // Ensure distance is positive + EXPECT_EQ(p2.distance, 10.0f); // Ensure distance is positive EXPECT_NEAR(p2.angle.InDegrees(), -90.0f, - 0.0001f); // Ensure angle is normalized to 270 degrees (180 + 90) + 0.0001f); // Ensure angle is normalized to 270 degrees (180 + 90) } // Edge Case 3: Testing with positive distance and angle = 180 -TEST(PolarOfTest, TestPositiveDistance) { +TYPED_TEST(PolarTests, TestPositiveDistance) { PolarOf p3(100.0f, AngleOf::Degrees(180.0f)); - EXPECT_EQ(p3.distance, 100.0f); // Ensure distance is correct + EXPECT_EQ(p3.distance, 100.0f); // Ensure distance is correct EXPECT_NEAR(p3.angle.InDegrees(), -180.0f, - 0.0001f); // Ensure angle is correct + 0.0001f); // Ensure angle is correct } #endif \ No newline at end of file diff --git a/test/Quaternion_test.cc b/test/Quaternion_test.cc index e71bce4..e51bd0e 100644 --- a/test/Quaternion_test.cc +++ b/test/Quaternion_test.cc @@ -27,15 +27,15 @@ TEST(Quaternion, ToAngles) { bool r = false; Quaternion q1 = Quaternion(0, 0, 0, 1); - Vector3 v = Vector3::zero; + Vector3Of v = Vector3Of::zero; v = Quaternion::ToAngles(q1); - r = v == Vector3(0, 0, 0); + r = v == Vector3Of(0, 0, 0); EXPECT_TRUE(r) << "Quaternion::ToAngles 0 0 0 1"; q1 = Quaternion(1, 0, 0, 0); v = Quaternion::ToAngles(q1); - r = v == Vector3(180, 0, 0); + r = v == Vector3Of(180, 0, 0); // EXPECT_TRUE(r) << "Quaternion::ToAngles 1 0 0 0"; // fails on MacOS? } @@ -56,16 +56,16 @@ TEST(Quaternion, MultiplicationVector) { bool r = false; Quaternion q1 = Quaternion(0, 0, 0, 1); - Vector3 v1 = Vector3(0, 1, 0); - Vector3 v = Vector3::zero; + Vector3Of v1 = Vector3Of(0, 1, 0); + Vector3Of v = Vector3Of::zero; v = q1 * v1; - r = v == Vector3(0, 1, 0); + r = v == Vector3Of(0, 1, 0); EXPECT_TRUE(r) << "0 0 0 1 * Vector 0 1 0"; q1 = Quaternion(1, 0, 0, 0); v = q1 * v1; - r = v == Vector3(0, -1, 0); + r = v == Vector3Of(0, -1, 0); EXPECT_TRUE(r) << "1 0 0 0 * Vector 0 1 0"; } @@ -118,7 +118,7 @@ TEST(Quaternion, SlerpUnclamped) { TEST(Quaternion, Euler) { bool r = false; - Vector3 v1 = Vector3(0, 0, 0); + Vector3Of v1 = Vector3Of(0, 0, 0); Quaternion q = Quaternion::identity; q = Quaternion::Euler(v1); @@ -129,7 +129,7 @@ TEST(Quaternion, Euler) { r = q == Quaternion::identity; EXPECT_TRUE(r) << "Euler 0 0 0"; - v1 = Vector3(90, 90, -90); + v1 = Vector3Of(90, 90, -90); q = Quaternion::Euler(v1); r = q == Quaternion(0, 0.707106709F, -0.707106709F, 0); EXPECT_TRUE(r) << "Euler Vector 90 90 -90"; @@ -142,7 +142,7 @@ TEST(Quaternion, Euler) { TEST(Quaternion, GetAngleAround) { bool r = false; - Vector3 v1 = Vector3(0, 1, 0); + Vector3Of v1 = Vector3Of(0, 1, 0); Quaternion q1 = Quaternion(0, 0, 0, 1); float f; @@ -153,7 +153,7 @@ TEST(Quaternion, GetAngleAround) { f = Quaternion::GetAngleAround(v1, q1); EXPECT_FLOAT_EQ(f, 180) << "GetAngleAround 0 1 0 , 0 0.7 -0.7 0"; - v1 = Vector3(0, 0, 0); + v1 = Vector3Of(0, 0, 0); f = Quaternion::GetAngleAround(v1, q1); r = isnan(f); EXPECT_TRUE(r) << "GetAngleAround 0 0 0 , 0 0.7 -0.7 0"; @@ -162,7 +162,7 @@ TEST(Quaternion, GetAngleAround) { TEST(Quaternion, GetRotationAround) { bool r = false; - Vector3 v1 = Vector3(0, 1, 0); + Vector3Of v1 = Vector3Of(0, 1, 0); Quaternion q1 = Quaternion(0, 0, 0, 1); Quaternion q = Quaternion::identity; @@ -175,7 +175,7 @@ TEST(Quaternion, GetRotationAround) { r = q == Quaternion(0, 1, 0, 0); EXPECT_TRUE(r) << "GetRotationAround 0 1 0 , 0 0.7 -0.7 0"; - v1 = Vector3(0, 0, 0); + v1 = Vector3Of(0, 0, 0); q = Quaternion::GetRotationAround(v1, q1); r = isnan(q.x) && isnan(q.y) && isnan(q.z) && isnan(q.w); EXPECT_TRUE(r) << "GetRotationAround 0 0 0 , 0 0.7 -0.7 0"; diff --git a/test/SphericalSingle_test.cc b/test/SphericalSingle_test.cc deleted file mode 100644 index 3dedb31..0000000 --- a/test/SphericalSingle_test.cc +++ /dev/null @@ -1,214 +0,0 @@ -#if GTEST -#include -#include -#include -#include - -#include "Spherical.h" - -#define FLOAT_INFINITY std::numeric_limits::infinity() - -TEST(SphericalSingle, FromVector3) { - Vector3 v = Vector3(0, 0, 1); - SphericalSingle s = SphericalSingle ::FromVector3(v); - - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; - EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) << "s.hor 0 0 1"; - EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert 0 0 1"; - - v = Vector3(0, 1, 0); - s = SphericalSingle ::FromVector3(v); - - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; - EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) << "s.hor 0 1 0"; - EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 90.0F) << "s.vert 0 1 0"; - - v = Vector3(1, 0, 0); - s = SphericalSingle ::FromVector3(v); - - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; - EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 90.0F) << "s.hor 1 0 0"; - EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert 1 0 0"; -} - -TEST(SphericalSingle, FromPolar) { - PolarSingle p = PolarSingle(1, AngleSingle::Degrees(0)); - SphericalSingle s = SphericalSingle ::FromPolar(p); - - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; - EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) - << "s.hor Polar(1 0)"; - EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) - << "s.vert Polar(1 0)"; - - p = PolarSingle(1, AngleSingle::Degrees(45)); - s = SphericalSingle ::FromPolar(p); - - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; - EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 45.0F) - << "s.hor Polar(1 45)"; - EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) - << "s.vert Polar(1 45)"; - - p = PolarSingle(1, AngleSingle::Degrees(-45)); - s = SphericalSingle ::FromPolar(p); - - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), -45.0F) - << "s.hor Polar(1 -45)"; - EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) - << "s.vert Polar(1 -45)"; - - p = PolarSingle(0, AngleSingle::Degrees(0)); - s = SphericalSingle ::FromPolar(p); - - EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; - EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) - << "s.hor Polar(0 0)"; - EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) - << "s.vert Polar(0 0)"; - - p = PolarSingle(-1, AngleSingle::Degrees(0)); - s = SphericalSingle ::FromPolar(p); - - EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), -180.0F) - << "s.hor Polar(-1 0)"; - EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) - << "s.vert Polar(-1 0)"; -} - -TEST(SphericalSingle, Incident1) { - Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); - SphericalSingle s = SphericalSingle ::FromVector3(v); - - SphericalSingle sr = SphericalSingle(2.49F, AngleSingle::Degrees(98.18f), - AngleSingle::Degrees(24.4F)); - EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); - EXPECT_NEAR(s.direction.horizontal.InDegrees(), - sr.direction.horizontal.InDegrees(), 1.0e-02); - EXPECT_NEAR(s.direction.vertical.InDegrees(), - sr.direction.vertical.InDegrees(), 1.0e-02); - - Vector3 r = Vector3(sr); - 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(SphericalSingle, Incident2) { - Vector3 v = Vector3(1.0f, 0.0f, 1.0f); - SphericalSingle s = SphericalSingle ::FromVector3(v); - - SphericalSingle sr = SphericalSingle( - 1.4142135623F, AngleSingle::Degrees(45.0f), AngleSingle::Degrees(0.0F)); - EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.direction.horizontal.InDegrees(), - sr.direction.horizontal.InDegrees(), 1.0e-05); - EXPECT_NEAR(s.direction.vertical.InDegrees(), - sr.direction.vertical.InDegrees(), 1.0e-05); - - Vector3 r = Vector3(sr); - 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 = SphericalSingle ::FromVector3(v); - - sr = SphericalSingle(1.4142135623F, AngleSingle::Degrees(0.0f), - AngleSingle::Degrees(45.0F)); - EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.direction.horizontal.InDegrees(), - sr.direction.horizontal.InDegrees(), 1.0e-05); - EXPECT_NEAR(s.direction.vertical.InDegrees(), - sr.direction.vertical.InDegrees(), 1.0e-05); - - r = Vector3(sr); - 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 = SphericalSingle ::FromVector3(v); - r = Vector3(s); - - EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); - EXPECT_NEAR(s.direction.horizontal.InDegrees(), 45.0F, 1.0e-02); - EXPECT_NEAR(s.direction.vertical.InDegrees(), 35.26F, 1.0e-02); - - 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 = SphericalSingle(10, 45, 45); - // r = s.ToVector3(); - // EXPECT_NEAR(r.x, 5, 1.0e-06); - // EXPECT_NEAR(r.y, 7.07, 1.0e-06); - // EXPECT_NEAR(r.z, 5, 1.0e-06); -} - -TEST(SphericalSingle, Addition) { - SphericalSingle v1 = - SphericalSingle(1, AngleSingle::Degrees(45), AngleSingle::Degrees(0)); - SphericalSingle v2 = SphericalSingle ::zero; - SphericalSingle r = SphericalSingle ::zero; - - r = v1 + v2; - EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; - - r = v1; - r += v2; - EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; - - v2 = SphericalSingle(1, AngleSingle::Degrees(-45), AngleSingle::Degrees(0)); - r = v1 + v2; - EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 0) << "Addition(1 -45 0)"; - EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 0) << "Addition(1 -45 0)"; - - v2 = SphericalSingle(1, AngleSingle::Degrees(0), AngleSingle::Degrees(90)); - r = v1 + v2; - EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; - EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 45) << "Addition(1 0 90)"; -} - -TEST(SphericalSingle, AdditionPerformance) { - const int numIterations = 1000000; // Number of additions to test - std::vector sphericalObjects; - - // Populate the vector with random SphericalOf objects - for (int i = 0; i < numIterations; ++i) { - float distance = (float)(rand() % 100); - float horizontal = (float)(rand() % 180); - float vertical = (float)(rand() % 360); - SphericalSingle s = SphericalSingle::Deg(distance, horizontal, vertical); - sphericalObjects.push_back(s); - } - - // Measure the time to perform multiple additions - auto start = std::chrono::high_resolution_clock::now(); - - SphericalSingle result = SphericalSingle::zero; // Start with a - // zero-initialized object - - for (int i = 0; i < numIterations - 1; ++i) { - result = result + sphericalObjects[i]; // Add objects - // together - } - - auto end = std::chrono::high_resolution_clock::now(); - std::chrono::duration duration = end - start; - std::cout << "Time to perform " << numIterations - 1 - << " additions: " << duration.count() << " seconds." << std::endl; - - // Assert that the time taken is less than - // 1 second (or any other performance - // requirement) - ASSERT_LE(duration.count(), 1.0) << "Performance test failed: " - "Additions took longer than 1 " - "second."; -} - -#endif \ No newline at end of file diff --git a/test/Spherical16_test.cc b/test/Spherical_test.cc similarity index 55% rename from test/Spherical16_test.cc rename to test/Spherical_test.cc index 8eea700..5a3568f 100644 --- a/test/Spherical16_test.cc +++ b/test/Spherical_test.cc @@ -1,17 +1,26 @@ #if GTEST #include -#include #include #include +#include #include "Spherical.h" #include "Vector3.h" #define FLOAT_INFINITY std::numeric_limits::infinity() -TEST(Spherical16, FromVector3) { - Vector3 v = Vector3(0, 0, 1); - Spherical16 s = Spherical16::FromVector3(v); +using BaseTypes = ::testing::Types; + +template +class SphericalTests : public ::testing::Test {}; +TYPED_TEST_SUITE(SphericalTests, BaseTypes); + +TYPED_TEST(SphericalTests, FromVector3) { + using T = TypeParam; + using Spherical = SphericalOf; + + Vector3Of v = Vector3Of(0, 0, 1); + Spherical s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 0 1"; EXPECT_FLOAT_EQ((float)s.direction.horizontal.InDegrees(), 0.0F) @@ -19,149 +28,167 @@ TEST(Spherical16, FromVector3) { EXPECT_FLOAT_EQ((float)s.direction.vertical.InDegrees(), 0.0F) << "s.vert 0 0 1"; - v = Vector3(0, 1, 0); - s = Spherical16::FromVector3(v); + v = Vector3Of(0, 1, 0); + s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 0 1 0"; EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 0.0F) << "s.hor 0 1 0"; EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 90.0F) << "s.vert 0 1 0"; - v = Vector3(1, 0, 0); - s = Spherical16::FromVector3(v); + v = Vector3Of(1, 0, 0); + s = Spherical::FromVector3(v); EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance 1 0 0"; EXPECT_FLOAT_EQ(s.direction.horizontal.InDegrees(), 90.0F) << "s.hor 1 0 0"; EXPECT_FLOAT_EQ(s.direction.vertical.InDegrees(), 0.0F) << "s.vert 1 0 0"; } -TEST(Spherical16, Vector3) { - Vector3 v = Vector3(1, 2, 3); - Spherical16 rd = Spherical16::FromVector3(v); - Vector3 rv = rd.ToVector3(); - EXPECT_LT(Vector3::Distance(v, rv), 10e-4) << " 1 2 3 <-> spherical"; +TYPED_TEST(SphericalTests, Vector3) { + using T = TypeParam; + using Spherical = SphericalOf; - v = Vector3(1, 2, -3); - rd = Spherical16::FromVector3(v); + Vector3Of v = Vector3Of(1, 2, 3); + Spherical rd = Spherical::FromVector3(v); + Vector3Of rv = rd.ToVector3(); + EXPECT_LT(Vector3Of::Distance(v, rv), 10e-4) << " 1 2 3 <-> spherical"; + + v = Vector3Of(1, 2, -3); + rd = Spherical::FromVector3(v); rv = rd.ToVector3(); - EXPECT_LT(Vector3::Distance(v, rv), 10e-4) << " 1 2 3 <-> spherical"; + EXPECT_LT(Vector3Of::Distance(v, rv), 10e-4) << " 1 2 3 <-> spherical"; } -// TEST(Spherical16, FromPolar) { +// TYPED_TEST(SphericalTests, FromPolar) { +// using T = TypeParam; +// using Spherical = SphericalOf; + // Polar p = Polar(1, 0); -// Spherical16 s = Spherical16::FromPolar(p); +// Spherical s = Spherical::FromPolar(p); // EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 0)"; // EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor Polar(1 0)"; // EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 0)"; // p = Polar(1, 45); -// s = Spherical16::FromPolar(p); +// s = Spherical::FromPolar(p); // EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 45)"; // EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 45.0F) << "s.hor Polar(1 45)"; // EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 45)"; // p = Polar(1, -45); -// s = Spherical16::FromPolar(p); +// s = Spherical::FromPolar(p); // EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(1 -45)"; // EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), -45.0F) << "s.hor Polar(1 -45)"; // EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(1 -45)"; // p = Polar(0, 0); -// s = Spherical16::FromPolar(p); +// s = Spherical::FromPolar(p); // EXPECT_FLOAT_EQ(s.distance, 0.0F) << "s.distance Polar(0 0)"; // EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), 0.0F) << "s.hor Polar(0 0)"; // EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(0 0)"; // p = Polar(-1, 0); -// s = Spherical16::FromPolar(p); +// s = Spherical::FromPolar(p); // EXPECT_FLOAT_EQ(s.distance, 1.0F) << "s.distance Polar(-1 0)"; // EXPECT_FLOAT_EQ(s.horizontal.InDegrees(), -180.0F) << "s.hor Polar(-1 0)"; // EXPECT_FLOAT_EQ(s.vertical.InDegrees(), 0.0F) << "s.vert Polar(-1 0)"; // } -TEST(Spherical16, Incident1) { - Vector3 v = Vector3(2.242557f, 1.027884f, -0.322347f); - Spherical16 s = Spherical16::FromVector3(v); +TYPED_TEST(SphericalTests, Incident1) { + using T = TypeParam; + using Spherical = SphericalOf; + using Angle = AngleOf; - Spherical16 sr = - Spherical16(2.49F, Angle16::Degrees(98.18f), Angle16::Degrees(24.4F)); + Vector3Of v = Vector3Of(2.242557f, 1.027884f, -0.322347f); + Spherical s = Spherical::FromVector3(v); + + Spherical sr = + Spherical(2.49F, Angle::Degrees(98.18f), Angle::Degrees(24.4F)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-01); EXPECT_NEAR(s.direction.horizontal.InDegrees(), sr.direction.horizontal.InDegrees(), 1.0e-02); EXPECT_NEAR(s.direction.vertical.InDegrees(), sr.direction.vertical.InDegrees(), 1.0e-02); - Vector3 r = - Spherical16(sr.distance, sr.direction.horizontal, sr.direction.vertical) + Vector3Of r = + Spherical(sr.distance, sr.direction.horizontal, sr.direction.vertical) .ToVector3(); - 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"; + EXPECT_NEAR(r.horizontal, v.horizontal, 1.0e-02) << "toVector3.x 1 0 0"; + EXPECT_NEAR(r.vertical, v.vertical, 1.0e-02) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.depth, v.depth, 1.0e-02) << "toVector3.z 1 0 0"; } -TEST(Spherical16, Incident2) { - Vector3 v = Vector3(1.0f, 0.0f, 1.0f); - Spherical16 s = Spherical16::FromVector3(v); +TYPED_TEST(SphericalTests, Incident2) { + using T = TypeParam; + using Spherical = SphericalOf; + using Angle = AngleOf; - Spherical16 sr = Spherical16(1.4142135623F, Angle16::Degrees(45.0f), - Angle16::Degrees(0.0F)); + Vector3Of v = Vector3Of(1.0f, 0.0f, 1.0f); + Spherical s = Spherical::FromVector3(v); + + Spherical sr = + Spherical(1.4142135623F, Angle::Degrees(45.0f), Angle::Degrees(0.0F)); + EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); + EXPECT_NEAR(s.direction.horizontal.InDegrees(), + sr.direction.horizontal.InDegrees(), 1.0e-05); + EXPECT_NEAR(s.direction.vertical.InDegrees(), + sr.direction.vertical.InDegrees(), 1.0e-05); + + Vector3Of r = + Spherical(sr.distance, sr.direction.horizontal, sr.direction.vertical) + .ToVector3(); + EXPECT_NEAR(r.horizontal, v.horizontal, 1.0e-06); + EXPECT_NEAR(r.vertical, v.vertical, 1.0e-06); + EXPECT_NEAR(r.depth, v.depth, 1.0e-06); + + v = Vector3Of(0.0f, 1.0f, 1.0f); + s = Spherical::FromVector3(v); + + sr = Spherical(1.4142135623F, Angle::Degrees(0), Angle::Degrees(45)); EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); EXPECT_NEAR(s.direction.horizontal.InDegrees(), sr.direction.horizontal.InDegrees(), 1.0e-05); EXPECT_NEAR(s.direction.vertical.InDegrees(), sr.direction.vertical.InDegrees(), 1.0e-05); - Vector3 r = - Spherical16(sr.distance, sr.direction.horizontal, sr.direction.vertical) + r = Spherical(sr.distance, sr.direction.horizontal, sr.direction.vertical) .ToVector3(); - 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); + EXPECT_NEAR(r.horizontal, v.horizontal, 1.0e-06); + EXPECT_NEAR(r.vertical, v.vertical, 1.0e-06); + EXPECT_NEAR(r.depth, v.depth, 1.0e-06); - v = Vector3(0.0f, 1.0f, 1.0f); - s = Spherical16::FromVector3(v); - - sr = Spherical16(1.4142135623F, Angle16::Degrees(0), Angle16::Degrees(45)); - EXPECT_NEAR(s.distance, sr.distance, 1.0e-05); - EXPECT_NEAR(s.direction.horizontal.InDegrees(), - sr.direction.horizontal.InDegrees(), 1.0e-05); - EXPECT_NEAR(s.direction.vertical.InDegrees(), - sr.direction.vertical.InDegrees(), 1.0e-05); - - r = Spherical16(sr.distance, sr.direction.horizontal, sr.direction.vertical) - .ToVector3(); - 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 = Spherical16::FromVector3(v); - r = Spherical16(s.distance, s.direction.horizontal, s.direction.vertical) + v = Vector3Of(1.0f, 1.0f, 1.0f); + s = Spherical::FromVector3(v); + r = Spherical(s.distance, s.direction.horizontal, s.direction.vertical) .ToVector3(); EXPECT_NEAR(s.distance, 1.73205080F, 1.0e-02); EXPECT_NEAR(s.direction.horizontal.InDegrees(), 45.0F, 1.0e-02); EXPECT_NEAR(s.direction.vertical.InDegrees(), 35.26F, 1.0e-02); - EXPECT_NEAR(r.Right(), v.Right(), 1.0e-04); - EXPECT_NEAR(r.Up(), v.Up(), 1.0e-04); - EXPECT_NEAR(r.Forward(), v.Forward(), 1.0e-04); + EXPECT_NEAR(r.horizontal, v.horizontal, 1.0e-04); + EXPECT_NEAR(r.vertical, v.vertical, 1.0e-04); + EXPECT_NEAR(r.depth, v.depth, 1.0e-04); - // s = Spherical16(10, 45, 45); + // s = Spherical(10, 45, 45); // r = s.ToVector3(); // EXPECT_NEAR(r.x, 5, 1.0e-06); // EXPECT_NEAR(r.y, 7.07, 1.0e-06); // EXPECT_NEAR(r.z, 5, 1.0e-06); } -TEST(Spherical16, Addition) { - Spherical16 v1 = Spherical16(1, Angle16::Degrees(45), Angle16::Degrees(0)); - Spherical16 v2 = Spherical16::zero; - Spherical16 r = Spherical16::zero; +TYPED_TEST(SphericalTests, Addition) { + using T = TypeParam; + using Spherical = SphericalOf; + using Angle = AngleOf; + + Spherical v1 = Spherical(1, Angle::Degrees(45), Angle::Degrees(0)); + Spherical v2 = Spherical::zero; + Spherical r = Spherical::zero; r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; @@ -170,41 +197,44 @@ TEST(Spherical16, Addition) { r += v2; EXPECT_FLOAT_EQ(r.distance, v1.distance) << "Addition(0 0 0)"; - v2 = Spherical16(1, Angle16::Degrees(-45), Angle16::Degrees(0)); + v2 = Spherical(1, Angle::Degrees(-45), Angle::Degrees(0)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 -45 0)"; EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 0) << "Addition(1 -45 0)"; EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 0) << "Addition(1 -45 0)"; - v2 = Spherical16(1, Angle16::Degrees(0), Angle16::Degrees(90)); + v2 = Spherical(1, Angle::Degrees(0), Angle::Degrees(90)); r = v1 + v2; EXPECT_FLOAT_EQ(r.distance, sqrtf(2)) << "Addition(1 0 90)"; EXPECT_FLOAT_EQ(r.direction.horizontal.InDegrees(), 45) << "Addition(1 0 90)"; EXPECT_FLOAT_EQ(r.direction.vertical.InDegrees(), 45) << "Addition(1 0 90)"; } -TEST(Spherical16, AdditionPerformance) { - const int numIterations = 1000000; // Number of additions to test - std::vector sphericalObjects; +TYPED_TEST(SphericalTests, AdditionPerformance) { + using T = TypeParam; + using Spherical = SphericalOf; + + const int numIterations = 1000000; // Number of additions to test + std::vector sphericalObjects; // Populate the vector with random SphericalOf objects for (int i = 0; i < numIterations; ++i) { float distance = (float)(rand() % 100); float horizontal = (float)(rand() % 180); float vertical = (float)(rand() % 360); - Spherical16 s = Spherical16::Deg(distance, horizontal, vertical); + Spherical s = Spherical::Deg(distance, horizontal, vertical); sphericalObjects.push_back(s); } // Measure the time to perform multiple additions auto start = std::chrono::high_resolution_clock::now(); - Spherical16 result = Spherical16::zero; // Start with a - // zero-initialized object + Spherical result = Spherical::zero; // Start with a + // zero-initialized object for (int i = 0; i < numIterations - 1; ++i) { - result = result + sphericalObjects[i]; // Add objects - // together + result = result + sphericalObjects[i]; // Add objects + // together } auto end = std::chrono::high_resolution_clock::now(); diff --git a/test/SwingTwistSingle_test.cc b/test/SwingTwistSingle_test.cc index 8885ae4..fd62e15 100644 --- a/test/SwingTwistSingle_test.cc +++ b/test/SwingTwistSingle_test.cc @@ -7,125 +7,133 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() -TEST(SwingTwistSingle, Quaternion) { +using BaseTypes = ::testing::Types; + +template +class SwingTwistTests : public ::testing::Test {}; +TYPED_TEST_SUITE(SwingTwistTests, BaseTypes); + +TYPED_TEST(SwingTwistTests, Quaternion) { + using T = TypeParam; + using SwingTwist = SwingTwistOf; + Quaternion q; - SwingTwistSingle s; + SwingTwist s; Quaternion rq; q = Quaternion::identity; - s = SwingTwistSingle::FromQuaternion(q); + s = SwingTwist::FromQuaternion(q); rq = s.ToQuaternion(); EXPECT_EQ(q, rq) << " 0 0 0 1 <-> SwingTwist"; q = Quaternion::Euler(90, 0, 0); - s = SwingTwistSingle::FromQuaternion(q); + s = SwingTwist::FromQuaternion(q); rq = s.ToQuaternion(); EXPECT_LT(Quaternion::Angle(q, rq), 10e-2) << " Euler 90 0 0 <-> SwingTwist"; q = Quaternion::Euler(0, 90, 0); - s = SwingTwistSingle::FromQuaternion(q); + s = SwingTwist::FromQuaternion(q); rq = s.ToQuaternion(); EXPECT_LT(Quaternion::Angle(q, rq), 10e-2) << " Euler 0 90 0 <-> SwingTwist"; q = Quaternion::Euler(0, 0, 90); - s = SwingTwistSingle::FromQuaternion(q); + s = SwingTwist::FromQuaternion(q); rq = s.ToQuaternion(); EXPECT_EQ(q, rq) << " Euler 0 0 90 <-> SwingTwist"; q = Quaternion::Euler(0, 180, 0); // ==> spherical S(180 0)T0 - s = SwingTwistSingle::FromQuaternion(q); + s = SwingTwist::FromQuaternion(q); rq = s.ToQuaternion(); EXPECT_LT(Quaternion::Angle(q, rq), 10e-2) << " Euler 0 90 0 <-> SwingTwist"; q = Quaternion::Euler(0, 135, 0); // ==> spherical S(180 45)T0 - s = SwingTwistSingle::FromQuaternion(q); + s = SwingTwist::FromQuaternion(q); rq = s.ToQuaternion(); EXPECT_LT(Quaternion::Angle(q, rq), 10e-2) << " Euler 0 90 0 <-> SwingTwist"; } -TEST(SwingTwistSingle, AngleAxis) { - SwingTwistSingle s; - SwingTwistSingle r; +TYPED_TEST(SwingTwistTests, AngleAxis) { + using T = TypeParam; + using SwingTwist = SwingTwistOf; + using Direction = DirectionOf; + using Angle = AngleOf; - s = SwingTwistSingle::AngleAxis(0, DirectionSingle::up); - EXPECT_EQ(s, SwingTwistSingle::Degrees(0, 0, 0)) << "0 up"; + SwingTwist s; + SwingTwist r; - r = SwingTwistSingle::AngleAxis(90, DirectionSingle::up); - s = SwingTwistSingle::Degrees(90, 0, 0); - EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) - << "90 up"; + s = SwingTwist::AngleAxis(0, Direction::up); + EXPECT_EQ(s, SwingTwist::Degrees(0, 0, 0)) << "0 up"; - r = SwingTwistSingle::AngleAxis(180, DirectionSingle::up); - s = SwingTwistSingle::Degrees(180, 0, 0); - EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) - << "180 up"; + r = SwingTwist::AngleAxis(90, Direction::up); + s = SwingTwist::Degrees(90, 0, 0); + EXPECT_LT(SwingTwist::Angle(r, s), Angle::Degrees(10e-2f)) << "90 up"; - r = SwingTwistSingle::AngleAxis(270, DirectionSingle::up); - s = SwingTwistSingle::Degrees(-90, 0, 0); - EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) - << "270 up"; + r = SwingTwist::AngleAxis(180, Direction::up); + s = SwingTwist::Degrees(180, 0, 0); + EXPECT_LT(SwingTwist::Angle(r, s), Angle::Degrees(10e-2f)) << "180 up"; - r = SwingTwistSingle::AngleAxis(90, DirectionSingle::right); - s = SwingTwistSingle::Degrees(0, 90, 0); - EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + r = SwingTwist::AngleAxis(270, Direction::up); + s = SwingTwist::Degrees(-90, 0, 0); + EXPECT_LT(SwingTwist::Angle(r, s), Angle::Degrees(10e-2f)) << "270 up"; + + r = SwingTwist::AngleAxis(90, Direction::right); + s = SwingTwist::Degrees(0, 90, 0); + EXPECT_LT(SwingTwist::Angle(r, s), Angle::Degrees(10e-2f)) << "90 right"; - r = SwingTwistSingle::AngleAxis(180, DirectionSingle::right); - s = SwingTwistSingle::Degrees(0, 180, 0); - EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + r = SwingTwist::AngleAxis(180, Direction::right); + s = SwingTwist::Degrees(0, 180, 0); + EXPECT_LT(SwingTwist::Angle(r, s), Angle::Degrees(10e-2f)) << "180 right"; - r = SwingTwistSingle::AngleAxis(270, DirectionSingle::right); - s = SwingTwistSingle::Degrees(0, -90, 0); - EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) + r = SwingTwist::AngleAxis(270, Direction::right); + s = SwingTwist::Degrees(0, -90, 0); + EXPECT_LT(SwingTwist::Angle(r, s), Angle::Degrees(10e-2f)) << "270 right"; - r = SwingTwistSingle::AngleAxis(90, DirectionSingle::forward); - s = SwingTwistSingle::Degrees(0, 0, 90); - EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) - << "90 up"; + r = SwingTwist::AngleAxis(90, Direction::forward); + s = SwingTwist::Degrees(0, 0, 90); + EXPECT_LT(SwingTwist::Angle(r, s), Angle::Degrees(10e-2f)) << "90 up"; - r = SwingTwistSingle::AngleAxis(180, DirectionSingle::forward); - s = SwingTwistSingle::Degrees(0, 0, 180); - EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) - << "180 up"; + r = SwingTwist::AngleAxis(180, Direction::forward); + s = SwingTwist::Degrees(0, 0, 180); + EXPECT_LT(SwingTwist::Angle(r, s), Angle::Degrees(10e-2f)) << "180 up"; - r = SwingTwistSingle::AngleAxis(270, DirectionSingle::forward); - s = SwingTwistSingle::Degrees(0, 0, -90); - EXPECT_LT(SwingTwistSingle::Angle(r, s), AngleSingle::Degrees(10e-2f)) - << "270 up"; + r = SwingTwist::AngleAxis(270, Direction::forward); + s = SwingTwist::Degrees(0, 0, -90); + EXPECT_LT(SwingTwist::Angle(r, s), Angle::Degrees(10e-2f)) << "270 up"; - auto r16 = SwingTwist16::AngleAxis(13, Direction16::down); - auto s16 = SwingTwist16::Degrees(-13, 0, 0); - EXPECT_LT(SwingTwist16::Angle(r16, s16), Angle16::Degrees(10e-2f)) + auto r16 = SwingTwist::AngleAxis(13, Direction::down); + auto s16 = SwingTwist::Degrees(-13, 0, 0); + EXPECT_LT(SwingTwist::Angle(r16, s16), Angle::Degrees(10e-2f)) << "270 up"; } -TEST(SwingTwistSingle, Normalize) { - SwingTwistSingle s; +TYPED_TEST(SwingTwistTests, Normalize) { + using T = TypeParam; + using SwingTwist = SwingTwistOf; - s = SwingTwistSingle::Degrees(0, 0, 0); - EXPECT_EQ(s, SwingTwistSingle::Degrees(0, 0, 0)) << "0 0 0 Normalized"; + SwingTwist s; - s = SwingTwistSingle::Degrees(0, 180, 0); - EXPECT_EQ(s, SwingTwistSingle::Degrees(180, 0, 180)) << "0 180 0 Normalized"; + s = SwingTwist::Degrees(0, 0, 0); + EXPECT_EQ(s, SwingTwist::Degrees(0, 0, 0)) << "0 0 0 Normalized"; - s = SwingTwistSingle::Degrees(0, 180, 180); - EXPECT_EQ(s, SwingTwistSingle::Degrees(180, 0, 0)) << "0 180 180 Normalized"; + s = SwingTwist::Degrees(0, 180, 0); + EXPECT_EQ(s, SwingTwist::Degrees(180, 0, 180)) << "0 180 0 Normalized"; - s = SwingTwistSingle::Degrees(270, 90, 0); - EXPECT_EQ(s, SwingTwistSingle::Degrees(-90, 90, 0)) << "270 90 0 Normalized"; + s = SwingTwist::Degrees(0, 180, 180); + EXPECT_EQ(s, SwingTwist::Degrees(180, 0, 0)) << "0 180 180 Normalized"; - s = SwingTwistSingle::Degrees(270, 270, 0); - EXPECT_EQ(s, SwingTwistSingle::Degrees(-90, -90, 0)) - << "270 270 0 Normalized"; + s = SwingTwist::Degrees(270, 90, 0); + EXPECT_EQ(s, SwingTwist::Degrees(-90, 90, 0)) << "270 90 0 Normalized"; - s = SwingTwistSingle::Degrees(270, 225, 0); - EXPECT_EQ(s, SwingTwistSingle::Degrees(90, -45, -180)) - << "270 225 0 Normalized"; + s = SwingTwist::Degrees(270, 270, 0); + EXPECT_EQ(s, SwingTwist::Degrees(-90, -90, 0)) << "270 270 0 Normalized"; - s = SwingTwistSingle::Degrees(270, 0, 225); - EXPECT_EQ(s, SwingTwistSingle::Degrees(-90, 0, -135)) - << "270 0 225 Normalized"; + s = SwingTwist::Degrees(270, 225, 0); + EXPECT_EQ(s, SwingTwist::Degrees(90, -45, -180)) << "270 225 0 Normalized"; + + s = SwingTwist::Degrees(270, 0, 225); + EXPECT_EQ(s, SwingTwist::Degrees(-90, 0, -135)) << "270 0 225 Normalized"; } #endif \ No newline at end of file diff --git a/test/Vector2_test.cc b/test/Vector2_test.cc index 8b5b127..9651563 100644 --- a/test/Vector2_test.cc +++ b/test/Vector2_test.cc @@ -8,9 +8,21 @@ #define FLOAT_INFINITY std::numeric_limits::infinity() -using Vector2 = Vector2Of; +using BaseTypes = ::testing::Types; +using FpTypes = ::testing::Types; + +template +class Vector2Tests : public ::testing::Test {}; +TYPED_TEST_SUITE(Vector2Tests, BaseTypes); + +template +class Vector2FpTests : public ::testing::Test {}; +TYPED_TEST_SUITE(Vector2FpTests, FpTypes); + +TYPED_TEST(Vector2Tests, FromPolar) { + using T = TypeParam; + using Vector2 = Vector2Of; -TEST(Vector2, FromPolar) { Vector2 v; PolarSingle p; Vector2Float r; @@ -37,7 +49,10 @@ TEST(Vector2, FromPolar) { EXPECT_FLOAT_EQ(r.vertical, 0.0F) << "FromPolar(0 0)"; } -TEST(Vector2, Magnitude) { +TYPED_TEST(Vector2Tests, Magnitude) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v = Vector2(1, 2); float m = 0; @@ -54,6 +69,14 @@ TEST(Vector2, Magnitude) { v = Vector2(0, 0); m = v.Magnitude(); EXPECT_FLOAT_EQ(m, 0) << "v.magnitude 0 0 "; +} + +TYPED_TEST(Vector2FpTests, Magnitude) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v; + float m = 0; if (std::numeric_limits::is_iec559) { v = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); @@ -66,7 +89,10 @@ TEST(Vector2, Magnitude) { } } -TEST(Vector2, SqrMagnitude) { +TYPED_TEST(Vector2Tests, SqrMagnitude) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v = Vector2(1, 2); float m = 0; @@ -83,6 +109,14 @@ TEST(Vector2, SqrMagnitude) { v = Vector2(0, 0); m = v.SqrMagnitude(); EXPECT_FLOAT_EQ(m, 0) << "v.sqrMagnitude 0 0 "; +} + +TYPED_TEST(Vector2FpTests, SqrMagnitude) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v; + float m; if (std::numeric_limits::is_iec559) { v = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); @@ -95,7 +129,10 @@ TEST(Vector2, SqrMagnitude) { } } -TEST(Vector2, Normalize) { +TYPED_TEST(Vector2Tests, Normalize) { + using T = TypeParam; + using Vector2 = Vector2Of; + bool r = false; Vector2 v1 = Vector2(0, 2); @@ -114,6 +151,15 @@ TEST(Vector2, Normalize) { v1 = Vector2(0, 0); v = v1.Normalized(); EXPECT_TRUE(v == Vector2(0, 0)) << "v.normalized 0 0"; +} + +TYPED_TEST(Vector2FpTests, Normalize) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v; + Vector2 v1; + float r; if (std::numeric_limits::is_iec559) { v1 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); @@ -128,7 +174,10 @@ TEST(Vector2, Normalize) { } } -TEST(Vector2, Negate) { +TYPED_TEST(Vector2Tests, Negate) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v1 = Vector2(4, 5); Vector2 v = Vector2::zero; @@ -142,6 +191,14 @@ TEST(Vector2, Negate) { v1 = Vector2(0, 0); v = -v1; EXPECT_TRUE(v == Vector2(0, 0)) << "- 0 0"; +} + +TYPED_TEST(Vector2FpTests, Negate) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v; + Vector2 v1; if (std::numeric_limits::is_iec559) { v1 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); @@ -156,7 +213,10 @@ TEST(Vector2, Negate) { } } -TEST(Vector2, Subtract) { +TYPED_TEST(Vector2Tests, Subtract) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); Vector2 v = Vector2::zero; @@ -181,6 +241,15 @@ TEST(Vector2, Subtract) { v -= v2; EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 - 0 0"; +} + +TYPED_TEST(Vector2FpTests, Subtract) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v; + Vector2 v1 = Vector2(4, 5); + Vector2 v2; if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); @@ -195,7 +264,10 @@ TEST(Vector2, Subtract) { } } -TEST(Vector2, Addition) { +TYPED_TEST(Vector2Tests, Addition) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); Vector2 v = Vector2::zero; @@ -215,6 +287,15 @@ TEST(Vector2, Addition) { EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 + 0 0"; v += v2; EXPECT_TRUE(v == Vector2(4, 5)) << "4 5 + 0 0"; +} + +TYPED_TEST(Vector2FpTests, Addition) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v; + Vector2 v1 = Vector2(4, 5); + Vector2 v2 = Vector2(0, 0); if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); @@ -229,7 +310,10 @@ TEST(Vector2, Addition) { } } -TEST(Vector2, Scale) { +TYPED_TEST(Vector2Tests, Scale) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); Vector2 v = Vector2::zero; @@ -244,6 +328,15 @@ TEST(Vector2, Scale) { v2 = Vector2(0, 0); v = Vector2::Scale(v1, v2); EXPECT_TRUE(v == Vector2(0, 0)) << "Scale 4 5 , 0 0"; +} + +TYPED_TEST(Vector2FpTests, Scale) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v; + Vector2 v1 = Vector2(4, 5); + Vector2 v2; if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); @@ -258,9 +351,12 @@ TEST(Vector2, Scale) { } } -TEST(Vector2, Multiply) { +TYPED_TEST(Vector2Tests, Multiply) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v1 = Vector2(4, 5); - float f = 3; + T f = 3; Vector2 v = Vector2::zero; v = v1 * f; @@ -273,6 +369,15 @@ TEST(Vector2, Multiply) { f = 0; v = v1 * f; EXPECT_TRUE(v == Vector2(0, 0)) << "4 5 * 0"; +} + +TYPED_TEST(Vector2FpTests, Multiply) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v; + Vector2 v1 = Vector2(4, 5); + T f; if (std::numeric_limits::is_iec559) { f = FLOAT_INFINITY; @@ -287,9 +392,12 @@ TEST(Vector2, Multiply) { } } -TEST(Vector2, Divide) { +TYPED_TEST(Vector2Tests, Divide) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v1 = Vector2(4, 5); - float f = 2; + T f = 2; Vector2 v = Vector2::zero; v = v1 / f; @@ -298,6 +406,15 @@ TEST(Vector2, Divide) { f = -2; v = v1 / f; EXPECT_TRUE(v == Vector2(-2, -2.5F)) << "4 5 / -3"; +} + +TYPED_TEST(Vector2FpTests, Divide) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v; + Vector2 v1 = Vector2(4, 5); + T f; if (std::numeric_limits::is_iec559) { f = 0; @@ -314,7 +431,10 @@ TEST(Vector2, Divide) { } } -TEST(Vector2, Dot) { +TYPED_TEST(Vector2Tests, Dot) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); float f = 0; @@ -329,6 +449,15 @@ TEST(Vector2, Dot) { v2 = Vector2(0, 0); f = Vector2::Dot(v1, v2); EXPECT_FLOAT_EQ(f, 0) << "Dot(4 5, 0 0)"; +} + +TYPED_TEST(Vector2FpTests, Dot) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v2; + Vector2 v1 = Vector2(4, 5); + float f; if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); @@ -341,7 +470,10 @@ TEST(Vector2, Dot) { } } -TEST(Vector2, Equality) { +TYPED_TEST(Vector2Tests, Equality) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); bool r = false; @@ -352,6 +484,15 @@ TEST(Vector2, Equality) { v2 = Vector2(4, 5); r = v1 == v2; EXPECT_TRUE(r) << "4 5 == 1 2"; +} + +TYPED_TEST(Vector2FpTests, Equality) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v1 = Vector2(4, 5); + Vector2 v2; + bool r; if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); @@ -364,7 +505,10 @@ TEST(Vector2, Equality) { } } -TEST(Vector2, Distance) { +TYPED_TEST(Vector2Tests, Distance) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); float f = 0; @@ -379,6 +523,15 @@ TEST(Vector2, Distance) { v2 = Vector2(0, 0); f = Vector2::Distance(v1, v2); EXPECT_FLOAT_EQ(f, 6.403124F) << "Distance(4 5, 0 0)"; +} + +TYPED_TEST(Vector2FpTests, Distance) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v1 = Vector2(4, 5); + Vector2 v2; + float f; if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); @@ -391,10 +544,14 @@ TEST(Vector2, Distance) { } } -TEST(Vector2, Angle) { +TYPED_TEST(Vector2Tests, Angle) { + using T = TypeParam; + using Vector2 = Vector2Of; + using Angle = AngleOf; + Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); - AngleSingle f = AngleSingle::zero; + Angle f = Angle::zero; bool r = false; f = Vector2::UnsignedAngle(v1, v2); @@ -407,26 +564,40 @@ TEST(Vector2, Angle) { v2 = Vector2(0, 0); f = Vector2::UnsignedAngle(v1, v2); EXPECT_FLOAT_EQ(f.InDegrees(), 0) << "Angle(4 5, 0 0)"; +} + +TYPED_TEST(Vector2FpTests, Angle) { + using T = TypeParam; + using Vector2 = Vector2Of; + + Vector2 v1 = Vector2(4, 5); + Vector2 v2; + AngleOf f; + float r; if (std::numeric_limits::is_iec559) { v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); f = Vector2::UnsignedAngle(v1, v2); - //r = isnan(f.InDegrees()); + // r = isnan(f.InDegrees()); r = f.InDegrees() == 0; EXPECT_TRUE(r) << "Angle(4 5, INFINITY INFINITY)"; v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); f = Vector2::UnsignedAngle(v1, v2); - //r = isnan(f.InDegrees()); + // r = isnan(f.InDegrees()); r = f.InDegrees() == 0; EXPECT_TRUE(r) << "Angle(4 5, -INFINITY -INFINITY)"; } } -TEST(Vector2, SignedAngle) { +TYPED_TEST(Vector2Tests, SignedAngle) { + using T = TypeParam; + using Vector2 = Vector2Of; + using Angle = AngleOf; + Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); - AngleSingle f = AngleSingle::zero; + Angle f = Angle::zero; bool r = false; f = Vector2::SignedAngle(v1, v2); @@ -440,20 +611,6 @@ TEST(Vector2, SignedAngle) { f = Vector2::SignedAngle(v1, v2); EXPECT_FLOAT_EQ(f.InDegrees(), 0) << "SignedAngle(4 5, 0 0)"; - if (std::numeric_limits::is_iec559) { - v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); - f = Vector2::SignedAngle(v1, v2); - //r = isnan(f.InDegrees()); - r = f.InDegrees() == 0; - EXPECT_TRUE(r) << "SignedAngle(4 5, INFINITY INFINITY)"; - - v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); - f = Vector2::SignedAngle(v1, v2); - //r = isnan(f.InDegrees()); - r = f.InDegrees() == 0; - EXPECT_TRUE(r) << "SignedAngle(4 5, -INFINITY -INFINITY)"; - } - v1 = Vector2(0, 1); v2 = Vector2(1, 0); f = Vector2::SignedAngle(v1, v2); @@ -465,24 +622,55 @@ TEST(Vector2, SignedAngle) { EXPECT_FLOAT_EQ(f.InDegrees(), 180.0F) << "SignedAngle(0 1, 1 0)"; } -TEST(Vector2, Rotate) { - Vector2 v1 = Vector2(1, 2); - Vector2 r = Vector2(0, 0); +TYPED_TEST(Vector2FpTests, SignedAngle) { + using T = TypeParam; + using Vector2 = Vector2Of; - r = Vector2::Rotate(v1, AngleSingle::Degrees(0)); + Vector2 v1 = Vector2(4, 5); + Vector2 v2; + AngleOf f; + float r; + + if (std::numeric_limits::is_iec559) { + v2 = Vector2(FLOAT_INFINITY, FLOAT_INFINITY); + f = Vector2::SignedAngle(v1, v2); + // r = isnan(f.InDegrees()); + r = f.InDegrees() == 0; + EXPECT_TRUE(r) << "SignedAngle(4 5, INFINITY INFINITY)"; + + v2 = Vector2(-FLOAT_INFINITY, -FLOAT_INFINITY); + f = Vector2::SignedAngle(v1, v2); + // r = isnan(f.InDegrees()); + r = f.InDegrees() == 0; + EXPECT_TRUE(r) << "SignedAngle(4 5, -INFINITY -INFINITY)"; + } +} + +TYPED_TEST(Vector2Tests, Rotate) { + using T = TypeParam; + using Vector2 = Vector2Of; + using Angle = AngleOf; + + Vector2 v1 = Vector2(1, 2); + Vector2Of r = Vector2(0, 0); + + r = Vector2::Rotate(v1, Angle::Degrees(0)); EXPECT_FLOAT_EQ(Vector2::Distance(r, v1), 0); - r = Vector2::Rotate(v1, AngleSingle::Degrees(180)); - EXPECT_NEAR(Vector2::Distance(r, Vector2(-1, -2)), 0, 1.0e-06); + r = Vector2::Rotate(v1, Angle::Degrees(180)); + EXPECT_NEAR(Vector2Of::Distance(r, Vector2(-1, -2)), 0, 1.0e-06); - r = Vector2::Rotate(v1, AngleSingle::Degrees(-90)); + r = Vector2::Rotate(v1, Angle::Degrees(-90)); EXPECT_NEAR(Vector2::Distance(r, Vector2(2, -1)), 0, 1.0e-06); - r = Vector2::Rotate(v1, AngleSingle::Degrees(270)); + r = Vector2::Rotate(v1, Angle::Degrees(270)); EXPECT_NEAR(Vector2::Distance(r, Vector2(2, -1)), 0, 1.0e-06); } -TEST(Vector2, Lerp) { +TYPED_TEST(Vector2Tests, Lerp) { + using T = TypeParam; + using Vector2 = Vector2Of; + Vector2 v1 = Vector2(4, 5); Vector2 v2 = Vector2(1, 2); Vector2 r = Vector2(0, 0); diff --git a/test/Vector3_test.cc b/test/Vector3_test.cc index 82e57e9..45975c8 100644 --- a/test/Vector3_test.cc +++ b/test/Vector3_test.cc @@ -1,134 +1,186 @@ #if GTEST #include -#include #include +#include #include "Vector3.h" #define FLOAT_INFINITY std::numeric_limits::infinity() -TEST(Vector3, FromSpherical) { +using BaseTypes = ::testing::Types; +using FpTypes = ::testing::Types; + +template +class Vector3Tests : public ::testing::Test {}; +TYPED_TEST_SUITE(Vector3Tests, BaseTypes); + +template +class Vector3FpTests : public ::testing::Test {}; +TYPED_TEST_SUITE(Vector3FpTests, FpTypes); + +TYPED_TEST(Vector3FpTests, FromSpherical) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v = Vector3(0, 0, 1); SphericalOf s = SphericalOf::FromVector3(v); - Vector3 r = Vector3(s); + Vector3 r = Vector3::FromSpherical(s); - 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"; + EXPECT_FLOAT_EQ(r.horizontal, 0.0F) << "toVector3.x 0 0 1"; + EXPECT_NEAR(r.vertical, 0.0F, 1.0e-06) << "toVector3.y 0 0 1"; + EXPECT_FLOAT_EQ(r.depth, 1.0F) << "toVector3.z 0 0 1"; v = Vector3(0, 1, 0); s = SphericalOf::FromVector3(v); - r = Vector3(s); + r = Vector3::FromSpherical(s); - 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"; + EXPECT_FLOAT_EQ(r.horizontal, 0.0F) << "toVector3.x 0 1 0"; + EXPECT_FLOAT_EQ(r.vertical, 1.0F) << "toVector3.y 0 1 0"; + EXPECT_NEAR(r.depth, 0.0F, 1.0e-06) << "toVector3.z 0 1 0"; v = Vector3(1, 0, 0); s = SphericalOf::FromVector3(v); - r = Vector3(s); + r = Vector3::FromSpherical(s); - 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"; + EXPECT_FLOAT_EQ(r.horizontal, 1.0F) << "toVector3.x 1 0 0"; + EXPECT_NEAR(r.vertical, 0.0F, 1.0e-06) << "toVector3.y 1 0 0"; + EXPECT_NEAR(r.depth, 0.0F, 1.0e-06) << "toVector3.z 1 0 0"; } -TEST(Vector3, Magnitude) { +TYPED_TEST(Vector3Tests, Magnitude) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v = Vector3(1, 2, 3); float m = 0; - m = v.magnitude(); + m = v.Magnitude(); EXPECT_FLOAT_EQ(m, 3.741657F) << "v.magnitude 1 2 3"; - m = Vector3::Magnitude(v); + m = Vector3::MagnitudeOf(v); EXPECT_FLOAT_EQ(m, 3.741657F) << "Vector3::Magnitude 1 2 3"; v = Vector3(-1, -2, -3); - m = v.magnitude(); + m = v.Magnitude(); EXPECT_FLOAT_EQ(m, 3.741657F) << "v.magnitude -1 -2 -3"; v = Vector3(0, 0, 0); - m = v.magnitude(); + m = v.Magnitude(); EXPECT_FLOAT_EQ(m, 0) << "v.magnitude 0 0 0 "; +} + +TYPED_TEST(Vector3FpTests, Magnitude) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v; + float m; if (std::numeric_limits::is_iec559) { v = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); - m = v.magnitude(); + m = v.Magnitude(); EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.magnitude INFINITY INFINITY INFINITY "; v = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); - m = v.magnitude(); + m = v.Magnitude(); EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.magnitude -INFINITY -INFINITY -INFINITY "; } } -TEST(Vector3, SqrMagnitude) { +TYPED_TEST(Vector3Tests, SqrMagnitude) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v = Vector3(1, 2, 3); float m = 0; - m = v.sqrMagnitude(); + m = v.SqrMagnitude(); EXPECT_FLOAT_EQ(m, 14) << "v.sqrMagnitude 1 2 3"; - m = Vector3::SqrMagnitude(v); + m = Vector3::SqrMagnitudeOf(v); EXPECT_FLOAT_EQ(m, 14) << "Vector3::SqrMagnitude 1 2 3"; v = Vector3(-1, -2, -3); - m = v.sqrMagnitude(); + m = v.SqrMagnitude(); EXPECT_FLOAT_EQ(m, 14) << "v.sqrMagnitude -1 -2 -3"; v = Vector3(0, 0, 0); - m = v.sqrMagnitude(); + m = v.SqrMagnitude(); EXPECT_FLOAT_EQ(m, 0) << "v.sqrMagnitude 0 0 0 "; +} + +TYPED_TEST(Vector3FpTests, SqrMagnitude) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v; + float m; if (std::numeric_limits::is_iec559) { v = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); - m = v.sqrMagnitude(); + m = v.SqrMagnitude(); EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.sqrMagnitude INFINITY INFINITY INFINITY "; v = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); - m = v.sqrMagnitude(); + m = v.SqrMagnitude(); EXPECT_FLOAT_EQ(m, FLOAT_INFINITY) << "v.sqrMagnitude -INFINITY -INFINITY -INFINITY "; } } -TEST(Vector3, Normalize) { +TYPED_TEST(Vector3Tests, Normalize) { + using T = TypeParam; + using Vector3 = Vector3Of; + bool r = false; Vector3 v1 = Vector3(0, 2, 0); Vector3 v = Vector3::zero; - v = v1.normalized(); + v = v1.Normalized(); EXPECT_TRUE(v == Vector3(0, 1, 0)) << "v.normalized 0 2 0"; v = Vector3::Normalize(v1); EXPECT_TRUE(v == Vector3(0, 1, 0)) << "Vector3::Normalize 0 2 0"; v1 = Vector3(0, -2, 0); - v = v1.normalized(); + v = v1.Normalized(); EXPECT_TRUE(v == Vector3(0, -1, 0)) << "v.normalized 0 -2 0"; v1 = Vector3(0, 0, 0); - v = v1.normalized(); + v = v1.Normalized(); EXPECT_TRUE(v == Vector3(0, 0, 0)) << "v.normalized 0 0 0"; +} + +TYPED_TEST(Vector3FpTests, Normalize) { + using T = TypeParam; + using Vector3 = Vector3Of; + + bool r = false; + + Vector3 v1 = Vector3(0, 2, 0); + Vector3 v = Vector3::zero; if (std::numeric_limits::is_iec559) { v1 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); - v = v1.normalized(); - r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); + v = v1.Normalized(); + r = isnan(v.horizontal) && isnan(v.vertical) && isnan(v.depth); EXPECT_TRUE(r) << "v.normalized INFINITY INFINITY INFINITY"; v1 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); - v = v1.normalized(); - r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); + v = v1.Normalized(); + r = isnan(v.horizontal) && isnan(v.vertical) && isnan(v.depth); EXPECT_TRUE(r) << "v.normalized -INFINITY -INFINITY -INFINITY"; } } -TEST(Vector3, Negate) { +TYPED_TEST(Vector3Tests, Negate) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v = Vector3::zero; @@ -142,6 +194,14 @@ TEST(Vector3, Negate) { v1 = Vector3(0, 0, 0); v = -v1; EXPECT_TRUE(v == Vector3(0, 0, 0)) << "- 0 0 0"; +} + +TYPED_TEST(Vector3FpTests, Negate) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v = Vector3::zero; if (std::numeric_limits::is_iec559) { v1 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); @@ -156,7 +216,11 @@ TEST(Vector3, Negate) { } } -TEST(Vector3, Subtract) { +TYPED_TEST(Vector3Tests, Subtract) { + using T = TypeParam; + using Vector3 = Vector3Of; + ; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v = Vector3::zero; @@ -175,6 +239,15 @@ TEST(Vector3, Subtract) { v2 = Vector3(0, 0, 0); v = v1 - v2; EXPECT_TRUE(v == Vector3(4, 5, 6)) << "4 5 6 - 0 0 0"; +} + +TYPED_TEST(Vector3FpTests, Subtract) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + Vector3 v = Vector3::zero; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); @@ -189,7 +262,10 @@ TEST(Vector3, Subtract) { } } -TEST(Vector3, Addition) { +TYPED_TEST(Vector3Tests, Addition) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v = Vector3::zero; @@ -204,6 +280,15 @@ TEST(Vector3, Addition) { v2 = Vector3(0, 0, 0); v = v1 + v2; EXPECT_TRUE(v == Vector3(4, 5, 6)) << "4 5 6 + 0 0 0"; +} + +TYPED_TEST(Vector3FpTests, Addition) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + Vector3 v = Vector3::zero; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); @@ -218,7 +303,11 @@ TEST(Vector3, Addition) { } } -TEST(Vector3, Scale) { +TYPED_TEST(Vector3Tests, Scale) { + using T = TypeParam; + using Vector3 = Vector3Of; + ; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v = Vector3::zero; @@ -233,6 +322,15 @@ TEST(Vector3, Scale) { v2 = Vector3(0, 0, 0); v = Vector3::Scale(v1, v2); EXPECT_TRUE(v == Vector3(0, 0, 0)) << "Scale 4 5 6 , 0 0 0"; +} + +TYPED_TEST(Vector3FpTests, Scale) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + Vector3 v = Vector3::zero; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); @@ -247,7 +345,10 @@ TEST(Vector3, Scale) { } } -TEST(Vector3, Multiply) { +TYPED_TEST(Vector3Tests, Multiply) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); float f = 3; Vector3 v = Vector3::zero; @@ -262,6 +363,15 @@ TEST(Vector3, Multiply) { f = 0; v = v1 * f; EXPECT_TRUE(v == Vector3(0, 0, 0)) << "4 5 6 * 0"; +} + +TYPED_TEST(Vector3FpTests, Multiply) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + float f = 3; + Vector3 v = Vector3::zero; if (std::numeric_limits::is_iec559) { f = FLOAT_INFINITY; @@ -276,7 +386,10 @@ TEST(Vector3, Multiply) { } } -TEST(Vector3, Divide) { +TYPED_TEST(Vector3Tests, Divide) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); float f = 2; Vector3 v = Vector3::zero; @@ -287,6 +400,16 @@ TEST(Vector3, Divide) { f = -2; v = v1 / f; EXPECT_TRUE(v == Vector3(-2, -2.5F, -3)) << "4 5 6 / -3"; +} + +TYPED_TEST(Vector3FpTests, Divide) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + float f = 2; + Vector3 v = Vector3::zero; + if (std::numeric_limits::is_iec559) { f = 0; @@ -304,7 +427,10 @@ TEST(Vector3, Divide) { } } -TEST(Vector3, Dot) { +TYPED_TEST(Vector3Tests, Dot) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); float f = 0; @@ -319,6 +445,15 @@ TEST(Vector3, Dot) { v2 = Vector3(0, 0, 0); f = Vector3::Dot(v1, v2); EXPECT_FLOAT_EQ(f, 0) << "Dot(4 5 6, 0 0 0)"; +} + +TYPED_TEST(Vector3FpTests, Dot) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + float f = 0; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); @@ -333,7 +468,10 @@ TEST(Vector3, Dot) { } } -TEST(Vector3, Equality) { +TYPED_TEST(Vector3Tests, Equality) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); bool r = false; @@ -344,6 +482,15 @@ TEST(Vector3, Equality) { v2 = Vector3(4, 5, 6); r = v1 == v2; EXPECT_TRUE(r) << "4 5 6 == 1 2 3"; +} + +TYPED_TEST(Vector3FpTests, Equality) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + bool r = false; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); @@ -357,7 +504,10 @@ TEST(Vector3, Equality) { } } -TEST(Vector3, Distance) { +TYPED_TEST(Vector3Tests, Distance) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); float f = 0; @@ -372,6 +522,15 @@ TEST(Vector3, Distance) { v2 = Vector3(0, 0, 0); f = Vector3::Distance(v1, v2); EXPECT_FLOAT_EQ(f, 8.77496433F) << "Distance(4 5 6, 0 0 0)"; +} + +TYPED_TEST(Vector3FpTests, Distance) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + float f = 0; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); @@ -386,7 +545,10 @@ TEST(Vector3, Distance) { } } -TEST(Vector3, Cross) { +TYPED_TEST(Vector3Tests, Cross) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v = Vector3::zero; @@ -405,21 +567,34 @@ TEST(Vector3, Cross) { v = Vector3::Cross(v1, v2); r = v == Vector3(0, 0, 0); EXPECT_TRUE(r) << "Cross(4 5 6, 0 0 0)"; +} + +TYPED_TEST(Vector3FpTests, Cross) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + Vector3 v = Vector3::zero; + bool r = false; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v = Vector3::Cross(v1, v2); - r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); + r = isnan(v.horizontal) && isnan(v.vertical) && isnan(v.depth); 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.Right()) && isnan(v.Up()) && isnan(v.Forward()); + r = isnan(v.horizontal) && isnan(v.vertical) && isnan(v.depth); EXPECT_TRUE(r) << "Cross(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } -TEST(Vector3, Project) { +TYPED_TEST(Vector3Tests, Project) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v = Vector3::zero; @@ -438,84 +613,124 @@ TEST(Vector3, Project) { v = Vector3::Project(v1, v2); r = v == Vector3(0, 0, 0); EXPECT_TRUE(r) << "Project(4 5 6, 0 0 0)"; - - if (std::numeric_limits::is_iec559) { - v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); - v = Vector3::Project(v1, v2); - 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.Right()) && isnan(v.Up()) && isnan(v.Forward()); - EXPECT_TRUE(r) << "Project(4 5 6, -INFINITY -INFINITY -INFINITY)"; - } } -TEST(Vector3, ProjectOnPlane) { +TYPED_TEST(Vector3FpTests, Project) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v = Vector3::zero; bool r = false; + if (std::numeric_limits::is_iec559) { + v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); + v = Vector3::Project(v1, v2); + r = isnan(v.horizontal) && isnan(v.vertical) && isnan(v.depth); + 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.horizontal) && isnan(v.vertical) && isnan(v.depth); + EXPECT_TRUE(r) << "Project(4 5 6, -INFINITY -INFINITY -INFINITY)"; + } +} + +TYPED_TEST(Vector3Tests, ProjectOnPlane) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + Vector3Of v = Vector3Of::zero; + bool r = false; + v = Vector3::ProjectOnPlane(v1, v2); - r = v == Vector3(1.71428561F, 0.428571224F, -0.857142925F); + r = v == Vector3Of(1.71428561F, 0.428571224F, -0.857142925F); EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, 1 2 3)"; + //EXPECT_EQ(v, Vector3(1.71428561F, 0.428571224F, -0.857142925F)); v2 = Vector3(-1, -2, -3); v = Vector3::ProjectOnPlane(v1, v2); - r = v == Vector3(1.71428561F, 0.428571224F, -0.857142925F); + r = v == Vector3Of(1.71428561F, 0.428571224F, -0.857142925F); EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, -1 -2 -3)"; v2 = Vector3(0, 0, 0); v = Vector3::ProjectOnPlane(v1, v2); r = v == Vector3(4, 5, 6); EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, 0 0 0)"; +} + +TYPED_TEST(Vector3FpTests, ProjectOnPlane) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + Vector3 v = Vector3::zero; + bool r = false; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v = Vector3::ProjectOnPlane(v1, v2); - r = isnan(v.Right()) && isnan(v.Up()) && isnan(v.Forward()); + r = isnan(v.horizontal) && isnan(v.vertical) && isnan(v.depth); 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.Right()) && isnan(v.Up()) && isnan(v.Forward()); + r = isnan(v.horizontal) && isnan(v.vertical) && isnan(v.depth); EXPECT_TRUE(r) << "ProjectOnPlane(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } -TEST(Vector3, Angle) { +TYPED_TEST(Vector3Tests, Angle) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); AngleOf f = AngleOf::Degrees(0); bool r = false; - f = Vector3::Angle(v1, v2); + f = Vector3::UnsignedAngle(v1, v2); EXPECT_FLOAT_EQ(f.InDegrees(), 12.9331388F) << "Angle(4 5 6, 1 2 3)"; v2 = Vector3(-1, -2, -3); - f = Vector3::Angle(v1, v2); + f = Vector3::UnsignedAngle(v1, v2); EXPECT_FLOAT_EQ(f.InDegrees(), 167.066864F) << "Angle(4 5 6, -1 -2 -3)"; v2 = Vector3(0, 0, 0); - f = Vector3::Angle(v1, v2); + f = Vector3::UnsignedAngle(v1, v2); EXPECT_FLOAT_EQ(f.InDegrees(), 0) << "Angle(4 5 6, 0 0 0)"; +} + +TYPED_TEST(Vector3FpTests, Angle) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + AngleOf f = AngleOf::Degrees(0); + bool r = false; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); - f = Vector3::Angle(v1, v2); + f = Vector3::UnsignedAngle(v1, v2); r = isnan(f.InDegrees()); EXPECT_TRUE(r) << "Angle(4 5 6, INFINITY INFINITY INFINITY)"; v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); - f = Vector3::Angle(v1, v2); + f = Vector3::UnsignedAngle(v1, v2); r = isnan(f.InDegrees()); EXPECT_TRUE(r) << "Angle(4 5 6, -INFINITY -INFINITY -INFINITY)"; } } -TEST(Vector3, SignedAngle) { +TYPED_TEST(Vector3Tests, SignedAngle) { + using T = TypeParam; + using Vector3 = Vector3Of; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 v3 = Vector3(7, 8, -9); @@ -545,6 +760,17 @@ TEST(Vector3, SignedAngle) { v3 = Vector3(0, 0, 0); f = Vector3::SignedAngle(v1, v2, v3); EXPECT_FLOAT_EQ(f.InDegrees(), 0) << "SignedAngle(4 5 6, 1 2 3, 0 0 0)"; +} + +TYPED_TEST(Vector3FpTests, SignedAngle) { + using T = TypeParam; + using Vector3 = Vector3Of; + + Vector3 v1 = Vector3(4, 5, 6); + Vector3 v2 = Vector3(1, 2, 3); + Vector3 v3 = Vector3(7, 8, -9); + AngleOf f = AngleOf::Degrees(0); + bool r = false; if (std::numeric_limits::is_iec559) { v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); @@ -559,7 +785,11 @@ TEST(Vector3, SignedAngle) { } } -TEST(Vector3, Lerp) { +TYPED_TEST(Vector3Tests, Lerp) { + using T = TypeParam; + using Vector3 = Vector3Of; + ; + Vector3 v1 = Vector3(4, 5, 6); Vector3 v2 = Vector3(1, 2, 3); Vector3 r = Vector3(0, 0, 0);