diff --git a/Source/Engine/Core/Math/Vector3.cpp b/Source/Engine/Core/Math/Vector3.cpp
index 5a26f2309..d11df8f6d 100644
--- a/Source/Engine/Core/Math/Vector3.cpp
+++ b/Source/Engine/Core/Math/Vector3.cpp
@@ -320,8 +320,17 @@ float Float3::Angle(const Float3& from, const Float3& to)
{
const float dot = Math::Clamp(Dot(Normalize(from), Normalize(to)), -1.0f, 1.0f);
if (Math::Abs(dot) > 1.0f - ZeroTolerance)
- return dot > 0.0f ? 0.0f : PI;
- return Math::Acos(dot);
+ return dot > 0.0f ? 0.0f : 180.0f;
+ return Math::Acos(dot) * RadiansToDegrees;
+}
+
+template<>
+float Float3::SignedAngle(const Float3& from, const Float3& to, const Float3& axis)
+{
+ const float angle = Angle(from, to);
+ const Float3 cross = Cross(from, to);
+ const float sign = Math::Sign(axis.X * cross.X + axis.Y * cross.Y + axis.Z * cross.Z);
+ return angle * sign;
}
template<>
@@ -648,8 +657,17 @@ double Double3::Angle(const Double3& from, const Double3& to)
{
const double dot = Math::Clamp(Dot(Normalize(from), Normalize(to)), -1.0, 1.0);
if (Math::Abs(dot) > 1.0 - ZeroTolerance)
- return dot > 0.0 ? 0.0 : PI;
- return Math::Acos(dot);
+ return dot > 0.0 ? 0.0 : 180.0;
+ return Math::Acos(dot) * RadiansToDegrees;
+}
+
+template<>
+double Double3::SignedAngle(const Double3& from, const Double3& to, const Double3& axis)
+{
+ const double angle = Angle(from, to);
+ const Double3 cross = Cross(from, to);
+ const double sign = Math::Sign(axis.X * cross.X + axis.Y * cross.Y + axis.Z * cross.Z);
+ return angle * sign;
}
template<>
@@ -881,6 +899,12 @@ int32 Int3::Angle(const Int3& from, const Int3& to)
return 0;
}
+template<>
+int32 Int3::SignedAngle(const Int3& from, const Int3& to, const Int3& axis)
+{
+ return 0;
+}
+
template<>
Int3 Int3::SnapToGrid(const Int3& pos, const Int3& gridSize)
{
diff --git a/Source/Engine/Core/Math/Vector3.cs b/Source/Engine/Core/Math/Vector3.cs
index 61d0e51f0..360057f5d 100644
--- a/Source/Engine/Core/Math/Vector3.cs
+++ b/Source/Engine/Core/Math/Vector3.cs
@@ -1345,7 +1345,7 @@ namespace FlaxEngine
}
///
- /// Calculates the angle (in degrees) between and . This is always the smallest value.
+ /// Calculates the angle (in degrees) between and vectors. This is always the smallest value.
///
/// The first vector.
/// The second vector.
@@ -1358,6 +1358,21 @@ namespace FlaxEngine
return (Real)Math.Acos(dot) * Mathr.RadiansToDegrees;
}
+ ///
+ /// Calculates the signed angle (in degrees) between and vectors. This is always the smallest value. The sign of the result depends on: the order of input vectors, and the direction of the vector.
+ ///
+ /// The first vector.
+ /// The second vector.
+ /// The axis around which the vectors are rotated.
+ /// The angle (in degrees).
+ public static Real SignedAngle(Vector3 from, Vector3 to, Vector3 axis)
+ {
+ Real angle = Angle(from, to);
+ Vector3 cross = Cross(from, to);
+ Real sign = Mathr.Sign(axis.X * cross.X + axis.Y * cross.Y + axis.Z * cross.Z);
+ return angle * sign;
+ }
+
///
/// Projects a 3D vector from object space into screen space.
///
diff --git a/Source/Engine/Core/Math/Vector3.h b/Source/Engine/Core/Math/Vector3.h
index 67f8e7d44..10271dece 100644
--- a/Source/Engine/Core/Math/Vector3.h
+++ b/Source/Engine/Core/Math/Vector3.h
@@ -812,13 +812,22 @@ public:
static FLAXENGINE_API T TriangleArea(const Vector3Base& v0, const Vector3Base& v1, const Vector3Base& v2);
///
- /// Calculates the angle (in radians) between from and to. This is always the smallest value.
+ /// Calculates the angle (in degrees) between from and to. This is always the smallest value.
///
/// The first vector.
/// The second vector.
- /// The angle (in radians).
+ /// The angle (in degrees).
static FLAXENGINE_API T Angle(const Vector3Base& from, const Vector3Base& to);
+ ///
+ /// Calculates the signed angle (in degrees) between from and to vectors. This is always the smallest value. The sign of the result depends on: the order of input vectors, and the direction of the axis vector.
+ ///
+ /// The first vector.
+ /// The second vector.
+ /// The axis around which the vectors are rotated.
+ /// The angle (in degrees).
+ static FLAXENGINE_API T SignedAngle(const Vector3Base& from, const Vector3Base& to, const Vector3Base& axis);
+
///
/// Snaps the input position onto the grid.
///