[Fix] Closest Quaternion
This commit is contained in:
@@ -44,6 +44,12 @@ namespace YachtDice.Dice
|
||||
return e.Value;
|
||||
}
|
||||
|
||||
public Quaternion GetClosestTopAlignedWorldRotation(Quaternion currentWorldRotation)
|
||||
{
|
||||
var e = GetExtremeEntryByWorldY(isTop: true);
|
||||
return GetClosestAlignedWorldRotation(e.Point, currentWorldRotation);
|
||||
}
|
||||
|
||||
public int AlignToBottomByLocalAngles()
|
||||
{
|
||||
var e = GetExtremeEntryByWorldY(isTop: false);
|
||||
@@ -82,6 +88,28 @@ namespace YachtDice.Dice
|
||||
return true;
|
||||
}
|
||||
|
||||
private Quaternion GetClosestAlignedWorldRotation(Transform facePoint, Quaternion currentWorldRotation)
|
||||
{
|
||||
if (!facePoint) throw new InvalidOperationException("Dice: facePoint == null.");
|
||||
|
||||
var baseWorldRotation = GetAlignedWorldRotation(facePoint);
|
||||
var bestWorldRotation = baseWorldRotation;
|
||||
var smallestAngle = Quaternion.Angle(currentWorldRotation, baseWorldRotation);
|
||||
|
||||
for (var i = 1; i < 4; i++)
|
||||
{
|
||||
var candidateWorldRotation = Quaternion.AngleAxis(90f * i, Vector3.up) * baseWorldRotation;
|
||||
var candidateAngle = Quaternion.Angle(currentWorldRotation, candidateWorldRotation);
|
||||
|
||||
if (candidateAngle >= smallestAngle) continue;
|
||||
|
||||
smallestAngle = candidateAngle;
|
||||
bestWorldRotation = candidateWorldRotation;
|
||||
}
|
||||
|
||||
return bestWorldRotation;
|
||||
}
|
||||
|
||||
private Entry GetExtremeEntryByWorldY(bool isTop)
|
||||
{
|
||||
if (_entrySet == null || _entrySet.Count == 0)
|
||||
@@ -118,11 +146,23 @@ namespace YachtDice.Dice
|
||||
return a > 180f ? a - 360f : (a < -180f ? a + 360f : a);
|
||||
}
|
||||
|
||||
private Quaternion GetAlignedWorldRotation(Transform facePoint)
|
||||
{
|
||||
var parentRotation = transform.parent != null ? transform.parent.rotation : Quaternion.identity;
|
||||
return parentRotation * GetAlignedLocalRotation(facePoint);
|
||||
}
|
||||
|
||||
private static Quaternion GetAlignedLocalRotation(Transform facePoint)
|
||||
{
|
||||
if (!facePoint) throw new InvalidOperationException("Dice: facePoint == null.");
|
||||
return Quaternion.Inverse(facePoint.localRotation);
|
||||
}
|
||||
|
||||
private void AlignByFaceLocalAngles(Transform facePoint)
|
||||
{
|
||||
if (!facePoint) throw new InvalidOperationException("Dice: facePoint == null.");
|
||||
|
||||
transform.localEulerAngles = Vector3.Scale(facePoint.localEulerAngles, new Vector3(-1f, -1f, -1f));
|
||||
transform.localRotation = GetAlignedLocalRotation(facePoint);
|
||||
|
||||
var e = transform.localEulerAngles;
|
||||
transform.localEulerAngles = new Vector3(Norm180(e.x), Norm180(e.y), Norm180(e.z));
|
||||
|
||||
Reference in New Issue
Block a user