cgv
Loading...
Searching...
No Matches
VR support

Introduction to VR Support in CGV Framework

The VR support distributed over several libraries and plugins. The following list gives a brief overview:

  • <cgv/libs/vr>

    basic interface to implement vr apps that is independent of cgv framework and specific vr api. It builds on the concept of a driver that provides instances of vr kits and supports calibration through a calibration matrix. There can be several drivers in use at the same time. A simple registry is used to manage drivers and vr kits. The vr_kit class provides access to the display and the controllers with a simple state polling api.

  • <cgv/3rd/openvr>

    a copy of the openvr library such that it compiles within the build system of the framework. There is one change to support compilation with unicode characters under windows.

  • <cgv/plugins/openvr_driver>

    implements the vr interface for the openvr api. The only thing that needs to be done is to add the openvr_driver plugin as dependent project in the .pj-file.

    Currently, under windows steam vr changes the framebuffer type to non sRGB. Then the gamma correction needs to be set to 1.0f with cgv::render::context::set_gamma(1.0f) instead of the standard value of 2.2f. As this happens even if no vr device is attached.

    One can define the option CGV_OPTIONS=NO_OPENVR when one is not using a vr kit. Then openvr is not initialized by the openvr driver.

  • <cgv/test/vr>

    Plugin that implements a vr driver emulating one or several vr kits that can be controlled with keyboard. More information on its usage can be found in Emulation of Virtual VR Kits.

  • <cgv/plugins/cg_vr>

    This plugin connects <cgv/libs/vr> to <cgv/gui> by translating changes in the vr kit states into events dispatched though the cgv::gui::event_handler interface. The central class for this is cgv::gui::vr_server. Please see its documentation. VR events are declared in the cgv/plugins/cg_vr/vr_events.h header and marked with the cgv::gui::EF_VR event flag.

  • <cgv/plugins/crg_vr_view>

    This plugin extends the stereo_view_interactor class of the crg_stereo_view plugin with vr support to the vr_view_interactor class. It connects to the on_device_change signal of the cgv::gui::vr_server singleton and keeps track of device changes in order to initialize and destruct their framebuffers in the opengl context of the vr_view_interactor.

    It keeps a current vr_kit which can be selected with {Ctrl-Alt-0..3} or through the user interface. It can render vr kits with meshes and or with spheres representing eyes and controllers. If the meshes are not provided in the CGV_DATA path and in Debug configuration the sphere rendering is the default.

    Furthermore, the action zone boundaries can be rendered as a dashed fence. It can also debug all emitted vr events in the text console window. The vr_view_interactor manages its own view which can be controlled with the mouse as in the case of the stereo_view_interactor.

    Further rendering passes are issued to render from the views of the hmds of the present vr kits. The current vr kit states are queried with pose_query=2 for the currently selected vr kit and with pose_query=1 for the others. The rendered vr views are submitted to the hmds and can optionally blit in the current framebuffer. The queried states are dispatched in the cgv::gui::vr_server singleton with the cgv::gui::vr_server::check_new_state() function such that you should use the second or third option descripted in the detailed documentation of the cgv::gui::vr_server.

    The vr_view_interactor provides the following configuration methods:

    All vr events provide information on the state of the vr_kit that generated the event. Further convenience functions that can be called also during the draw process are

  • <cgv/plugins/vr_test>

    an advanced example of how to use the vr in the cgv framework that includes picking and grabbing of boxes through controller rays and a touch of the controller touchpad, offline text rendering to display an information board and rendering a polygonal mesh (currently the file name is hard coded and needs to be changed in the code to some local meshes)

Calibration of Tracking System

Each vr driver has an optional 3x4 matrix to transform all tracked poses. The transformation can be enabled with vr::vr_driver::enable_calibration_transformation() and disabled with vr::vr_driver::enable_calibration_transformation(). One can query the current transformation matrix with vr::vr_driver::put_calibration_transformation(). Setting the calibration matrix is restricted to classes derived from vr::vr_calibration_base.

Typically, one does not deal with the calibration matrix directly, but uses the functionality implemented in vr_view_interactor. To define the calibration matrix in a way that the coordinates of the tracking system align with the physical world, one follows the following procedure:

  1. find a point on a horizontal surface in physical space (table or ground) which has a corresponding point in your virtual scene
  2. place a controller upside on the horizontal surface pointing in a direction aligned with a physical edge that corresponds to a virtual edge.
  3. single click corresponding point in your virtual scene, such that the focus point of vr_view_interactor is set to the clicked point
  4. press {Shift-Ctrl-0..3} with the number key corresponding to the controller index (you can also use a tracker for calibration). Then vr_view_interactor sets its calibration location vectors and update and enable the calibration matrix of the current vr driver such that tracked position of the calibrated controller matches the position of the focus point in the virtual scene
  5. to adjust the rotation go to the [vr interactor] tab and open the [VR calibration] UI node. Adjust the [tracking_rotation] slider to match the 2D rotation of the virtual controller and the physical controller. The vr_view_interactor always updates the driver calibration matrix when this rotation angle is changed.
  6. When you are done with calibration, you can save the calibration to a file by pressing the save icon of [calibration_file_path]. Please choose .cal as extension.

To automatically read your calibration at program start add the following line to your .pj-file:

type(vr_view_interactor):calibration_file_path="D:/develop/table.cal"

Emulation of Virtual VR Kits

When you add the plugin <cgv/test/vr/vr_emulator.pj> to the list of dependent projects in your .pj-file:

addProjectDeps = [ ... , "vr_emulator", ... ];
addProjectDirs = [ ... , CGV_DIR."/test/vr", ... ];

the plugin automatically creates an instance of the vr_emulator class that generates a new tabgroup in the UI and handles keyboard shortcuts. You can configure the vr_emulator instance in your configuration file. See cgv/test/vr/config.def for a documented list of possible configurations, which include creation of vr kits at program start.

After program start you can create a new vr_kit with the shortcut {Ctrl-Alt-N}.

Each vr_kit is controlled by a very simple model of the human body that can move and turn, bend the hip forward/backward, turn the head left or right (yaw) and move each hand in a local 3D coordinate system with origin in the corresponding shoulder and oriented as the hip coordinate system.

To control the body model the vr_emulator allows to use the keys {0}, {1}, {2}, and {3} as modifier keys to control up to 4 vr_kits with the keyboard. The arrow keys allow to move and rotate. {PgUp} and {PgDn} control hip bending and {Home} and {End} yawing.

The controller keys of each kit are can be toggled with the following keys pressed while holding the modifier key ({0 .. 3}) of the vr kit:

  • {W} ... left menu button
  • {X} ... left grip button
  • {Q} ... left system button
  • {E} ... left A button
  • {A} ... left pad touch
  • {S} ... left pad press
  • {I} ... right menu button
  • {O} ... right grip button
  • {U} ... right system button
  • {B} ... right A button
  • {J} ... right pad press
  • {K} ... right pad touch

To make sure that all keys are dispatched by vr_emulator, select it for keyboard focus with the tab key or by selecting its tab group.

Application Development

The most convenient approach to use vr in a cgv application is through the plugin <cgv/plugins/crg_vr_view> which replaces the plugin <cgv/plugins/crg_stereo_view> of a none vr application. To get access to vr kits you need the plugin <cgv/plugins/openvr_driver> to use openvr and or <cgv/test/vr_emulator> to use the vr emulation. Finally, you need to include the libraries <cgv/libs/vr> and <cgv/libs/cg_vr>.

To implement your application main class, e.g. vr_viewer, derive it as usual from cgv::base::node, cgv::render::drawable, cgv::gui::event_handler, and optionally from cgv::gui::provider if you want to provide a classic UI.

You typically enable and configure VR in your drawable::init method by connecting the cgv::gui::vr_server singleton to the event processing of the main window and telling the cgv::render::vr_view_interactor instance which vr events should be generated and how the main rendering window should be configured. In <cgv/plugins/vr_test> you can find an example where the following code fragments are important:

{c++}
#include <cg_vr/vr_server.h>
#include <vr_view_interactor.h>
{
auto view_ptr = find_view_as_node();
if (view_ptr) {
vr_view_ptr = dynamic_cast<vr_view_interactor*>(view_ptr);
if (vr_view_ptr) {
vr_view_ptr->set_event_type_flags(
vr_view_ptr->enable_vr_event_debugging(true);
vr_view_ptr->draw_action_zone(false);
vr_view_ptr->draw_vr_kits(true);
vr_view_ptr->enable_blit_vr_views(true);
vr_view_ptr->set_blit_vr_view_width(200);
}
}
}
base class for all drawables, which is independent of the used rendering API.
Definition context.h:621
view * find_view_as_node(size_t view_idx=0) const
convenience function to find the view control in the current hierarchy
Definition drawable.cxx:49
bool init(cgv::render::context &ctx)
this method is called after creation or recreation of the context, return whether all necessary funct...
Definition vr_test.cxx:457
extends the stereo view interactor for vr support
void set_blit_vr_view_width(int width)
set the width with which vr views are blit
void draw_vr_kits(bool do_draw)
set whether to draw vr kits
void enable_vr_event_debugging(bool enable=true)
set whether vr events should be printed to the console window
void enable_blit_vr_views(bool enable)
enable vr view blitting
void draw_action_zone(bool do_draw)
whether to draw action zone
void set_event_type_flags(cgv::gui::VREventTypeFlags flags)
set the event type flags of to be emitted events
VREventTypeFlags
flags to define which events should be generated by server
Definition vr_server.h:27
@ VRE_POSE
pose events
Definition vr_server.h:36
@ VRE_ONE_AXIS_GENERATES_KEY
whether one axis events should generate a key event when passing inputs threshold value
Definition vr_server.h:34
@ VRE_TWO_AXES
pad / stick events
Definition vr_server.h:33
@ VRE_ONE_AXIS
trigger / throttle / pedal events
Definition vr_server.h:32
@ VRE_KEY
key events
Definition vr_server.h:31
@ VRE_STATUS
status change events
Definition vr_server.h:30
@ VRE_TWO_AXES_GENERATES_DPAD
whether two axes input generates direction pad keys when presses
Definition vr_server.h:35
@ VRE_DEVICE
device change events
Definition vr_server.h:29
void connect_vr_server(bool connect_device_change_only_to_animation_trigger, cgv::gui::window_ptr w)
connect the gamepad server to the given window or the first window of the application,...

For the includes you need to add the following include paths in your .pj file:

addIncDirs=[INPUT_DIR, CGV_DIR."/libs", CGV_DIR."/test"];

If you have enabled the device (cgv::gui::VRE_DEVICE) and status (cgv::gui::VRE_STATUS) events, you can set special callbacks to get informed of device changes and changes of the tracking and attachement status of hmds, controllers and trackers. This can already be prepared in your constructor:

{c++}
connect(cgv::gui::ref_vr_server().on_device_change, this, &vr_test::on_device_change);
connect(cgv::gui::ref_vr_server().on_status_change, this, &vr_test::on_status_change);
void on_status_change(void *kit_handle, int ci, vr::VRStatus old_status, vr::VRStatus new_status)
keep track of status changes
Definition vr_test.cxx:107
void on_device_change(void *kit_handle, bool attach)
register on device change events
Definition vr_test.cxx:128
vr_server & ref_vr_server()
return a reference to gamepad server singleton

These callbacks are implemented like this:

{c++}
#include <vr/vr_driver.h>
void vr_test::on_device_change(void* kit_handle, bool attach)
{
if (attach) {
vr::vr_kit* kit_ptr = vr::get_vr_kit(kit_handle);
:
}
}
void vr_test::on_status_change(void* kit_handle, int ci, vr::VRStatus old_status, vr::VRStatus new_status)
{
vr::vr_kit* kit_ptr = vr::get_vr_kit(kit_handle);
:
}
a vr kit is composed of headset, two controllers, and two trackers, where all devices can be attached...
Definition vr_kit.h:69
vr_kit * get_vr_kit(void *handle)
query a pointer to a vr kit by its device handle, function can return null pointer in case that no vr...
VRStatus
different status values for a trackable
Definition vr_state.h:85
defines the class vr::vr_driver class and gives access to the driver registry with the functions vr::...

The vr events are dispatched through your handle method and where you can ensure that you only process vr events by

{c++}
{
if ((e.get_flags() & cgv::gui::EF_VR) == 0)
return false;
:
}
unsigned get_flags() const
return the event flags
Definition event.cxx:214
bool handle(cgv::gui::event &e)
overload and implement this method to handle events
Definition vr_test.cxx:328
@ EF_VR
whether event is from VR kit
Definition event.h:35

For examples of how to process vr events please checkout <cgv/plugins/vr_test/vr_test.cxx>.

Device Information

To get device information of the vr kit and its attached controllers and trackers, the vr::vr_kit class provides the vr::vr_kit::get_device_info() function that stores all static device information. The information on controllers and trackers is filled when they are attached, what can change during program execution. Information on not attached controllers and trackers might be invalid. The attachment status can be tracked in the status events and is also accessible in all vr events through the get_state() function, e.g. cgv::gui::vr_key_event::get_state(). When browsing the documentation on the vr::vr_kit_info class, always check also the inheritance hierarchy as for example the serial number is available for all derived device classes from the vr::vr_device_info class.