The Vrui FAQ

  1. What is this Vrui thing, anyway?
  2. How is Vrui different from, say, glut?
  3. How is Vrui different from Qt, Gtk+, etc.?
  4. How is Vrui different from Open SceneGraph, OpenSG, OSG, etc.?
  5. How is Vrui different from Ogre, Horde, Irrlicht, Sauerbraten, etc.?
  6. How is Vrui different from other VR toolkits like Cavelib, FreeVR, VR Juggler, etc.?
  7. On what operating systems does Vrui run?
  8. What is the difference between Vrui.cfg and VRDevices.cfg?
  9. How do I get started developing in Vrui?
  10. How do I receive input from the keyboard?
  11. How do I query the display resolution in points per inch etc.?

1. What is this Vrui thing, anyway?

Vrui (Virtual Reality User Interface) is a development toolkit for 3D graphics applications, with a strong focus on interactivity and immersive display environments. In the context of Vrui, immersive display environments mean displays consisting of one or more (large) stereoscopic screens, 3D head tracking, and 3D tracked input devices. Canonical examples of immersive display environments are CAVEs or head-mounted displays, and, more recently, those composed of 3D TVs, and gaming input devices.

Vrui's overriding goal is to support development of correct, portable, and usable applications. In this context, portable means that an application is developed in one environment – typically a desktop environment – but runs correctly in any environment. Usable means that a Vrui application run in a desktop environment is exactly as effective as a native desktop application, and that the same Vrui application run in a CAVE or other immersive environment type is exactly as effective as an application developed natively for that specific environment.

2. How is Vrui different from, say, glut?

In certain ways, Vrui is very much like glut. It allows writing graphics applications without having to worry about the details of the underlying hardware or graphics system, and introduces very little overhead when writing simple applications. Also, Vrui allows applications direct access to OpenGL, to employ custom low-level code. In many cases, Vrui is a more powerful replacement for glut. It has little enough overhead that it easily used for very simple applications, but at the same time already offers much additional functionality, such as simplified window management, multiple built-in 3D navigation metaphors, 3D measurement and annotation tools, virtual 3D input devices, recording and playback facilities, etc.

Unlike glut, Vrui is portable to non-desktop environments. Here, portable means that a Vrui application is only written once, and then runs in any environment, without even having to be recompiled. This portability is achieved by shielding application writers much more from the underlying display system as glut does: Vrui applications do not have to open their windows or set up their OpenGL rendering contexts, and they do not directly receive input from mouse or keyboard. In fact, handling of input is probably the biggest difference between Vrui and glut.

An additional difference between Vrui and glut is that Vrui consists of an entire hierarchy of layered libraries that work together to support developers in writing correct, portable, and usable applications. For example, Vrui contains a comprehensive cluster-transparent file I/O handling library, explicit high-performance intra-cluster communication, a comprehensive library for affine and projective 3D geometry, OpenGL support classes supporting generic programming, an OpenGL-based GUI widget set, and a scene graph library. While all these are completely optional, and Vrui is intentionally designed to be as compatible as possible with third-party libraries, developers are encouraged to use the highest-level available abstractions provided by the entire Vrui package.

3. How is Vrui different from Qt, Gtk+, etc.?

Qt, Gtk+, etc. are primarily 2D GUI toolkits, which also happen to offer widgets representing 3D graphics context for 3D rendering. Vrui, on the other hand, is primarily a 3D graphics toolkit, which also happens to offer widgets for (3D) GUIs. In other words, the GUI widget set is only a relatively small part of Vrui.

Ignoring everything else, though, the widget set offered by Vrui is comparable to those offered by Qt or Gtk+ or other 2D GUI toolkits, albeit not as complete (yet). Vrui's GUI widgets are three-dimensional, since they are intended to work in a virtual three-dimensional display space, but their functionality and layout is very similar to 2D GUI widgets. There are dialogs, menus, buttons, sliders, etc., just as usual. From a programming point of view, Vrui's GUI widgets more or less follow the approach of OSF/Motif, in that they primarily rely on automatic layout based on a hierarchical description, and on (C++-style) callbacks to connect widgets to application behavior. One could say that Vrui's widget set is a complete rip-off of OSF/Motif, translated to C++.

4. How is Vrui different from Open SceneGraph, OpenSG, OSG, etc.?

While Vrui contains a scene graph library, its primary focus is on providing direct access to the underlying OpenGL 3D graphics library for custom applications with specific rendering needs. It is also possible, albeit often difficult in practice, to layer an existing scene graph library on top of Vrui, for the added benefit of portability to non-desktop environments.

5. How is Vrui different from Ogre, Horde, Irrlicht, Sauerbraten, etc.?

Vrui is not a complete game engine, but a toolkit to develop correct, portable, and usable 3D graphics applications. Vrui does not address asset management, handling of 3D modeling data formats, view-dependent or multi-resolution rendering, advanced lighting, collision detection, game logic, artifical intelligence, etc. These aspects are delegated to application code, or to higher-level libraries, which could be part of Vrui itself (like the scene graph library), or developed by third parties.

In other words, Vrui is primarily a display and interaction engine, and comparable to the lower levels contained in any high-level game engine. As a result, given a game engine that has a clear separation of responsibilty between its layers, it can be possible to layer an existing game engine on top of Vrui, for the added benefit of being able to run that game engine in non-desktop environments. However, because most commercial or free game engines do not make this clear distinction, doing so might be difficult in practice.

6. How is Vrui different from other VR toolkits like Cavelib, FreeVR, VR Juggler, etc.?

VR toolkits like Cavelib, FreeVR, VR Juggler, etc. are decidedly low-level toolkits. They shield application developers from some aspects of the underlying display and input device hardware, but typically not enough to support truly portable or usable applications. In a certain way, the analogous comparison between Vrui and, say, Cavelib, in the desktop world is that between X Windows and an X-based GUI toolkit like Qt. While X hides differences in display and input device hardware, and even distribution to some extent, applications based directly on X have to contain their own GUI code. Before GUI toolkits became available, this really happened and resulted in completely different user interfaces between applications. One application might have used the middle mouse button to scroll; another might have used a proto-scroll bar; another might have used clicks into a "map" of scrollable space; in short, the situation was untenable.

GUI toolkits like Qt or Gtk+ remedied that problem by introducing a higher level. Instead of working with windows and mouse events, applications could now use "widgets" with specific purposes and widget events, leading to much better user interfaces, and, more important, consistent interfaces between applications.

Vrui attempts to do to immersive 3D graphics what Qt et al. did to 2D GUIs. It provides higher-level interfaces, to prevent individual applications from "reinventing the wheel," and instead foster consistent user interfaces. Instead of dealing directly with OpenGL windows and 4x4 matrices representing input devices, Vrui applications render into a toolkit-provided 3D application space, and receive higher-level events from input devices. As a concrete example, in other toolkits navigation, i.e., the mapping from 3D application space to display space, is handled by each application individually, whereas in Vrui it is handled by the toolkit. Overall, the result is that Vrui applications with widely differing purposes "look & feel" the same.

An intended side effect of Vrui's higher-level abstractions is that Vrui applications are portable between vastly different types of display environments. A single Vrui application will run in a CAVE like a native CAVE application, and will run on the desktop very similarly to a native desktop application. In comparison, other toolkits require applications to be developed for a narrower range of target environments, sometimes requiring different code for single-screen and multi-screen environments, and none that we are aware of support running applications on desktop environments in any way that is useful beyond basic debugging.

An additional difference is that Vrui consists of an entire hierarchy of layered libraries that work together to support developers in writing correct, portable, and usable applications. For example, Vrui contains a comprehensive cluster-transparent file I/O handling library, explicit high-performance intra-cluster communication, a comprehensive library for affine and projective 3D geometry, OpenGL support classes supporting generic programming, an OpenGL-based GUI widget set, and a scene graph library. While all these are completely optional, and Vrui is intentionally designed to be as compatible as possible with third-party libraries, developers are encouraged to use the highest-level available abstractions provided by the entire Vrui package.

For example, Vrui's underlying geometry library is used throughout Vrui's API instead of passing positions or orientations as flat 3- or 4-element arrays or 4x4 matrices. Vrui uses abstract geometry classes such as Point and Vector for affine points and vectors, respectively, and a hierarchy of abstract transformation classes from translations or rotations only over rigid body transformations to fully-general affine or projective transformations. All these classes have full sets of algebraic operations, which means application code can in almost all cases use them as black boxes. These higher-level classes significantly reduce the burden on application developers to either write their own algebraic operations, such as matrix inversion, or continuously convert back-and-forth between the toolkit's flat representation and the representation of a third-party geometry library they want to use. An intended side-effect of the use of higher-level abstractions at the API is that implicit constraints can be made explicit. For example, tracked 6-DOF input devices can only change position and orientation, and instead of representing those as generic projective transformations, i.e., 4x4 matrices, Vrui represents them as rigid-body transformations, i.e., a translation vector plus a unit quaternion. This makes arithmetic involving input devices easier, more efficient, and more robust. That said, all classes have methods to convert from/to flat array representations to be backwards-compatible with third-party libraries an application developer might want to use.

7. On what operating systems does Vrui run?

Vrui runs on UNIX-like operating systems. It is primarily being developed on Linux, specifically 64-bit Fedora Linux, but it builds and runs without problems on any other Linux distribution.

Vrui also builds and runs on Mac OS X, but there are currently some Linux-only features, particularly handling of sound and video, some non-standard required libraries –libpng, libjpeg, libtiff, libusb – that need to be installed from source or using software management systems such as homebrew, and Vrui is generally more thoroughly tested on Linux.

Vrui does not build on Windows. Microsoft's Visual C++, at least the most recent version tested, cannot deal with some of the C++ template constructs used in Vrui. Other C++ compilers, such as Intel's, can do those, but they are typically quite expensive. Even with a proper C++ compiler, several of the underlying architecture decisions in Vrui are deeply rooted in the UNIX paradigm. Porting Vrui would take significant initial effort, and continual effort to maintain a split codebase.

Vrui does build and run under UNIX emulation systems such as cygwin, but it will not be particularly useful because no version of cygwin we have tried offers hardware-accelerated 3D graphics. As Vrui applications rely heavily on high-performance graphics, they will barely be usable under cygwin.

The same problem applies if Linux is run inside a virtual machine. No virtual machine hypervisor we have tried offers hardware-accelerated 3D graphics inside the virtual machine, and Vrui applications will barely be usable as a result.

8. What is the difference between Vrui.cfg and VRDevices.cfg?

Vrui contains its own low-level device driver, VRDeviceDaemon, to talk to input device hardware such as 3D tracking systems, data gloves, wands, joysticks, etc. and convert their data streams into a unified format to be accepted by the Vrui toolkit run-time environment. This device driver is configured for a particular display environment via the VRDevices.cfg configuration file. This file defines what types of input device hardware are present, and how they work together in the same space.

The Vrui run-time environment itself is configured via the Vrui.cfg configuration file. This file defines the complete display environment, including the positions, orientations, and sizes of all screens, all viewers present in an environment, the OpenGL windows used to render 3D views to those screens, the number and types of 3D input devices presented by the low-level device driver, which tools are available, etc.

Concretely, VRDevices.cfg is read when the low-level device driver is started, whereas Vrui.cfg is read whenever a Vrui application is started. Both configuration files together define the complete set-up of the display environment in which Vrui runs, and need to be created and/or adapted carefully based on the details of a concrete environment. In a shared display environment like a CAVE, this task would typically fall to a dedicated system integrator / administrator, whereas configuration is more or less unnecessary in single-user desktop environments, where the default setup will cover the common cases.

9. How do I get started developing in Vrui?

Unfortunately, Vrui does not yet have comprehensive developer guides. As a prerequisite, developing for Vrui requires a good understanding of 3D graphics, especially of the OpenGL graphics library on which Vrui is based, and of C++. With these in place, starting Vrui developers are encouraged to think of Vrui as being very similar to glut, and take it from there. Vrui comes with a set of template or example applications showing the (little amount of) boilerplate code required to set up a Vrui application, and detailed comments explaining where one would put application and 3D rendering code, for example. If a developer has code for a glut application, it is usually enough to strip out any OpenGL setup and viewpoint navigation code (OpenGL setup and navigation are handled by Vrui), paste the rest into the simplest Vrui template, and compile that to get a working Vrui application.

After these initial steps, developers are encouraged to use several existing Vrui applications to see how they look and feel, especially as they are run in different display environment types, and then peruse the HTML documentation that does exist. A good starting point is the "Library Overview" section, which lists the component library layers that make up the whole Vrui package, and in turn list all the header files and classes contained in those libraries. The interfaces of all those classes are defined in their respective header files, including detailed comments on all interface methods and functions.

Another important starting point is the Vrui kernel API in include/Vrui/Vrui.h, which declares all core functions applications use to communicate with Vrui. Due to Vrui's microkernel architecture, most of its functionality is not provided by the kernel itself, but by delegate classes such as Vrui::VRWindow, or by external so-called managers such as the input device manager. References to these managers are retrieved through the kernel API, but afterwards applications communicate directly with those managers. The bottom line is that all of Vrui's functionality is accessed through the kernel API, either directly or indirectly via managers or delegate classes.

While the low-level documentation of classes and interfaces provided by the source code comments are reportedly rather good, they don't tell in which scenarios a developer might use a certain class. This will hopefully be addressed by higher-level development guides in the near future. In the meantime, another important resource is the "Development Rules" document, which lists common pitfalls stemming from Vrui's difference in philosophy to other VR or 3D graphics toolkits, and its focus on portability and usability. For example, the way Vrui applications are supposed to handle user input is Vrui's one feature most distinct from other toolkits.

10. How do I receive input from the keyboard?

You don't. No, really. Unlike glut et al., Vrui aims to support environment-independent applications, and non-desktop environments do not have keyboards. As a result, Vrui applications receive input in a very different manner than, say, glut applications. Instead of directly receiving events from the keyboard (or the mouse) via dedicated callbacks, Vrui applications receive events from so-called tools, which in turn receive events from actual input devices.

To use a concrete example, assume an application that wants to do something when the user presses a specific key. In glut et al., this would be handled by registering a keyboard event callback, which will in turn check the identity of the just-pressed key when called, and invoke the proper application behavior if the desired key is pressed. In Vrui, application behaviors are implemented as tools. If an application has some behavior X that is to be invoked when some key is pressed, the developer would create a corresponding tool class X and hand it to Vrui's tool manager during start-up. After that, a user can dynamically bind a tool object of class X to any button she desires; after that, if she presses that button, the bound tool object will be called, and can in turn invoke behavior X.

While this approach sounds more complicated, it has important benefits. For one, it works in non-desktop environments. Even if there is no keyboard, there will still be some input device that has some ways to signal that a user wants to initiate an event (which could be an actual button, or a gesture, or a voice command, etc.), and Vrui's dynamic tool binding mechanism allows the user to bind a tool of class X to any such event source, without the application developer having to code any support for that. Even if constrained to the desktop, this allows users to map application behaviors to any keys they desire – in other words, the keyboard remapping functionality common in PC games comes for free in Vrui.

Additionally, in actual code, setting up a tool is no more complicated than writing a callback. For simple cases like the one above, where a key press invokes some behavior, Vrui offers a convenience shortcut that creates a tool class, passes it to Vrui's tool manager, handles dynamic binding, and invokes an arbitrary application callback when an event happens, in a single line of code. Only in more complex cases, such as when behaviors require their own internal states, will a developer have to implement an actual tool class, which would be essentially the same in other toolkits as well.

11. How do I query the display resolution in points per inch etc.?

You don't. Due to Vrui's portability, an application might not have a display, might have multiple displays with different resolutions, or might have an immersive display, where display resolution is not an applicable concept. In Vrui, only very specific applications, such as calibration utilities, would need to know anything about display resolution. In almost all cases, the actual functionality for which a developer would like to know the display resolution can be achieved in a more direct way. One common example is scaling: a developer wants to be able to display 3D data at fixed scales (1:1, 1:100) such that images on the display can be measured. This is supported directly in Vrui: if an application tells Vrui which unit of measurement is used by an application, it will provide an interactive scale bar that shows the exact scale factor from application to real world, and means to adjust the scale factor to common fixed values, such as 1:1.

Another common example is an application needing to know how big to make a display, like a text label, or how big to make the influence zone around an interaction event, based on display resolution. In Vrui, these parameters are configured by the system integrator/administrator appropriately for a concrete environment, and can be queried directly via the Vrui kernel API.

In other words, Vrui applications should always render in 3D application space in any unit of measurement they want, advertise that unit to Vrui's coordinate manager, and let Vrui take care of the rest. Any questions about appropriate display sizes, interaction fuzz values, optimal font sizes, etc. should be answered by querying the Vrui kernel API whenever needed.