Non-planar Tilesort Rendering

Typically, a tilesort configuration renders a physically (and logically) flat mural. That is, all the image tiles lie in the same plane. Chromium 1.6 and later supports non-planar tilesorting for applications such as virtual reality displays (such as the CAVE).

This discussion will focus on CAVE-like configurations in which there are two or more walls arranged around the user at right angles. Chromium is not limited to this arrangement, however; image tiles may be arbitrarily oriented.

Running a CAVE with Chromium

A CAVE system typically has two or three walls and a floor upon which video projectors display views of the virtual world. Usually, applications need to be modified to use the CAVE library before they can be run in a CAVE. Furthermore, a separate instance of the application may need to be running on each of the rendering hosts (they must be synchronized as well). With Chromium's non-planar tilesort feature, unmodified applications can be run in a CAVE (with some limitations).

Our approach is to use a Chromium server/render node to drive each video wall and run one instance of the application with a tilesort SPU. The Chromium configuration file specifies the size and orientation of each wall, the view frustums, etc.

Two levels of functionality (and complexity) are available:

  1. Run unmodified applications, but with no CAVE head tracking.
  2. Modify the application to support CAVE head tracking.

To summarize how things work:

First Example (cavetest1.conf)

The mothership/configs/cavetest1.conf file is a simple example of driving a CAVE-like system with Chromium. As is, all of the CAVE walls/views are displayed in windows on the local host. But this configuration file can be easily modified to support a real CAVE.

Here are the interesting bits of the cavetest1.conf file.

To run the cavetest1.conf demo, do the following:

By default, the city program is run. Other programs, such as atlantis may be run, but the configuration file may need some tweaking (fScale, farPlane, zTranslate, etc).

Second Example (cavetest2.conf)

The cavetest2.conf file illustrates how to render tiled walls. Suppose you wanted your CAVE walls to be 2048 x 2048 pixels driven by four projectors (four Chromium network/server nodes) each emitting a 1024 x 1024 image. This configuration file illustrates how one would accomplish that.

Notes:

To run the cavetest2.conf demo, do the following:

By default, the city program is run.

Third Example - Head Tracking

A CAVE equipped with head tracking hardware can adjust the projected images depending on the user's position inside the CAVE. Unfortunately, there's no way to achieve this effect without modifying the application code.

With Chromium, a call to the glChromiumParametervCR() function can be used to specify the per-server projection matrix from inside of the application, instead of in the Python configuration file.

The following code from the Chromium city demo illustrates how to set a unique projection matrix for each view (each network/server node).

static void MultiFrustum(void)
{
   int i;
   for (i = 0; i < NumViews; i++) {
      const float fSize = 1.1;
      GLfloat f[7];
      float eyex, eyez;
      float angle = (90.0 * i) * M_PI / 180.0; /* angle in radians */

      /* Each view is another 90 degree rotation about the Y axis */
      /* Compute the eye position in the rotated view */
      eyex = cos(angle) * EyeX - sin(angle) * EyeZ;
      eyez = sin(angle) * EyeX + cos(angle) * EyeZ;

      f[0] = i; /* the server */
      /* Skew the view frustum according to eye position (i.e. the
       * person's position in the cave.
       * XX This is also where we'd specify an interocular distance for stereo.
       */
      f[1] = -fSize - eyex;  /* left */
      f[2] =  fSize - eyex;  /* right */
      f[3] = -fSize - EyeY;  /* bottom */
      f[4] =  fSize - EyeY;  /* top */
      f[5] =  fSize - eyez;  /* near */
      f[6] = 100.0;          /* far */
      glChromiumParametervCR_ptr(GL_SERVER_FRUSTUM_CR, GL_FLOAT, 7, f);
   }
}

When the application detects a change in head position, the MultiFrustum() function would be called in place of the normal OpenGL code to specify the projection matrix.

The sample code above is meant to be used with the cavetest1.conf or cavetest2.conf example configurations. Specifically, each wall (server) is rotated 90 degrees from its neighbor. Each frustum is skewed according to the eye position within the CAVE.

The MultiFrustum() function is only example code and may need quite a few modifications to work in other applications.

The global variables EyeX, EyeY, EyeZ are the user's eye position within the CAVE.

The per-server projection matrix is set by calling glChromiumParametervCR(GL_SERVER_FRUSTUM_CR, GL_FLOAT, 7, m) where m[0] is the server index and m[1] through m[6] are the desired frustum left, right, bottom, top, near, far parameters.

Alternately, an arbitrary per-server projection matrix may be set by calling glChromiumParametervCR(GL_SERVER_PROJECTION_MATRIX_CR, GL_FLOAT, 18, m) where m[0] is the server index, m[1] is 0 or 1 indicating the left or right eye view (0 for non-stereo) and m[2] through m[17] are the sixteen elements of the projection matrix.

The per-server viewing matrix may also be set from within the application (instead of in the Python configuration file) by calling glChromiumParametervCR(GL_SERVER_VIEW_MATRIX_CR, GL_FLOAT, 18, m) where m[0] is the server index, m[1] is 0 or 1 indicating the left or right eye view (0 for non-stereo) and m[2] through m[17] are the sixteen elements of the viewing matrix.

NOTE: if you specify the projection or viewing matrices in the application with glChromiumParametervCR the Python configuration file should not set those matrices with the 'view_matrix' or 'projection_matrix' options.

The city demo, (run with either cavetest1.conf or cavetest2.conf) illustrates this technique. Press the x/X, y/Y and z/Z keys to translate the user/eye position within the CAVE.

To do: Stereo...