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);
}
}
}

文章评论