统一镜像Oculus Rift控制器位置以进行双边运动

时间:2019-07-12 19:50:25

标签: c# unity3d vector accessibility oculus

当前,我正在尝试编写一个脚本,以将只有一个功能臂的用户将一个控制器的运动镜像到另一个控制器。如何将一个控制器的位置镜像到另一个控制器上,以使手臂处于双向运动状态?

对y轴和z轴进行镜像很容易,因为它们一起移动并且旋转也易于镜像。我无法反映x轴的运动。我想要这样,以便如果一只手伸出另一只手也一样,并且它们都一起移动。有什么想法我可能能够做到这一点吗?我已附上当前脚本。 我还使用OVRCemeraRig脚本中的简单布尔逻辑禁用了非镜像控制器的位置跟踪,以防止出现卡顿现象 由于使用了最终IK,因此需要使用OVRCemeraRig

我尝试过改变工作臂的x位置,然后将该值添加到不工作臂。那没用。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class VRMirror : MonoBehaviour
{
    public bool mirrorLeft;
    public bool mirrorRight;
    public GameObject leftHand; //left hand anchor in OVRCameraRig
    public GameObject rightHand; //right hand anchor from OVRCameraRig
    void Start()
    {

    }
    void FixedUpdate()
    {
        Transform left = leftHand.GetComponent<Transform>();
        Transform right = rightHand.GetComponent<Transform>();
        if (mirrorLeft)
        {
            Vector3 leftPos = left.position;
            Quaternion leftRot = left.rotation;
            leftRot.y = -leftRot.y;
            right.position = leftPos;
            right.rotation = leftRot;
        }
        else if (mirrorRight)
        {
            Vector3 rightPos = right.position;
            Quaternion rightRot = right.rotation;

            rightRot.y = -rightRot.y;
            left.position = rightPos;
            left.rotation = rightRot;

        }
    }
}

2 个答案:

答案 0 :(得分:1)

为了稳健起见,让我们假设玩家的身体旋转不一定总是正确地指向(1,0,0)世界方向。取而代之的是,我们可以参考玩家的变形playerTransform(一定要使用检查器或如果需要的话在Start中进行赋值),并以此进行计算。

要计算相对矢量的双边对称位置,可以计算relativeVec - 2f * playerTransform.right * Vector3.Dot(relativeVec, playerTransform.right);。在注释中说明为什么行之有效。

对于位置,我们可以将源手的绝对位置转换为相对于玩家的位置,然后找到目标手的相对位置,然后将其转换回绝对位置。

要进行旋转,请确定源手的向上和向前,并反射它们以确定目标手的向上和向前。使用Quaternion.SetLookRotation将矢量转换为目标手的旋转。

我们可以将相同的代码用于相对位置和方向矢量,因此,一旦掌握了数学知识,实际上并不需要太多的代码。而且,由于Transform是一个类,我们可以制作一个执行反射过程的方法,然后将其传递给我们,它是我们要成为源和目标的转换:

public class VRMirror : MonoBehaviour
{
    public bool mirrorLeft;
    public bool mirrorRight;
    public GameObject leftHand; //left hand anchor in OVRCameraRig
    public GameObject rightHand; //right hand anchor from OVRCameraRig

    public Transform playerTransform;

    void Start()
    {

    }
    void FixedUpdate()
    {

        Transform left = leftHand.GetComponent<Transform>();
        Transform right = rightHand.GetComponent<Transform>();
        if (mirrorLeft)
        {
            MirrorFromTo(left, right);
        }
        else if (mirrorRight)
        {
            MirrorFromTo(right, left);
        }
    }

    void MirrorFromTo(Transform sourceTransform, Transform destTransform)
    {
        // Determine dest position
        Vector3 playerToSourceHand = sourceTransform.position - playerTransform.position;
        Vector3 playerToDestHand = ReflectRelativeVector(playerToSourceHand);
        destTransform.position = playerTransform.position + playerToDestHand ;

        // Determine dest rotation
        Vector3 forwardVec = ReflectRelativeVector(sourceTransform.forward);
        Vector3 upVec = ReflectRelativeVector(sourceTransform.up);
        destTransform.rotation = Quaternion.LookRotation(forwardVec,upVec);
    }

    Vector3 ReflectRelativeVector(Vector3 relativeVec) 
    {
       // relativeVec
       //     Take the relative vector....
       // + Vector3.Dot(relativeVec, playerTransform.right)
       //     and for how far along the player's right direction it is 
       //     away from the player (may be negative),
       // * playerTransform.right
       //     move it that distance along the player's right...
       // * -2f
       //    negative two times (i.e., along the left direction 2x)

       return relativeVec 
           + Vector3.Dot(relativeVec, playerTransform.right)
               * playerTransform.right 
               * -2f;
    }
}

答案 1 :(得分:1)

我对@Ruzihm的内容进行了一些更改。十分感谢你的帮助。在下面的示例代码中,一切都可以正常运行,但是我建议@Ruzihm回答,因为他如何处理旋转。如果播放器模型固定并且您没有转动身体,则此代码有效。如果需要转弯,请在ReflectRelativeVector函数中使用:playerTransform.right而不是Vector3.right,但是使用playerTransform.right会随着头部的移动来移动手臂。

public class VRMirror : MonoBehaviour
{
    public bool mirrorLeft;
    public bool mirrorRight;
    public GameObject leftHand; //left hand anchor in OVRCameraRig
    public GameObject rightHand; //right hand anchor from OVRCameraRig

    public Transform playerTransform;  

    void Start()
    {

    }
    void FixedUpdate()
    {

        Transform left = leftHand.GetComponent<Transform>();
        Transform right = rightHand.GetComponent<Transform>();
        if (mirrorLeft)
        {
             MirrorFromTo(left, right);
        }
        else if (mirrorRight)
        {
            MirrorFromTo(right, left);

        }
    }

    void MirrorFromTo(Transform sourceTransform, Transform destTransform)
    {
        // Determine dest position
        Vector3 playerToSourceHand = sourceTransform.position - playerTransform.position;
        Vector3 playerToDestHand = ReflectRelativeVector(playerToSourceHand);
        destTransform.position = playerTransform.position + playerToDestHand;

        // Determine dest rotation
        Quaternion destRot = sourceTransform.rotation;

        destRot.y = -destRot.y;
        destRot.z = -destRot.z;
        destTransform.rotation = destRot;

    }

    Vector3 ReflectRelativeVector(Vector3 relativeVec)
    {
        // relativeVec
        //     Take the relative vector....
        // + Vector3.Dot(relativeVec, playerTransform.right)
        //     and for how far along the player's right direction it is 
        //     away from the player (may be negative),
        // * playerTransform.right
        //     move it that distance along the player's right...
        // * -2f
        //    negative two times (i.e., along the left direction 2x)

        return relativeVec
        + Vector3.Dot(relativeVec, Vector3.right)
            * Vector3.right
            * -2f;
    }
}

这是编辑器的屏幕截图: enter image description here