FreeVR Library Programming Tutorial (w/ OpenGL)
The FreeVR Library will be used to exemplify many VR interface and
programming techniques.
FreeVR will work in most local VR facilities (eg. CAVE™ or Head-Based-Display),
as well as on the available desktop machines in a simulated-VR mode.
It can be used on PC's with Linux and OpenGL installed, or
in a (currently very) limited way on PC's with Cygwin installed.
The FreeVR webpage is www.freevr.org.
This tutorial takes the approach of starting with an extremely simple initial
example and then advancing in very small increments (baby steps) until we can
perform some interesting tasks in virtual reality.
Another point to make about this tutorial is that it is not intended as a
means to learn advanced OpenGL programing.
The computer graphics in these examples are all very simple.
The goal of the tutorial is to highlight programming tasks that are unique
to programming for a virtual reality system.
On the other hand, some basic OpenGL techniques can be learned by following
this tutorial, as it will show how to handle texture maps, billboards,
cutting planes, and moveable lights.
Other tutorials are under development for interfacing FreeVR to additional
rendering and world simulation systems.
Presently there is a tutorial available for the SGI Performer scene-graph
library, but as Performer has greatly decreased in usage new tutorials
will cover similar, but more popular libraries.
This tutorial has been most recently tested with FreeVR version 0.6a.
Part 2: Examples 6 - 11
Now that we know the basics about creating simple VR experiences, and
have done the mildly interesting task of moving an object about through
physical inputs, we will continue the tutorial of OpenGL FreeVR programs by
introducing how to let participants manipulate objects in the virtual
world through the "direct manipulation" method of control.
We will also look at providing a means of communicating to the user
through very simple text output, and we will begin to explore the
use of the FreeVR locking mechanism to ensure the safty of the
world database.
Each example links to a copy of the source code
(and the difference from the previous example)
.
The examples can be compiled with one or more of the following additional
files:
Example 6: Very simple output — 2D text (ex6)
Text rendering is often useful as part of the user interface,
or for debugging applications.
This example introduces a very basic way of adding text into the
rendering of the virtual world.
It is not the best method for most circumstances, but will serve
to get us started.

- The FreeVR Library provides:
- vrRenderText() — Render a string as 2D text in
the virtual world.
- vrRenderInfo — an internal FreeVR structure that
provides a conduit for information through the rendering
routine.
- This example provides our first exposure to the vrRenderInfo type.
This FreeVR internal structure contains information about the current
rendering state.
This state information is not directly useful for the application
programmer, but it is required by some of the functions that will
be called by the render routine — such as the vrRenderText()
function used in this example.
Thus, the new argument to the render routine which is then passed
directly to the FreeVR render helper functions can be thought of a
a conduit for the render state information.
- NOTE: 2D raster text is sub-optimal for rendering 3D worlds.
Especially when the user can change their relative view of
the text. It is always displayed parallel to the bottom of
the screen, and always at a constant size.
The result is that as the text moves relative to the user
it will have the appearance of changing in size.
This effect is the result of the text remaining a constant
physical size, while the rest of the virtual world will be
changing in response to user movement.
The relative changes between the text and the rest of the
virtual world are what produce the appearance of the text
growing and shrinking.
One way to circumvent this issue, is to affix the text to the
physical location of one of the screens.
Since the relationship between the screen and the user
is always physically matched between the virtual and real
worlds, the text will always be rendering correctly.
- NOTE also: the OpenGL lighting model is disabled during the rendering
of the text. This is to keep the text rendered as a bright white,
rather than the dimmer color that would occur due to only being
partially illuminated by the lights in the scene.
- Example 6 (ex6_text.c) code
shows how to render simple 2D text.
- There are minor
differences between ex5 and ex6.
Example 7: A virtual pointer & Coordinate Systems (ex7)

- One of the more difficult aspects of VR programming is
dealing with coordinate systems.
- There is a coordinate system (CS) for the real world,
the tracking system, each screen,
the virtual world, the head, the hand, each eye, etc.
- The FreeVR Library provides some relief:
- vrRenderTransform6sensor() — adds a matrix to the
OpenGL matrix stack that moves (transforms) from the
world coordinate system to the coordinate system of
the given sensor.
- This function is called in the application's drawing routine.
- Example 7 (ex7_pointer.c) uses
vrRenderTransform6sensor() to render a (long, cyan) pointer
"attached" to the wand.
- There are minor
differences between ex6 and ex7.

Example 8: Objects with behavior & using vectors (ex8)
Objects that move on their own can make for a more interesting virtual world.
In this example, we use the direction the wand is pointing (a 6sensor input)
to affect the direction of a small projectile.

The wand will be used to shoot a small yellow cube.
Once the cube is shot, it continues to move on its own.
This example introduces a new type and two new functions:
- vrVector — a structure with a three element array
storing a direction.
Field "v" is an array of doubles.
- vrVectorGetRWFrom6sensorDir() — gets the direction
a 6-dof sensor is pointing relative to the real world.
The result is a vrVector.
- vrGet2switchDelta() — gets the change in value
between now, and the last time this function was called
for the given input.
Thus, a 2-switch can return:
- -1: switch was just released,
- 0: switch has not changed, and
- 1: switch was just pressed.
Example 8 (ex8_shoot.c)
lets the user shoot a small yellow cube.
There are minor
differences between ex7 and ex8.
Example 9: Object Selection (ex9)
- Before we can manipulate an object, we need to specify which one.
- By determining where the wand is, we can put it to use.
- The FreeVR Library helps with:
- vrPointGetRWFrom6sensor() — tells us where things are
in virtual space.
- vrPoint type — stores an X,Y,Z location as an array
in field "v".
Note: in the example code, a #define is used to treat the
vrPoint.v field as a simple array named "wand_location".
- Example 9 (ex9_contact.c)
lets the user select one of the objects in the virtual world.
- There are minor
differences between ex8 and ex9.
- This form of selection is called "selection by contact."

Example 10: Manipulating the world (ex10)
- Doing something with the selected object.
- We will once again use the FreeVR function:
- vrGet2switchValue() — a user controlled input variable
- With this we can tell the world simulation when we want the
object to mimic our movement.
- Example 10 (ex10_manip.c)
does just that.
- There are minor
differences between ex9 and ex10.

Example 11: Using Locks to Safeguard the Code (ex11)
- Locking code is added to remove the potential for bugs that can occur
when one process is writing to the same memory from which another
is simultaneously reading.
- The FreeVR Library provides:
- vrLockCreate() — Create a new vrLock
- vrLockWriteSet() — Prevent other code fragments
bound by this lock from reading or writing to the
associated memory.
- vrLockWriteRelease() — Allow other code fragments
bound by this lock to access the associated memory.
- vrLockReadSet() — Prevent other code fragments
bound by this lock from writing to the associated memory.
NOTE: other reading threads are permissible.
- vrLockReadRelease() Allow other code fragments
bound by this lock free access the associated memory.
- With the use of locks, it is sometimes more efficient to store
information from shared memory in a local variable to reduce
the number of times locking is required.
- Example 11 (ex11_locks.c) code
shows how to do read and write locking.
- There are minor
differences between ex10 and ex11.
Last modified 10 January 2010.
Bill Sherman, shermanw@indiana.edu
© Copyright William R. Sherman, 2010.
All rights reserved.
In particular, republishing any files associated with this tutorial
in whole or in part, in any form (included electronic forms)
is prohibited without written consent of the copyright holder.
Porting to other rendering systems is also prohibited without
written consent of the copyright holder.