讓一個物體的兩個標準軸向與某兩個互相垂直的向量重合

在unity的左手座標系系統中,一個物體有三個軸向,確定了兩個軸向那物體的旋轉就確定了,很多時候我們只需要指定物體的某個方向比如transform.forward= others.transform.forward,又或者指定物體的旋轉transform.rotation = others.transform.rotation就可以滿足需求,但是如果我們需要指定物體的A的z軸與b的z軸一致,但是y軸是b的x軸的反方向呢,這種時候上面的兩種做法就不能滿足情況了,不懂四元數的話又比較喫力,所以這裏提供一個方法,可以實現一個物體的兩個標準軸的方向與兩個互相垂直的軸重合
具體思路是,先讓物體的一個軸與目標軸重合,然後再讓物體圍繞已擺弄好的軸旋轉從而讓另一個軸與目標軸重合

/// <summary>
    /// 讓toChngTrn達到
    /// firstVctrToOper代表的軸方向與firstVctrToReach一致並且
    /// scndVctrToOper代表的軸方向與scndVctrToReach一致的時候
    /// 的旋轉
    /// </summary>
    /// <param name="firstVctrToOper"></param>
    /// <param name="scndVctrToOper"></param>
    /// <param name="toChngTrn"></param>
    /// <param name="firstVctrToReach"></param>
    /// <param name="scndVctrToReach"></param>
    public static void AlignTransformWithTwoVctr(Vector3 firstVctrToOper,
        Vector3 scndVctrToOper, Transform toChngTrn, Vector3 firstVctrToReach,
        Vector3 scndVctrToReach)
    {
        if (firstVctrToOper == scndVctrToOper ||
            firstVctrToReach == scndVctrToReach || toChngTrn == null)
        {
            Debug.LogError(" ThreeDUtil AlignTransformWithTwoVctr invalid Param ");
            return;
        }

        Vector3 rotateAroundPivotVctr = Vector3.zero;
        //第一次的時候直接設置值即可
        if (firstVctrToOper == toChngTrn.forward)
        {
            //Debug.LogError(" ThreeDUtil AlignTransformWithTwoVctr " +
            //    "firstVctrToOper == toChngTrn.forward");
            toChngTrn.forward = firstVctrToReach;
            rotateAroundPivotVctr = Vector3.forward;
        }
        else if (firstVctrToOper == toChngTrn.right)
        {
            //Debug.LogError(" ThreeDUtil AlignTransformWithTwoVctr " +
            //    "firstVctrToOper == toChngTrn.right");
            toChngTrn.right = firstVctrToReach;
            rotateAroundPivotVctr = Vector3.right;
        }
        else if (firstVctrToOper == toChngTrn.up)
        {
            //Debug.LogError(" ThreeDUtil AlignTransformWithTwoVctr " +
            //    "firstVctrToOper == toChngTrn.up");
            toChngTrn.up = firstVctrToReach;
            rotateAroundPivotVctr = Vector3.up;
        }

        Transform tempTrn1 = new GameObject("tempTrn1").transform;
        tempTrn1.rotation = toChngTrn.rotation;

        bool isFind = true;
        if (!AlignScndPivot(scndVctrToReach, PivotEnum.Front, toChngTrn.forward,
            rotateAroundPivotVctr, toChngTrn))
        {
            if (!AlignScndPivot(scndVctrToReach, PivotEnum.Right, toChngTrn.right,
            rotateAroundPivotVctr, toChngTrn))
            {
                if (!AlignScndPivot(scndVctrToReach, PivotEnum.Up, toChngTrn.up,
                rotateAroundPivotVctr, toChngTrn))
                {
                    isFind = false;
                }
                else
                {
                    Debug.LogError("ThreeDUtil PivotEnum.Up find");
                }
            }
            else
            {
                Debug.LogError("ThreeDUtil PivotEnum.Right find");
            }
        }
        else
        {
            Debug.LogError("ThreeDUtil  PivotEnum.Front find");
        }

        if (!isFind)
        {
            Debug.LogError("ThreeDUtil AlignTransformWithTwoVctr notFind");
        }
        GameObject.Destroy(tempTrn1.gameObject);
    }

    static bool AlignScndPivot(Vector3 toReachVctr, PivotEnum matchPivot,
        Vector3 toChngPivotVctr, Vector3 rotatePivotVctr, Transform toChngTrn)
    {
        float deltaDegree = 0;
        Transform tempTrn2, tempTrn3;

        deltaDegree = Vector3.Angle(toChngPivotVctr, toReachVctr);

        //Debug.LogError("ThreeDUtil AlignScndPivot deltaDegree " +
        //    deltaDegree + " rotatePivotVctr " + rotatePivotVctr);

        tempTrn2 = new GameObject("tempTrn2").transform;
        tempTrn3 = new GameObject("tempTrn3").transform;

        tempTrn2.rotation = toChngTrn.rotation;

        tempTrn2.Rotate(rotatePivotVctr, deltaDegree, Space.Self);

        tempTrn3.rotation = tempTrn2.rotation;

        Vector3 tempTestPivot = Vector3.zero;
        switch (matchPivot)
        {
            case PivotEnum.Right:
                tempTestPivot = tempTrn3.right;
                break;
            case PivotEnum.Front:
                tempTestPivot = tempTrn3.forward;
                break;
            case PivotEnum.Up:
                tempTestPivot = tempTrn3.up;
                break;
        }

        if (tempTestPivot == toReachVctr)
        {
            toChngTrn.rotation = tempTrn3.rotation;
            GameObject.Destroy(tempTrn2.gameObject);
            GameObject.Destroy(tempTrn3.gameObject);
            return true;
        }
        else
        {
            //假如先順時針旋轉了一定角度, 逆時針旋轉角度a還原成原先的樣子
            //再旋轉角度a就可以了
            tempTrn3.Rotate(rotatePivotVctr, -deltaDegree * 2, Space.Self);
            if (tempTestPivot == toReachVctr)
            {
                toChngTrn.rotation = tempTrn3.rotation;
                GameObject.Destroy(tempTrn2.gameObject);
                GameObject.Destroy(tempTrn3.gameObject);

                return true;
            }
        }
        GameObject.Destroy(tempTrn2.gameObject);
        GameObject.Destroy(tempTrn3.gameObject);
        return false;

    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章