How can I fixe a head limitation on the Oculus Rift/ Unity

Hi guys, I had a question and coded a shitty solution.

So my main question is : How can I fixe a head limitation on the Oculus Rift/Unity asset ?
To illustrate the problem, here is a picture:
37293-raymanexemple.png
→ I want the head of the player to be limitated in a zone and by using Oculus Rift head tracking positionning.

So the second question is: I coded a solution. Is it a shitty solution and how would you do it ? Do you have a better solution ?

My solution:
(Beerware license)

In OVRCameraRig.cs, I change the UpdateAnchors() methode by the following code :

  • delegatePositionning : give the possibility to manage the positionning instead of OVRCameraRig.

  • onPositionningUpdate: send to delegate the data that should be use to position the OVR cameras.

    public bool delegatePositionning;
    public delegate void UpdatePositionning(OVRPose leftPose, OVRPose rightPose, Transform left, Transform center, Transform right);
    public UpdatePositionning onPositionningUpdate;

      private void UpdateAnchors()
      {
    
          if (! delegatePositionning)
          {
    
              OVRPose leftEye = OVRManager.display.GetEyePose(OVREye.Left);
              OVRPose rightEye = OVRManager.display.GetEyePose(OVREye.Right);
              leftEyeAnchor.localRotation = leftEye.orientation;
              centerEyeAnchor.localRotation = leftEye.orientation; // using left eye for now
              rightEyeAnchor.localRotation = rightEye.orientation;
    
              leftEyeAnchor.localPosition = leftEye.position;
              centerEyeAnchor.localPosition = 0.5f * (leftEye.position + rightEye.position);
              rightEyeAnchor.localPosition = rightEye.position;
          }
          else 
          {
              if (onPositionningUpdate != null)
              {
                  OVRPose leftEye = OVRManager.display.GetEyePose(OVREye.Left);
                  OVRPose rightEye = OVRManager.display.GetEyePose(OVREye.Right);
                  onPositionningUpdate(leftEye, rightEye, leftEyeAnchor, centerEyeAnchor, rightEyeAnchor);
              }
          }
      }
    

Now that I can manage the positionning instead the OVRCam with the original data.
I can do what I want with it :wink: .

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(OVRCameraRig))]
public abstract class MyOVR_Positionning : MonoBehaviour
{


    private OVRCameraRig cameraRig;
    public Transform root;
    public void OnEnable()
    {
        if (cameraRig == null)
        {
            cameraRig = GetComponent<OVRCameraRig>() as OVRCameraRig;
        }
        if (cameraRig != null)
        {
            cameraRig.onPositionningUpdate += PositionOculusInScene;
        }

    }

    public void OnDisable()
    {
        if (cameraRig != null)
        {
            cameraRig.onPositionningUpdate -= PositionOculusInScene;
        }

    }


// Methode to inherit to be able to repositionning the camera at will.
    protected abstract void PositionOculusInScene(OVRPose leftPose, OVRPose rightPose, Transform left, Transform center, Transform right);

// Methode to apply the position you wantnow  like they do in OVRCamera
    protected void ApplyPositionningAt(Transform leftOVREye, Transform OVRcenter, Transform rightOVREye, ref Vector3 centerPosition, ref Vector3 toGoToTheRight, ref Vector3 toGoToTheLeft, ref Quaternion orientationLeft, ref Quaternion orientationRight)
    {
        leftOVREye.localPosition = centerPosition + toGoToTheLeft;
        OVRcenter.localPosition = centerPosition;
        rightOVREye.localPosition = centerPosition + toGoToTheRight;

        leftOVREye.localRotation = orientationLeft;
        OVRcenter.localRotation = orientationLeft;
        rightOVREye.localRotation = orientationRight;
    }
}

For exemple: limitate the head position, multiply it distance …

using UnityEngine;
using System.Collections;

public class MyOVR_StayNextNeck : MyOVR_Positionning {


    public Vector3 offsetbaseAdjustment;


    public float decreaseDistance = 0.3f;
    public float maxDistance = 0.5f;

    protected override void PositionOculusInScene(OVRPose leftPose, OVRPose rightPose, Transform left, Transform center, Transform right)
    {
        if (left == null || center == null || right == null) return;
        if (root == null)
        {
            Debug.Log("No root define !", this.gameObject);
        }
        Vector3 centerPosition = (leftPose.position + rightPose.position) / 2f;
        Vector3 centerToRight = rightPose.position - centerPosition;
        Vector3 centerToLeft = leftPose.position - centerPosition;

        //Add to the center the offset wanted.
        // How many distane between the offset  and the center
        float rootDistance = Vector3.Distance(Vector3.zero, centerPosition);

        if (rootDistance > decreaseDistance)
        {
            float distLimit = maxDistance - decreaseDistance;
            float pourcentBeforeOutMax = Mathf.Clamp((rootDistance - decreaseDistance) / (maxDistance - decreaseDistance), 0f, Mathf.Infinity);
            float pourcentToCourbe = pourcentBeforeOutMax * 0.5f * 0.5f;
               centerPosition = offsetbaseAdjustment + centerPosition.normalized * (decreaseDistance + decreaseDistance * pourcentToCourbe);
                     
        }
        else
            centerPosition = offsetbaseAdjustment + centerPosition;

        ApplyPositionningAt(left, center, right, ref centerPosition, ref centerToRight, ref centerToLeft, ref leftPose.orientation, ref rightPose.orientation);

    }

   
}

Hi,

Using your system, I made up another script to delimite the user head in a certain area using a visible box in the editor.
It is usefull if you want your player to be able to crouch but not moving far away.

Enjoy, and feel free for any feedback.

using UnityEngine;
using System.Collections;

public class MyOVR_StayDelimitedPlace : MyOVR_Positionning
{
    public Vector3 mPositionOffset = new Vector3(0,0,0);

    public bool mPositionBoundsUseCenter;
    public Bounds mPositionBounds;

    public float mMultiplicatorMovement = 1;

    public KeyCode mShortKeyRecenterPose = KeyCode.Space;

    protected override void PositionOculusInScene(OVRPose leftPose, OVRPose rightPose, Transform left, Transform center, Transform right)
    {
        if (left == null || center == null || right == null) return;

        Vector3 centerPosition = (leftPose.position + rightPose.position) / 2f;
        Vector3 centerToRight = rightPose.position - centerPosition;
        Vector3 centerToLeft = leftPose.position - centerPosition;

        // multiply distance and replace left and right camera
        centerPosition *= mMultiplicatorMovement;
        leftPose.position = centerPosition + centerToLeft;
        rightPose.position = centerPosition + centerToRight;


        Vector3 halfSizeBoxcolliderLocal = (mPositionBounds.extents / 2);

        if (Input.GetKey(mShortKeyRecenterPose))
        {
            OVRManager.display.RecenterPose();
        }

        centerPosition += mPositionOffset;        
        if (mPositionBoundsUseCenter)
        {
            centerPosition += mPositionBounds.center;
        }

        // clamp the camera within the box
        centerPosition = new Vector3(
            Mathf.Clamp(centerPosition.x, -halfSizeBoxcolliderLocal.x, halfSizeBoxcolliderLocal.x),
            Mathf.Clamp(centerPosition.y, -halfSizeBoxcolliderLocal.y, halfSizeBoxcolliderLocal.y),
            Mathf.Clamp(centerPosition.z, -halfSizeBoxcolliderLocal.z, halfSizeBoxcolliderLocal.z));

        ApplyPositionningAt(left, center, right, ref centerPosition, ref centerToRight, ref centerToLeft, ref leftPose.orientation, ref rightPose.orientation);
    }


    void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.green;

        Vector3 posCenter = mPositionOffset;
        if (mPositionBoundsUseCenter)
        {
            posCenter += mPositionBounds.center;
        }
        posCenter = transform.TransformPoint(posCenter);

        Gizmos.DrawSphere(posCenter, 0.02f);

        if (mPositionBounds.extents.x < 0 || mPositionBounds.extents.z < 0 || mPositionBounds.extents.z < 0)
        {
            Debug.LogError("mPositionBounds Should not have negative value");
        }

        Gizmos.DrawWireCube(transform.TransformPoint(mPositionBounds.center), transform.TransformDirection( Vector3.Scale(mPositionBounds.extents, transform.lossyScale) ));
    }
}