Quaternion rotation = Quaternion.FromToRotation(dirA, dirB); return rotation * originalPoint;
通常使用上面方式来将一个点从方向A移动到方向B,但是如果方向A和方向B平行相反时(比如(0,0,1)->(0,0,-1))上面的计算会有问题,此时我们需要指定旋转轴,然后旋转180度,比如
Quaternion rotation = Quaternion.AngleAxis(180f, Vector3.up); return rotation * originalPoint;
但是如果两点不在z轴平面,比如(1,1,1)->(-1,-1,-1),此时需要动态计算出旋转轴,可以使用如下代码
using UnityEngine; public class ParallelRotationCalculator : MonoBehaviour { public Vector3 startDirection = new Vector3(1, 1, 1); public Vector3 targetDirection = new Vector3(-1, -1, -1); public Vector3 originalPoint = Vector3.zero; // 原始点位置 // 动态计算旋转轴(当两个向量平行相反时) private Vector3 CalculatePerpendicularAxis(Vector3 dir) { //使用正交化方法生成垂直向量 dir.Normalize(); // 选择与dir方向分量差异最大的轴,避免平行 Vector3 candidateAxis = Mathf.Abs(dir.x) < 0.7f ? Vector3.right : Mathf.Abs(dir.y) < 0.7f ? Vector3.up : Vector3.forward; Vector3 axis = Vector3.Cross(dir, candidateAxis).normalized; // 二次验证:若叉积模长接近0,换另一轴 if (axis.sqrMagnitude < 0.001f) { candidateAxis = candidateAxis == Vector3.right ? Vector3.up : Vector3.right; axis = Vector3.Cross(dir, candidateAxis).normalized; } return axis; } // 计算旋转后的点位置 public Vector3 CalculateRotatedPoint() { Vector3 dirA = startDirection.normalized; Vector3 dirB = targetDirection.normalized; //通过点积检测:若 Vector3.Dot(A, B) ≈ -1(考虑浮点误差),则两向量平行反向 if (Vector3.Dot(dirA, dirB) < -0.999f) // 平行反向 { Vector3 axis = CalculatePerpendicularAxis(dirA); Quaternion rotation = Quaternion.AngleAxis(180f, axis); return rotation * originalPoint; } else // 非平行方向 { Quaternion rotation = Quaternion.FromToRotation(dirA, dirB); return rotation * originalPoint; } } // 可视化调试 void OnDrawGizmos() { Vector3 rotatedPoint = CalculateRotatedPoint(); Gizmos.color = Color.green; Gizmos.DrawSphere(originalPoint, 0.1f); // 原始点 Gizmos.color = Color.red; Gizmos.DrawSphere(rotatedPoint, 0.1f); // 旋转后的点 Gizmos.DrawLine(originalPoint, rotatedPoint); // 连线 // 绘制旋转轴(仅平行反向时) if (Vector3.Dot(startDirection.normalized, targetDirection.normalized) < -0.999f) { Vector3 axis = CalculatePerpendicularAxis(startDirection); Gizmos.color = Color.blue; Gizmos.DrawLine(originalPoint - axis * 2, originalPoint + axis * 2); } } }
文章评论