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

View File

@ -188,7 +188,7 @@ float clamp(float x, float lower, float upper) {
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());
if (denominator < epsilon)
return 0;
@ -200,23 +200,23 @@ float Vector3::Angle(const Vector3& v1, const Vector3& v2) {
float cdot = clamp(fraction, -1.0, 1.0);
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& axis) {
// angle in [0,180]
float angle = Vector3::Angle(v1, v2);
AngleOf<float> angle = Vector3::Angle(v1, v2);
Vector3 cross = Vector3::Cross(v1, v2);
float b = Vector3::Dot(axis, cross);
float signd = b < 0 ? -1.0F : (b > 0 ? 1.0F : 0.0F);
// 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) {

View File

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

View File

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