Change Vector3::Angle return type to AngleOf<float>

This commit is contained in:
Pascal Serrarens 2024-08-05 12:16:27 +02:00
parent 18cf653aff
commit c72bba4f7a
4 changed files with 81 additions and 70 deletions

View File

@ -3,9 +3,10 @@
// file, You can obtain one at https ://mozilla.org/MPL/2.0/. // file, You can obtain one at https ://mozilla.org/MPL/2.0/.
#include "Quaternion.h" #include "Quaternion.h"
#include "Vector3.h"
#include <float.h> #include <float.h>
#include <math.h> #include <math.h>
#include "Angle.h"
#include "Vector3.h"
void CopyQuat(const Quat& q1, Quat& q2) { void CopyQuat(const Quat& q1, Quat& q2) {
q2.x = q1.x; q2.x = q1.x;
@ -42,7 +43,9 @@ Quaternion::~Quaternion() {}
const Quaternion Quaternion::identity = Quaternion(0, 0, 0, 1); const Quaternion Quaternion::identity = Quaternion(0, 0, 0, 1);
Vector3 Quaternion::xyz() const { return Vector3(x, y, z); } Vector3 Quaternion::xyz() const {
return Vector3(x, y, z);
}
float Quaternion::GetLength() const { float Quaternion::GetLength() const {
return sqrtf(x * x + y * y + z * z + w * w); return sqrtf(x * x + y * y + z * z + w * w);
@ -202,8 +205,8 @@ Quaternion Quaternion::FromToRotation(Vector3 fromDirection,
Vector3 toDirection) { Vector3 toDirection) {
Vector3 axis = Vector3::Cross(fromDirection, toDirection); Vector3 axis = Vector3::Cross(fromDirection, toDirection);
axis = Vector3::Normalize(axis); axis = Vector3::Normalize(axis);
float angle = Vector3::SignedAngle(fromDirection, toDirection, axis); AngleOf<float> angle = Vector3::SignedAngle(fromDirection, toDirection, axis);
Quaternion rotation = Quaternion::AngleAxis(angle, axis); Quaternion rotation = Quaternion::AngleAxis(angle.ToFloat(), axis);
return rotation; return rotation;
} }
@ -245,7 +248,8 @@ void Quaternion::ToAngleAxis(float *angle, Vector3 *axis) {
*angle *= Rad2Deg; *angle *= Rad2Deg;
} }
void Quaternion::ToAxisAngleRad(const Quaternion &q, Vector3 *const axis, void Quaternion::ToAxisAngleRad(const Quaternion& q,
Vector3* const axis,
float* angle) { float* angle) {
Quaternion q1 = (fabs(q.w) > 1.0f) ? Quaternion::Normalize(q) : q; Quaternion q1 = (fabs(q.w) > 1.0f) ? Quaternion::Normalize(q) : q;
*angle = 2.0f * acosf(q1.w); // angle *angle = 2.0f * acosf(q1.w); // angle
@ -258,7 +262,8 @@ void Quaternion::ToAxisAngleRad(const Quaternion &q, Vector3 *const axis,
*axis = Vector3(1, 0, 0); *axis = Vector3(1, 0, 0);
} }
} }
Quaternion Quaternion::SlerpUnclamped(const Quaternion &a, const Quaternion &b, Quaternion Quaternion::SlerpUnclamped(const Quaternion& a,
const Quaternion& b,
float t) { float t) {
// if either input is zero, return the other. // if either input is zero, return the other.
if (Quaternion::GetLengthSquared(a) == 0.0f) { if (Quaternion::GetLengthSquared(a) == 0.0f) {
@ -309,7 +314,8 @@ Quaternion Quaternion::SlerpUnclamped(const Quaternion &a, const Quaternion &b,
return Quaternion(); return Quaternion();
} }
Quaternion Quaternion::Slerp(const Quaternion &a, const Quaternion &b, Quaternion Quaternion::Slerp(const Quaternion& a,
const Quaternion& b,
float t) { float t) {
if (t > 1) if (t > 1)
t = 1; t = 1;
@ -403,8 +409,10 @@ Quaternion Quaternion::GetRotationAround(Vector3 axis, Quaternion rotation) {
return twist; return twist;
} }
void Quaternion::GetSwingTwist(Vector3 axis, Quaternion rotation, void Quaternion::GetSwingTwist(Vector3 axis,
Quaternion *swing, Quaternion *twist) { Quaternion rotation,
Quaternion* swing,
Quaternion* twist) {
*twist = GetRotationAround(axis, rotation); *twist = GetRotationAround(axis, rotation);
*swing = rotation * Quaternion::Inverse(*twist); *swing = rotation * Quaternion::Inverse(*twist);
} }

View File

@ -188,7 +188,7 @@ float clamp(float x, float lower, float upper) {
return upperClamp; return upperClamp;
} }
float Vector3::Angle(const Vector3& v1, const Vector3& v2) { AngleOf<float> Vector3::Angle(const Vector3& v1, const Vector3& v2) {
float denominator = sqrtf(v1.sqrMagnitude() * v2.sqrMagnitude()); float denominator = sqrtf(v1.sqrMagnitude() * v2.sqrMagnitude());
if (denominator < epsilon) if (denominator < epsilon)
return 0; return 0;
@ -200,23 +200,23 @@ float Vector3::Angle(const Vector3& v1, const Vector3& v2) {
float cdot = clamp(fraction, -1.0, 1.0); float cdot = clamp(fraction, -1.0, 1.0);
float r = ((float)acos(cdot)) * Rad2Deg; float r = ((float)acos(cdot)) * Rad2Deg;
return r; return AngleOf<float>(r);
} }
float Vector3::SignedAngle(const Vector3& v1, AngleOf<float> Vector3::SignedAngle(const Vector3& v1,
const Vector3& v2, const Vector3& v2,
const Vector3& axis) { const Vector3& axis) {
// angle in [0,180] // angle in [0,180]
float angle = Vector3::Angle(v1, v2); AngleOf<float> angle = Vector3::Angle(v1, v2);
Vector3 cross = Vector3::Cross(v1, v2); Vector3 cross = Vector3::Cross(v1, v2);
float b = Vector3::Dot(axis, cross); float b = Vector3::Dot(axis, cross);
float signd = b < 0 ? -1.0F : (b > 0 ? 1.0F : 0.0F); float signd = b < 0 ? -1.0F : (b > 0 ? 1.0F : 0.0F);
// angle in [-179,180] // angle in [-179,180]
float signed_angle = angle * signd; AngleOf<float> signed_angle = angle * signd;
return signed_angle; return AngleOf<float>(signed_angle);
} }
Vector3 Vector3::Lerp(const Vector3& v1, const Vector3& v2, float f) { Vector3 Vector3::Lerp(const Vector3& v1, const Vector3& v2, float f) {

View File

@ -204,13 +204,13 @@ struct Vector3 : Vec3 {
/// @remark This reterns an unsigned angle which is the shortest distance /// @remark This reterns an unsigned angle which is the shortest distance
/// between the two vectors. Use Vector3::SignedAngle if a signed angle is /// between the two vectors. Use Vector3::SignedAngle if a signed angle is
/// needed. /// needed.
static float Angle(const Vector3& v1, const Vector3& v2); static AngleOf<float> Angle(const Vector3& v1, const Vector3& v2);
/// @brief The signed angle between two vectors /// @brief The signed angle between two vectors
/// @param v1 The starting vector /// @param v1 The starting vector
/// @param v2 The ending vector /// @param v2 The ending vector
/// @param axis The axis to rotate around /// @param axis The axis to rotate around
/// @return The signed angle between the two vectors /// @return The signed angle between the two vectors
static float SignedAngle(const Vector3& v1, static AngleOf<float> SignedAngle(const Vector3& v1,
const Vector3& v2, const Vector3& v2,
const Vector3& axis); const Vector3& axis);

View File

@ -1,7 +1,7 @@
#if GTEST #if GTEST
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <limits>
#include <math.h> #include <math.h>
#include <limits>
#include "Vector3.h" #include "Vector3.h"
@ -488,29 +488,29 @@ TEST(Vector3, ProjectOnPlane) {
TEST(Vector3, Angle) { TEST(Vector3, Angle) {
Vector3 v1 = Vector3(4, 5, 6); Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3); Vector3 v2 = Vector3(1, 2, 3);
float f = 0; AngleOf<float> f = 0;
bool r = false; bool r = false;
f = Vector3::Angle(v1, v2); f = Vector3::Angle(v1, v2);
EXPECT_FLOAT_EQ(f, 12.9331388F) << "Angle(4 5 6, 1 2 3)"; EXPECT_FLOAT_EQ(f.ToFloat(), 12.9331388F) << "Angle(4 5 6, 1 2 3)";
v2 = Vector3(-1, -2, -3); v2 = Vector3(-1, -2, -3);
f = Vector3::Angle(v1, v2); f = Vector3::Angle(v1, v2);
EXPECT_FLOAT_EQ(f, 167.066864F) << "Angle(4 5 6, -1 -2 -3)"; EXPECT_FLOAT_EQ(f.ToFloat(), 167.066864F) << "Angle(4 5 6, -1 -2 -3)";
v2 = Vector3(0, 0, 0); v2 = Vector3(0, 0, 0);
f = Vector3::Angle(v1, v2); f = Vector3::Angle(v1, v2);
EXPECT_FLOAT_EQ(f, 0) << "Angle(4 5 6, 0 0 0)"; EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "Angle(4 5 6, 0 0 0)";
if (std::numeric_limits<float>::is_iec559) { if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
f = Vector3::Angle(v1, v2); f = Vector3::Angle(v1, v2);
r = isnan(f); r = isnan(f.ToFloat());
EXPECT_TRUE(r) << "Angle(4 5 6, INFINITY INFINITY INFINITY)"; EXPECT_TRUE(r) << "Angle(4 5 6, INFINITY INFINITY INFINITY)";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
f = Vector3::Angle(v1, v2); f = Vector3::Angle(v1, v2);
r = isnan(f); r = isnan(f.ToFloat());
EXPECT_TRUE(r) << "Angle(4 5 6, -INFINITY -INFINITY -INFINITY)"; EXPECT_TRUE(r) << "Angle(4 5 6, -INFINITY -INFINITY -INFINITY)";
} }
} }
@ -519,39 +519,42 @@ TEST(Vector3, SignedAngle) {
Vector3 v1 = Vector3(4, 5, 6); Vector3 v1 = Vector3(4, 5, 6);
Vector3 v2 = Vector3(1, 2, 3); Vector3 v2 = Vector3(1, 2, 3);
Vector3 v3 = Vector3(7, 8, -9); Vector3 v3 = Vector3(7, 8, -9);
float f = 0; AngleOf<float> f = 0;
bool r = false; bool r = false;
f = Vector3::SignedAngle(v1, v2, v3); f = Vector3::SignedAngle(v1, v2, v3);
EXPECT_FLOAT_EQ(f, -12.9331388F) << "SignedAngle(4 5 6, 1 2 3, 7 8 -9)"; EXPECT_FLOAT_EQ(f.ToFloat(), -12.9331388F)
<< "SignedAngle(4 5 6, 1 2 3, 7 8 -9)";
v2 = Vector3(-1, -2, -3); v2 = Vector3(-1, -2, -3);
f = Vector3::SignedAngle(v1, v2, v3); f = Vector3::SignedAngle(v1, v2, v3);
EXPECT_FLOAT_EQ(f, 167.066864F) << "SignedAngle(4 5 6, -1 -2 -3, 7 8 -9)"; EXPECT_FLOAT_EQ(f.ToFloat(), 167.066864F)
<< "SignedAngle(4 5 6, -1 -2 -3, 7 8 -9)";
v2 = Vector3(0, 0, 0); v2 = Vector3(0, 0, 0);
f = Vector3::SignedAngle(v1, v2, v3); f = Vector3::SignedAngle(v1, v2, v3);
EXPECT_FLOAT_EQ(f, 0) << "SignedAngle(4 5 6, 0 0 0, 7 8 -9 )"; EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "SignedAngle(4 5 6, 0 0 0, 7 8 -9 )";
v2 = Vector3(1, 2, 3); v2 = Vector3(1, 2, 3);
v3 = Vector3(-7, -8, 9); v3 = Vector3(-7, -8, 9);
f = Vector3::SignedAngle(v1, v2, v3); f = Vector3::SignedAngle(v1, v2, v3);
EXPECT_FLOAT_EQ(f, 12.9331388F) << "SignedAngle(4 5 6, 1 2 3, -7 -8 9)"; EXPECT_FLOAT_EQ(f.ToFloat(), 12.9331388F)
<< "SignedAngle(4 5 6, 1 2 3, -7 -8 9)";
v3 = Vector3(0, 0, 0); v3 = Vector3(0, 0, 0);
f = Vector3::SignedAngle(v1, v2, v3); f = Vector3::SignedAngle(v1, v2, v3);
EXPECT_FLOAT_EQ(f, 0) << "SignedAngle(4 5 6, 1 2 3, 0 0 0)"; EXPECT_FLOAT_EQ(f.ToFloat(), 0) << "SignedAngle(4 5 6, 1 2 3, 0 0 0)";
if (std::numeric_limits<float>::is_iec559) { if (std::numeric_limits<float>::is_iec559) {
v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY); v2 = Vector3(FLOAT_INFINITY, FLOAT_INFINITY, FLOAT_INFINITY);
f = Vector3::SignedAngle(v1, v2, v3); f = Vector3::SignedAngle(v1, v2, v3);
r = isnan(f); r = isnan(f.ToFloat());
EXPECT_TRUE(r) << "SignedAngle(4 5 6, INFINITY INFINITY INFINITY)"; EXPECT_TRUE(r) << "SignedAngle(4 5 6, INFINITY INFINITY INFINITY)";
v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY); v2 = Vector3(-FLOAT_INFINITY, -FLOAT_INFINITY, -FLOAT_INFINITY);
f = Vector3::SignedAngle(v1, v2, v3); f = Vector3::SignedAngle(v1, v2, v3);
r = isnan(f); r = isnan(f.ToFloat());
EXPECT_TRUE(r) << "SignedAngle(4 5 6, -INFINITY -INFINITY -INFINITY)"; EXPECT_TRUE(r) << "SignedAngle(4 5 6, -INFINITY -INFINITY -INFINITY)";
} }
} }