计算给定 3 个点及其相对位置的平面的 3D 旋转

Posted

技术标签:

【中文标题】计算给定 3 个点及其相对位置的平面的 3D 旋转【英文标题】:Calculate 3D rotation of a plane given 3 points and their relative position 【发布时间】:2022-01-06 06:29:43 【问题描述】:

我正在尝试在 Unity 中旋转 3D 平面,给定三个点。这些点并不总是相同的,但它们总是在这张图片中的红点上

我知道这些点的绝对位置,以及它们相对于平面的位置。例如,我可能知道点 (-5, 5) 位于 (10, -4, 13)。

我知道当三个点在一条线上时(例如 (-5, 5)、(0, 5) 和 (5, 5)),不可能计算完整的旋转,所以我已经抛出异常在这种情况下。但是,当三个点不在一条线上时,应该可以计算完整的旋转。

到目前为止,我已经使用下面的代码进行旋转,但这错过了围绕 y 轴的旋转(示例使用点 (-5, 5)、(5, 5) 和 (-5, -5 )。

Vector3 p1 = Point1.transform.position;// point 1 absolute position
Vector3 p1Relative = new Vector3(-5, 0, 5);
Vector3 p2 = Point2.transform.position;// point 2 absolute position
Vector3 p2Relative = new Vector3(5, 0, 5);
Vector3 p3 = Point3.transform.position;// point 3 absolute position
Vector3 p3Relative = new Vector3(-5, 0, -5);

Gizmos.DrawSphere(p1, .1f);
Gizmos.DrawSphere(p2, .1f);
Gizmos.DrawSphere(p3, .1f);

Vector3 normal = Vector3.Cross(p2 - p1, p3- p1);
rotator.transform.up = normal;

如何扩展或更改此代码以包含围绕 Y 轴的旋转?提前谢谢你。

【问题讨论】:

我很困惑......如果你有一个明显中心位置的平面......那么有两个额外的点应该足以计算这个权利的旋转? 确实如此!然而,我也在 3D 空间中移动飞机。不过我可以计算出这个中心位置。 【参考方案1】:

此答案使用robjohn 在数学堆栈交换中描述的this method。

您可以解决一对Matrix4x4s,您可以使用它们从第一个坐标系转换到第二个坐标系,然后使用它来计算原点(中心点)和旋转以对齐轴(使用 @ 987654325@);

public class test : MonoBehaviour

    [SerializeField] Transform point1;
    [SerializeField] Transform point2;
    [SerializeField] Transform point3;

    [SerializeField] Vector2 relativePos1;
    [SerializeField] Vector2 relativePos2;
    [SerializeField] Vector2 relativePos3;

    [SerializeField] Transform demonstrator;

    void Update()
    
        Vector3 absolutePos1 = point1.position;
        Vector3 absolutePos2 = point2.position;
        Vector3 absolutePos3 = point3.position;

        Vector3 relativePos4 = (Vector3)relativePos1 +
                Vector3.Cross(relativePos2 - relativePos1, 
                relativePos3 - relativePos1);
        Vector3 absolutePos4 = absolutePos1 + 
                Vector3.Cross(absolutePos2 - absolutePos1, 
                absolutePos3 - absolutePos1);

        Vector4 rightColumn = new Vector4(0, 0, 0, 1);
        Matrix4x4 P = new Matrix4x4(relativePos2 - relativePos1,
                relativePos3 - relativePos1, 
                relativePos4 - (Vector3)relativePos1, rightColumn);
        Matrix4x4 Q = new Matrix4x4(absolutePos2 - absolutePos1, 
                absolutePos3 - absolutePos1, 
                absolutePos4 - absolutePos1, rightColumn);

        Vector3 originPos = TransformPos(P, Q, Vector3.zero);

        // up in source is forward in output        
        Vector3 forwardPos = TransformPos(P, Q, Vector3.up);

        // back in source is up in output
        Vector3 upPos = TransformPos(P, Q, Vector3.back);

        demonstrator.position = originPos;
        demonstrator.rotation = Quaternion.LookRotation(forwardPos 
                - originPos, upPos - originPos);
    

    Vector3 TransformPos(Matrix4x4 P, Matrix4x4 Q, Vector3 input)
    
        Matrix4x4 invP = P.inverse;
        return Q * invP * input + ((Vector4)point1.position 
                - Q * invP * relativePos1);
    

【讨论】:

如果有错别字或问题,请告诉我,我可以改正

以上是关于计算给定 3 个点及其相对位置的平面的 3D 旋转的主要内容,如果未能解决你的问题,请参考以下文章

如何在opengl中计算给定3D点及其2D屏幕位置的投影/模型视图矩阵

给定表面法线,找到 3D 平面的旋转

向数学达人求助,如何求到平面上五个任意的点距离最近的点的位置?已知那五个点的位置

找到与已知 Homography 的平面平行的平面的 Homography

Three.js 飞机的 3D 旋转

从3个点检索正角度或负角度