让一个物体的两个标准轴向与某两个互相垂直的向量重合

在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;

    }
发布了90 篇原创文章 · 获赞 15 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_43149049/article/details/104660722