Build a Simple OpenVR application

OpenVR is an API and runtime that allows access to VR hardware from multiple vendors without requiring applications to have specific knowledge of the hardware they are targeting. This repository is an SDK that contains the API and samples. The runtime is under SteamVR in Tools on Steam.

This article describes the necessary steps you should follow to build, load, and run a simple WaveEngine application on the OpenVR platform.

OpenVR pre requisites

  • You should install SteamVR from your Steam library.
  • Setup your VR device (HTC Vive for instance) and the room environment.


Create a VR Camera

In this step, you will learn how to create a stereo VR Camera, which will render the scene into the headset.

WaveEngine has included a set of components that allows creating a Stereo Camera regardless of the VR technology used (OpenVR, Oculus, Google Cardboard…).

  1. First of all, we start creating an Empty Entity 3D. This action will create an Entity that only has a Transform3D component:
  2. Add the VRCameraRig component to the previously created entity. This component is responsible for creating the stereo camera configuration:
    The VRCameraRig component creates a hierarchy to its own entity:

VR Camera hierarchy

This hierarchy is used to maintain a stereo camera 3D system, that allows you to draw each eye separately and helps developers know where every special feature is located (eyes, position tracker, etc…).


A brief overview of the VR hierarchy:

  • TrackingSpace. This is a single entity with a Transform3D component. It allows you to adjust the VR tracking space to the app requirements. For example, by default, all tracking position units given by Oculus are measured in meters, so if you want to use centimeters instead of meters, you only need to scale the TrackingSpace entity 100 times (Transform3D.LocalScale  = new Vector3(100, 100, 100)).
    • LeftEyeAnchor. This is the left eye camera entity. Always coincides with the position of the left eye.
    • RightEyeAnchor. This is the right eye camera entity. Always coincides with the position of the right eye.
    • CenterEyeAnchor. This entity is placed in the average location between the left and right eye position. This entity is commonly used to know the “head” position.
    • LeftControllerEntity. This entity coincides with the left controller entity. It has a VRController component instance, that provides its state information.
    • RightControllerEntity. This entity coincides with the right controller entity. It has a VRController component instance, that provides its state information.
    • TrackerAnchor. A simple entity (only contains a Transform3D), that is placed in the location of the position tracker camera.

VRCameraRig component

The VRCameraRig component is responsible for controlling the stereo camera system. It has the following properties:

  • Monoscopic. If true, the eyes see the same image, this option disables the 3D stereoscope.
  • VRMode. This flag specifically enables the way a stereo camera will be rendered. It has the following values:
    • HmdMode. Both eyes will be rendered into the headset. This is the default value.
    • AttachedMode. Render only one eye (Center eye) and nothing is rendered into the headset. This mode is useful for debugging purposes.
    • All. Both modes are rendered at the same time (Both eyes in the headset and the center eye is in the application window).

VRController component

Each Controller entity has the VRController component. It has the following configuration:

  • ControllerRole. It indicates if this controller is associated with the Right or Left hand. You have a third option called Undefined:
    • ControllerIndex. If you specify the Undefined controller role, you could specify the controller index which you want to track.
  • TrackingLostMode. Specify how this entity behaves if the controller tracking pose is lost.
  • State. This is a property that gives the input state of the controller. It uses the VRGenericControllerState structure to provide the controller state.


This structure represents a generic abstraction of  the input state of a VR Controller:

The following input properties are mapped:

  • Trigger. Gives a float value of the amount
    • TriggerButton. When the trigger is pressed.
  • ThumbStick. Vector2 that indicates the direction of this stick.
    • ThumbStickButton. When the thumbstick is pressed.
  • Menu. Buttons usually used to show your application menu.
  • Grip. This button is commonly used to grip objects.
  • Button1. First app specific button.
  • Button2. Second app specific button.

HTC Vive Controllers input map

Oculus Touch Controllers input map

OpenVR integration

The VRCameraRig creates the stereoscopic camera entity hierarchy, but it is VR platform agnostic, so this is designed to work for another VR platforms (like Oculus Rift, HoloLens, Cardboard…).

The OpenVR integration can be done in the following steps:

  1. Install WaveEngine.OpenVR NuGet package into your Game Windows solution.
  2. Change the Application type of your game. Open the App.cs file, which is located into your Windows launcher project, and let the App class to extend the OpenVRApplication. This allows you to configure your application to render inside the Oculus Rift headset:
    • Find the following line:
      public class App : WaveEngine.Adapter.Application
    • And replace the base class by OculusVRApplication:
      public class App : OpenVRApplication
  3. Add the OpenVRProvider component to your camera rig entity (the entity that has the VRCameraRig component). This component is responsible for updating the VRCameraRig entities with the OpenVR headset information and configures the cameras to render inside the OpenVR headset (HTC Vive for instance).

After that, try to put some models into your scene, and place the camera rig entity into your desired head position (in that case we put the helicopter cockpit model, and we place the camera rig entity inside the cockpit):

And when you execute your application, you will see your first awesome Oculus Rift example!


Leave a Reply

Your email address will not be published. Required fields are marked *