mirror of
https://github.com/Redot-Engine/redot-engine.git
synced 2025-12-06 07:17:42 -05:00
Merge pull request #107618 from DanielGSilva/quat-arc
Fix `Quaternion(arc_from: Vector3, arc_to: Vector3)` behaves differently in gdscript and c#
This commit is contained in:
@@ -652,12 +652,10 @@ namespace Godot
|
|||||||
column2 = -column2;
|
column2 = -column2;
|
||||||
}
|
}
|
||||||
Vector3 column0 = up.Value.Cross(column2);
|
Vector3 column0 = up.Value.Cross(column2);
|
||||||
#if DEBUG
|
|
||||||
if (column0.IsZeroApprox())
|
if (column0.IsZeroApprox())
|
||||||
{
|
{
|
||||||
throw new ArgumentException("The target vector and up vector can't be parallel to each other.");
|
throw new ArgumentException("Target and up vectors are colinear. This is not advised as it may cause unwanted rotation around local Z axis.");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
column0.Normalize();
|
column0.Normalize();
|
||||||
Vector3 column1 = column2.Cross(column0);
|
Vector3 column1 = column2.Cross(column0);
|
||||||
return new Basis(column0, column1, column2);
|
return new Basis(column0, column1, column2);
|
||||||
|
|||||||
@@ -558,18 +558,35 @@ namespace Godot
|
|||||||
|
|
||||||
public Quaternion(Vector3 arcFrom, Vector3 arcTo)
|
public Quaternion(Vector3 arcFrom, Vector3 arcTo)
|
||||||
{
|
{
|
||||||
Vector3 c = arcFrom.Cross(arcTo);
|
#if DEBUG
|
||||||
real_t d = arcFrom.Dot(arcTo);
|
if (arcFrom.IsZeroApprox() || arcTo.IsZeroApprox())
|
||||||
|
|
||||||
if (d < -1.0f + Mathf.Epsilon)
|
|
||||||
{
|
{
|
||||||
X = 0f;
|
throw new ArgumentException("The vectors must not be zero.");
|
||||||
Y = 1f;
|
}
|
||||||
Z = 0f;
|
#endif
|
||||||
W = 0f;
|
#if REAL_T_IS_DOUBLE
|
||||||
|
const real_t AlmostOne = 0.999999999999999;
|
||||||
|
#else
|
||||||
|
const real_t AlmostOne = 0.99999975f;
|
||||||
|
#endif
|
||||||
|
Vector3 n0 = arcFrom.Normalized();
|
||||||
|
Vector3 n1 = arcTo.Normalized();
|
||||||
|
real_t d = n0.Dot(n1);
|
||||||
|
if (Mathf.Abs(d) > AlmostOne)
|
||||||
|
{
|
||||||
|
if (d >= 0.0f)
|
||||||
|
{
|
||||||
|
return; // Vectors are same.
|
||||||
|
}
|
||||||
|
Vector3 axis = n0.GetAnyPerpendicular();
|
||||||
|
X = axis.X;
|
||||||
|
Y = axis.Y;
|
||||||
|
Z = axis.Z;
|
||||||
|
W = 0.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Vector3 c = n0.Cross(n1);
|
||||||
real_t s = Mathf.Sqrt((1.0f + d) * 2.0f);
|
real_t s = Mathf.Sqrt((1.0f + d) * 2.0f);
|
||||||
real_t rs = 1.0f / s;
|
real_t rs = 1.0f / s;
|
||||||
|
|
||||||
@@ -578,6 +595,7 @@ namespace Godot
|
|||||||
Z = c.Z * rs;
|
Z = c.Z * rs;
|
||||||
W = s * 0.5f;
|
W = s * 0.5f;
|
||||||
}
|
}
|
||||||
|
this = Normalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -1283,5 +1283,19 @@ namespace Godot
|
|||||||
{
|
{
|
||||||
return $"({X.ToString(format, CultureInfo.InvariantCulture)}, {Y.ToString(format, CultureInfo.InvariantCulture)}, {Z.ToString(format, CultureInfo.InvariantCulture)})";
|
return $"({X.ToString(format, CultureInfo.InvariantCulture)}, {Y.ToString(format, CultureInfo.InvariantCulture)}, {Z.ToString(format, CultureInfo.InvariantCulture)})";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal readonly Vector3 GetAnyPerpendicular()
|
||||||
|
{
|
||||||
|
// Return the any perpendicular vector by cross product with the Vector3.RIGHT or Vector3.UP,
|
||||||
|
// whichever has the greater angle to the current vector with the sign of each element positive.
|
||||||
|
// The only essence is "to avoid being parallel to the current vector", and there is no mathematical basis for using Vector3.RIGHT and Vector3.UP,
|
||||||
|
// since it could be a different vector depending on the prior branching code Math::abs(x) <= Math::abs(y) && Math::abs(x) <= Math::abs(z).
|
||||||
|
// However, it would be reasonable to use any of the axes of the basis, as it is simpler to calculate.
|
||||||
|
if (IsZeroApprox())
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The Vector3 must not be zero.");
|
||||||
|
}
|
||||||
|
return Cross((Mathf.Abs(X) <= Mathf.Abs(Y) && Mathf.Abs(X) <= Mathf.Abs(Z)) ? new Vector3(1, 0, 0) : new Vector3(0, 1, 0)).Normalized();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user