#CodeSnippets: Toggle Vive’s front facing camera and “Tron Mode” at run time

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:

Render a quad next to one of the controllers with video of the room, just like in SteamVR dashboard.

Enable Tron Mode

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.

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:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

using UnityEngine;

using Valve.VR;

publicclassSwitchVideoMode: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;

enumVideoMode

{

NONE,

TRON_AND_VIDEO,

TRON,

VIDEO,

}

VideoMode vMode;

voidStart()

{

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.

EVRSettingsErrore=EVRSettingsError.None;

vartron_enabled=OpenVR.Settings.GetBool(

OpenVR.k_pch_Camera_Section,

OpenVR.k_pch_Camera_EnableCameraForCollisionBounds_Bool,

refe);

vMode=tron_enabled?VideoMode.TRON:VideoMode.NONE;

if(e!=EVRSettingsError.None)

{

Debug.LogError(e);

}

rightCtrl.MenuButtonClicked+=CtrlClicked;

leftCtrl.MenuButtonClicked+=CtrlClicked;

}

boolmenuPressed;

voidCtrlClicked(objectsender,ClickedEventArgse)

{

menuPressed=true;

}

voidUpdate()

{

if(menuPressed)

{

vMode=(VideoMode)(((int)vMode+1)%4);

SetVideoMode(vMode);

menuPressed=false;

}

}

voidSetVideoMode(VideoModem)

{

EVRSettingsErrore=EVRSettingsError.None;

switch(m)

{

caseVideoMode.NONE:

SetCameraVideo(false);

e=SetTronMode(false);

break;

caseVideoMode.TRON:

SetCameraVideo(false);

e=SetTronMode(true);

break;

caseVideoMode.VIDEO:

SetCameraVideo(true);

e=SetTronMode(false);

break;

caseVideoMode.TRON_AND_VIDEO:

SetCameraVideo(true);

e=SetTronMode(true);

break;

}

if(e!=EVRSettingsError.None)

{

Debug.LogError(e);

}

}

EVRSettingsError SetTronMode(boolenable)

{

EVRSettingsErrore=EVRSettingsError.None;

OpenVR.Settings.SetBool(OpenVR.k_pch_Camera_Section,

OpenVR.k_pch_Camera_EnableCameraForCollisionBounds_Bool,

enable,

refe);

OpenVR.Settings.Sync(true,refe);

returne;

}

voidSetCameraVideo(boolenable)

{

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.

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.