Simple DGL Examples:

The first example shows a static ball drawn in the center of the CAVE.

Here is the code that comprises this program, with brief explanations:

#include <stdlib.h> 
#include <signal.h>
#include <GL/gl.h> 
#include <GL/glu.h>
#include <dtk.h>
#include <dtkX11.h>
#include <dgl.h>
#include <dglX11.h>
#include <math.h>

#define SPHERE 4
#ifndef PI
#define PI 3.141592654
#endif

struct XYZ
{
  float x;
  float y;
  float z;
};

bool go;
GLdouble x=0, y=0, r=0.3, x2=0, y2=0;
GLuint i=0, i2=0, step=0;

static float material_red[] = {1.f, 0.f, 0.f, 1.f};

void signal_catcher(int sig)
{
  go = false;
}

// This is largest part of the program--the routine to draw the sphere itself. Since DGL does not yet draw gluObjects (like sphere) the sphere must be drawn from scratch

void CreateSphere(XYZ c,double r,int n)
{
   int i,j;
   double theta1,theta2,theta3;
   XYZ e,p;

   glNewList(SPHERE, GL_COMPILE);
   if (r < 0)
      r = -r;
   if (n < 0)
      n = -n;
   if (n < 4 || r <= 0) 
     {
      glBegin(GL_POINTS);
      glVertex3f(c.x,c.y,c.z);
      glEnd();
      return;
     }

   for (j=0;j=n;i++) {
         theta3 = i * 2*PI / n;
	 
         e.x = cos(theta2) * cos(theta3);
         e.y = sin(theta2);
         e.z = cos(theta2) * sin(theta3);
         p.x = c.x + r * e.x;
         p.y = c.y + r * e.y;
         p.z = c.z + r * e.z;

         glNormal3f(e.x,e.y,e.z);
         glTexCoord2f(i/(double)n,2*(j+1)/(double)n);
         glVertex3f(p.x,p.y,p.z);

         e.x = cos(theta1) * cos(theta3);
         e.y = sin(theta1);
         e.z = cos(theta1) * sin(theta3);
         p.x = c.x + r * e.x;
         p.y = c.y + r * e.y;
         p.z = c.z + r * e.z;
	 
         glNormal3f(e.x,e.y,e.z);
         glTexCoord2f(i/(double)n,2*j/(double)n);
         glVertex3f(p.x,p.y,p.z);
       }
       glEnd();
     }
   
   glEndList();
}

// DGL has several main callback routines. The initial callback, which has definitions of objects drawn--lighting, material, etc. This is called before any drawing takes place in function main(), and the main drawing callback display_callback which is called repeatedly and redrawn. DGL also can create other drawing threads, but I have not made use of them here.


void gl_init_callback(const dglDisplayInfo *info, void *data)

{
  unsigned int index = info->thread->threadNumber();

  XYZ a;
  
  a.x=0.0;
  a.y=0.0;
  a.z=0.0;

  CreateSphere(a, r, 20);

  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glShadeModel(GL_SMOOTH);
}

// The main drawing function


void display_callback(const dglDisplayInfo *info, void *data)

{
 
  static float light_ambient[]   = {.5f, .5f, .5f, 1.f};
  static float light_diffuse[]   = {.5f, .5f, .5f, 1.f};
  static float light_direction[] = {0.f, -1.f, 1.f, 0.f};

  unsigned int index = info->thread->threadNumber();


  glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light_direction);

  glPushMatrix();
  glNormal3f(0.f, -1.f, 0.f);
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_red);
  glTranslatef(0.f, 1.0, 0.f);

// Draw that sphere
glCallList(SPHERE);

  glPopMatrix();

}

int main(int argc, char **argv)
{

// Catch all keyboard signals
signal(SIGINT, signal_catcher);

  signal(SIGTERM, signal_catcher);
  go = true;

// Create a new manager object
dglManager *manager = new dglManager();

  if (!manager || manager->isInvalid()) {
    printf("Could not create a valid manager.\n");
    return EXIT_FAILURE;
  }

  manager->initGLCallback(gl_init_callback, NULL);
  manager->displayCallback(display_callback, NULL);
  manager->config();
  
  dglDisplay *display = manager->display(0);
  if (!display || display->isInvalid()) {
    printf("Could not find a valid display object.\n");
    return EXIT_FAILURE;
  }
  display->clearBuffers(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  display->coordSystem(dglDisplay::NAVIGATED_NDC_COORDS);

  while (go && (manager->state & DTK_ISRUNNING)) {
    manager->sync();
    manager->frame();
  }

  delete manager;

  return EXIT_SUCCESS;
}

The majority of the code should be fairly straightforward, look for more detailed documentation on DGL. The next example is virtually identical, but uses a simple bounce routine to add motion to the ball and simulate it bouncing off the CAVE walls. Another difference are those snazzy blue lines drawn on the floor, borrowed from DGL's creator---Chris Logie.


#include <stdlib.h>
#include <signal.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <dtk.h>
#include <dtkX11.h>
#include <dgl.h>
#include <dglX11.h>
#include <math.h>

bool go;
vector cube_list(16);
vector square_list(16);

#define SPHERE 4
#ifndef PI
#define PI 3.141592654
#endif


struct XYZ
{
  float x;
  float y;
  float z;
};

static float material_red[]     = {1.f, 0.f, 0.f, 1.f};
static float material_green[]   = {0.f, 1.f, 0.f, 1.f};
static float material_blue[]    = {0.f, 0.f, 1.f, 1.f};
static float material_white[]   = {1.f, 1.f, 1.f, 1.f};
static float material_cyan[]    = {0.f, 1.f, 1.f, 1.f};
static float material_magenta[] = {1.f, 0.f, 1.f, 1.f};
static float material_yellow[]  = {1.f, 1.f, 0.f, 1.f};
static float material_black[]   = {0.f, 0.f, 0.f, 1.f};

GLdouble x=0, y=0, r=0.1, x2=0, y2=0;
GLuint i=0, i2=0, step=0;

XYZ pos;

float posxacc = .02;
float posyacc = .01;
float poszacc = .03;

float bounceang = 0;

void signal_catcher(int sig)
{
  go = false;
}


void SimpleBounce()
{
  

  if (pos.x >= 1 || pos.x <= -1)
    {
      posxacc *= -1;
    }

  if (pos.y >= 1 || pos.y <= -1)
    {
      posyacc *= -1;
    }
  
  if (pos.z >= 1 || pos.z <= -1)
    {
      poszacc *= -1;
    }

  pos.x += posxacc;
  pos.y += posyacc;
  pos.z += poszacc;

  glTranslatef(pos.x, pos.y, pos.z);

}
  
  
void CreateSphere(XYZ c,double r,int n)
{
   int i,j;
   double theta1,theta2,theta3;
   XYZ e,p;

   glNewList(SPHERE, GL_COMPILE);
   if (r < 0)
      r = -r;
   if (n < 0)
      n = -n;
   if (n < 4 || r <= 0) 
     {
      glBegin(GL_POINTS);
      glVertex3f(c.x,c.y,c.z);
      glEnd();
      return;
     }

   for (j=0;j=n;i++) {
         theta3 = i * 2*PI / n;
	 
         e.x = cos(theta2) * cos(theta3);
         e.y = sin(theta2);
         e.z = cos(theta2) * sin(theta3);
         p.x = c.x + r * e.x;
         p.y = c.y + r * e.y;
         p.z = c.z + r * e.z;

         glNormal3f(e.x,e.y,e.z);
         glTexCoord2f(i/(double)n,2*(j+1)/(double)n);
         glVertex3f(p.x,p.y,p.z);

         e.x = cos(theta1) * cos(theta3);
         e.y = sin(theta1);
         e.z = cos(theta1) * sin(theta3);
         p.x = c.x + r * e.x;
         p.y = c.y + r * e.y;
         p.z = c.z + r * e.z;
	 
         glNormal3f(e.x,e.y,e.z);
         glTexCoord2f(i/(double)n,2*j/(double)n);
         glVertex3f(p.x,p.y,p.z);
       }
       glEnd();
     }
   
   glEndList();
}



void gl_init_callback(const dglDisplayInfo *info, void *data)
{
  unsigned int index = info->thread->threadNumber();

  XYZ a;

  pos.x = 0.0;
  pos.y = 0.0;
  pos.z = 0.0;

  a.x=0.0;
  a.y=0.0;
  a.z=0.0;

  CreateSphere(a, r, 20);

  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glShadeModel(GL_SMOOTH);
   
  square_list[index] = glGenLists(1);
  glNewList(square_list[index], GL_COMPILE);
  glBegin(GL_QUADS);
  glNormal3f(0.f, 0.f, 1.f);
    glVertex3f(-0.5f, -0.5f, 0.0f);
    glVertex3f( 0.5f, -0.5f, 0.0f);
    glVertex3f( 0.5f,  0.5f, 0.0f);
    glVertex3f(-0.5f,  0.5f, 0.0f);
  glEnd();
  glEndList();
}


void display_callback(const dglDisplayInfo *info, void *data)
{
  static float theta = 0.1f;
  static float light_ambient[]   = {.5f, .5f, .5f, 1.f};
  static float light_diffuse[]   = {.5f, .5f, .5f, 1.f};
  static float light_direction[] = {0.f, -1.f, 1.f, 0.f};

  unsigned int index = info->thread->threadNumber();

  theta += 0.1f;
  if (theta > 360.0f) theta -= 360.f;

  glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light_direction);

  glPushMatrix();
  glNormal3f(0.f, -1.f, 0.f);
  glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_red);
  glTranslatef(0.f, 0.7, 0.f);
  SimpleBounce();
  glCallList(SPHERE);
  glPopMatrix();

  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  for (float x=-1.5f; x < 2.f; x+=1.f) {
    for (float y=-1.5f; y < 2.f; y+=1.f) {
      glPushMatrix();
        glTranslatef(x, y, -1.f);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_blue);
	glCallList(square_list[index]);
      glPopMatrix();
    }
  }

  for (float x=-5.f; x<6.f; x+=2.f) {
    glPushMatrix();
      glTranslatef(x, 3.f, -1.f);
      glScalef(2.f, 2.f, 2.f);
      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_blue);
      glCallList(square_list[index]);
    glPopMatrix();
    glPushMatrix();
      glTranslatef(x, -3.f, -1.f);
      glScalef(2.f, 2.f, 2.f);
      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_blue);
      glCallList(square_list[index]);
    glPopMatrix();
  }

  for (float y=-1.f; y<2.f; y+=2.f) {
    glPushMatrix();
      glTranslatef(3.f, y, -1.f);
      glScalef(2.f, 2.f, 2.f);
      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_blue);
      glCallList(square_list[index]);
    glPopMatrix();
    glPushMatrix();
      glTranslatef(-3.f, y, -1.f);
      glScalef(2.f, 2.f, 2.f);
      glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_blue);
      glCallList(square_list[index]);
    glPopMatrix();
  }
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);


}

int main(int argc, char **argv)
{
  signal(SIGINT, signal_catcher);
  signal(SIGTERM, signal_catcher);
  go = true;

  dglManager *manager = new dglManager();

  if (!manager || manager->isInvalid()) {
    printf("Could not create a valid manager.\n");
    return EXIT_FAILURE;
  }

  manager->initGLCallback(gl_init_callback, NULL);
  manager->displayCallback(display_callback, NULL);
  manager->config();
  
  dglDisplay *display = manager->display(0);
  if (!display || display->isInvalid()) {
    printf("Could not find a valid display object.\n");
    return EXIT_FAILURE;
  }
  display->clearBuffers(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  display->coordSystem(dglDisplay::NAVIGATED_NDC_COORDS);

  while (go && (manager->state & DTK_ISRUNNING)) {
    manager->sync();
    manager->frame();
  }

  delete manager;

  return EXIT_SUCCESS;
}