簡體   English   中英

計算給定 3 個點的平面的 3D 旋轉及其相對 position

[英]Calculate 3D rotation of a plane given 3 points and their relative position

我正在嘗試在 Unity 中旋轉 3D 中的平面,給出三點。 這些點並不總是相同的,但它們始終位於此圖像中的紅點上

我知道這些點的絕對位置,以及它們相對於平面的 position。 例如,我可能知道點 (-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 軸的旋轉? 先感謝您。

聽起來你實際上有給定的分數

  • 左上角
  • 右上角
  • 左下角

所以你可能會得到兩個方向,並簡單地假設給定的 3 點實際上是他們聲稱的

var ul = UpperLeft.transform.position;
var ur = UpperRight.transform.position;
var ll = LowerLeft.transform.position;

// actually ignored since setting right and up is already enough
// need it though to calculate the up vector and the final position
var forward = ul - ll;
var right = ur - ul;

var up = Vector3.Cross(forward, right);
rotator.transform.up = up;
rotator.transform.right = right;

// and finally if needed place the center 
rotator.transform.position = ul + right * 0.5f - forward * 0.5f;

在此處輸入圖像描述

一旦你確定了向前和向上的方向, Quaternion.LookRotation讓這變得簡單:

struct VirtualPoint 
{
    Vector3 absolutePos;
    Vector3 relativePos;
}

// Uses list of points, but works for 3
void GetMinMaxPoints(List<VirtualPoint> points, out VirtualPoint xMinP, 
        out VirtualPoint xMaxP, out VirtualPoint yMinP, 
        out VirtualPoint yMaxP)
{
    Debug.Assert(points.Count >= 1);

    xMinP = xMaxP = yMinP = yMaxP = points[0];

    float xMin, xMax, yMin, yMax;
    xMin = xMax = points[0].relativePos.x;
    yMin = yMax = points[0].relativePos.y;

    foreach (Virtual point: points) 
    {
        Vector3 pos = point.relativePos;
        if (pos.x < xMin)
        {
            xMin = pos.x;
            xMinP = point;
        }
        else if (pos.x > xMax)
        {
            xMax = pos.x;
            xMaxP = point
        }

        if (pos.y < yMin) 
        {
            yMin = pos.y;
            yMinP = point;
        }
        else if (pos.y > yMax)
        {
            yMax = pos.y;
            yMaxP = point;
        }
    }
}

Quaternion GetPlaneRotation(List<VirtualPoint> points)
{
    Debug.Assert(points.Count >= 3);

    GetMinMaxPoints( out VirtualPoint xMinP, out VirtualPoint xMaxP,
        out VirtualPoint yMinP, out VirtualPoint yMaxP);
    
    if (xMinP.absolutePos == xMaxP.absolutePos 
            || yMinP.absolutePos == xMinP.absolutePos)
    {
        throw new System.Exception("points don't define plane");
    }

    Vector3 forwardDir = yMaxP.absolutePos - yMinP.absolutePos;
    Vector3 rightdir = xMaxP.absolutePos - xMaxP.absolutePos;

    Vector3 upDir = Vector3.Cross(forwardDir, rightDir);

    return Quaternion.LookRotation(forwardDir, upDir);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM