Search Unity

#CodeSnippets: Toggle Vive's front facing camera and "Tron Mode" at run time

June 16, 2017 in Technology | 4 min. read
Topics covered
Share

Is this article helpful for you?

Thank you for your feedback!

How to programmatically turn the front facing camera video and camera for chaperone bounds on and off on the HTC Vive.

Unity’s 2017 hack week happened a couple of weeks ago in Nyborg, Denmark. As our contribution, my team decided to explore physical VR and UX/UI with HTC Vive trackers. In our proposed scenario, the application starts with a step that provides quick and easy calibration to scan the physical world into the virtual. This is followed by a fully immersive VR experience where virtual objects and surfaces are aligned with physical ones.

The HTC Vive headset has a camera that users can activate in SteamVR to show video of the actual room they are in, and also to activate what is commonly referred to as “Tron Mode,” a setting called Allow Camera for Chaperone Bounds which detects and highlights the edges of objects. For the proposed scenario, we wanted to test and evaluate three different options for allowing users to “draw” the physical world:

  1. Render a quad next to one of the controllers with video of the room, just like in SteamVR dashboard.
  2. Enable Tron Mode
  3. Options (1) and (2) at the same time.

We needed to programmatically go through each of these options, turning the front facing camera video and the Allow Camera for Chaperone Bounds setting on and off. In this blog post we share the code for how this was accomplished for the hack week project.

Rendering video to a quad next to the controller was easy since the SteamVR Unity plugin provides a sample scene that does it: SteamVR_TestTrackedCamera located in the folder SteamVR -> Extras has all we need. After parenting the TrackedCamera game object to one of the controllers in the object hierarchy, toggling it on and off is just a matter of enabling/disabling the associated game object.

Toggling Tron Mode is done by calling SetBool in OpenVR settings:

EVRSettingsError SetTronMode(bool enable)
{
    EVRSettingsError e = EVRSettingsError.None;
    OpenVR.Settings.SetBool(OpenVR.k_pch_Camera_Section,
                            OpenVR.k_pch_Camera_EnableCameraForCollisionBounds_Bool,
                            enable,
                            ref e);
    OpenVR.Settings.Sync(true, ref e);
    return e;
}

We then define an enumeration for the video mode, and call the toggle functions when a menu button is pressed. The following behavior is assigned to TrackedCamera:

using UnityEngine;
using Valve.VR;

public class SwitchVideoMode : MonoBehaviour
{
    [SerializeField]
    SteamVR_TrackedController rightCtrl;
    [SerializeField]
    SteamVR_TrackedController leftCtrl;

    [SerializeField]
    [Tooltip("Quad that is parented to controller and renders video")]
    GameObject videoQuad;

    SteamVR_TestTrackedCamera trackedCamera;

    enum VideoMode
    {
        NONE,
        TRON_AND_VIDEO,
        TRON,
        VIDEO,
    }

    VideoMode vMode;

    void Start()
    {
        trackedCamera = GetComponent<SteamVR_TestTrackedCamera>();


        // we assume on Start that TrackedCamera game object and video quad
        // are disabled in the object hierarchy, so only test for tron mode.
        EVRSettingsError e = EVRSettingsError.None;
        var tron_enabled = OpenVR.Settings.GetBool(
            OpenVR.k_pch_Camera_Section,
            OpenVR.k_pch_Camera_EnableCameraForCollisionBounds_Bool,
            ref e);
        vMode = tron_enabled ? VideoMode.TRON : VideoMode.NONE;
        if (e != EVRSettingsError.None)
        {
            Debug.LogError(e);
        }

        rightCtrl.MenuButtonClicked += CtrlClicked;
        leftCtrl.MenuButtonClicked += CtrlClicked;
    }

    bool menuPressed;
    void CtrlClicked (object sender, ClickedEventArgs e)
    {
        menuPressed = true;
    }

    void Update ()
    {
        if (menuPressed)
        {
            vMode = (VideoMode)(((int)vMode + 1) % 4);
            SetVideoMode(vMode);
            menuPressed = false;
        }
    }

    void SetVideoMode(VideoMode m)
    {
        EVRSettingsError e = EVRSettingsError.None;

        switch (m)
        {
            case VideoMode.NONE:
                SetCameraVideo(false);
                e = SetTronMode(false);
                break;
            case VideoMode.TRON:
                SetCameraVideo(false);
                e = SetTronMode(true);
                break;
            case VideoMode.VIDEO:
                SetCameraVideo(true);
                e = SetTronMode(false);
                break;
            case VideoMode.TRON_AND_VIDEO:
                SetCameraVideo(true);
                e = SetTronMode(true);
                break;
        }

        if (e != EVRSettingsError.None)
        {
            Debug.LogError(e);
        }
    }


    EVRSettingsError SetTronMode(bool enable)
    {
        EVRSettingsError e = EVRSettingsError.None;
        OpenVR.Settings.SetBool(OpenVR.k_pch_Camera_Section,
                                OpenVR.k_pch_Camera_EnableCameraForCollisionBounds_Bool,
                                enable,
                                ref e);
        OpenVR.Settings.Sync(true, ref e);
        return e;
    }

    void SetCameraVideo(bool enable)
    {
        videoQuad.SetActive(enable);
        trackedCamera.enabled = enable;
    }
}

The video below shows what activating each video mode at run time looks like in our hack week project. By combining the construction tool programmed by my colleague Josh Naylor and the video mode switching behavior, I am able to build a box in VR that is aligned with a real, physical one. After building the virtual box, I disable video and become completely immersed in a virtual reality scene that is calibrated with the physical space.

This content is hosted by a third party provider that does not allow video views without acceptance of Targeting Cookies. Please set your cookie preferences for Targeting Cookies to yes if you wish to view videos from these providers.

The code snippet in this article is a solution in the context of a hack week project. For scalability and modularity, developers would probably want to handle video modes independently, and add additional features like allowing resizing of the video quad. While in this experience we found that just the video quad next to the controller was enough to outline small-to-medium-size objects, UX professionals would probably find it valuable to experiment and evaluate if Tron Mode is more suitable for certain scenarios, or whether combining both video feed and Tron makes a difference in terms of immersion and alignment. I share this code as a starting point and reference.

For a full video of our project, check the video on YouTube. My teammates were: Greg Madison, Jonas Minnberg, Josh Naylor and Tristan Genevet.

What other use cases do you have for toggling these features at run time? We’d love to hear them!

June 16, 2017 in Technology | 4 min. read

Is this article helpful for you?

Thank you for your feedback!

Topics covered