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
#include <dgl.h>
#include
#include
<math.h>
bool go; vectorcube_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; }