#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <GL/glut.h>
/*
Demonstration OpenGL application
Create a model of a pulsar
*/
typedef struct {
double x,y,z;
} XYZ;
typedef struct {
double r,g,b;
} COLOUR;
typedef struct {
unsigned char r,g,b,a;
} PIXELA;
typedef struct {
XYZ vp; /* View position */
XYZ vd; /* View direction vector */
XYZ vu; /* View up direction */
XYZ pr; /* Point to rotate about */
double focallength; /* Focal Length along vd */
double aperture; /* Camera aperture */
double eyesep; /* Eye separation */
} CAMERA;
void Display(void);
void CreateEnvironment(void);
void MakeGeometry(void);
void MakeLighting(void);
void HandleKeyboard(unsigned char key,int x, int y);
void HandleSpecialKeyboard(int key,int x, int y);
void HandleMouse(int,int,int,int);
void HandleMainMenu(int);
void HandleSpeedMenu(int);
void HandleSpinMenu(int);
void HandleVisibility(int vis);
void HandleReshape(int,int);
void HandleMouseMotion(int,int);
void HandleIdle(void);
void GiveUsage(char *);
void RotateCamera(int,int,int);
void TranslateCamera(int,int);
void CameraHome(int);
void Normalise(XYZ *);
XYZ CalcNormal(XYZ,XYZ,XYZ);
int WindowDump(int,int,int);
#define ABS(x) (x < 0 ? -(x) : (x))
#define MIN(x,y) (x < y ? x : y)
#define MAX(x,y) (x > y ? x : y)
#define TRUE 1
#define FALSE 0
#define ESC 27
#define PI 3.141592653589793238462643
#define DTOR 0.0174532925
#define RTOD 57.2957795
#define CROSSPROD(p1,p2,p3) \
p3.x = p1.y*p2.z - p1.z*p2.y; \
p3.y = p1.z*p2.x - p1.x*p2.z; \
p3.z = p1.x*p2.y - p1.y*p2.x
/* Flags */
int fullscreen = FALSE;
int stereo = FALSE;
int showconstruct = FALSE;
int windowdump = FALSE;
int debug = FALSE;
int screenwidth=800,screenheight=600;
int currentbutton = -1;
double rotatespeed = 1;
double dtheta = 1;
CAMERA camera;
XYZ origin = {0.0,0.0,0.0};
double rotateangle = 0.0; /* Pulsar Rotation angle */
int main(int argc,char **argv)
{
int i;
int mainmenu,speedmenu,spinmenu;
/* Parse the command line arguments */
for (i=1;i<argc;i++) {
if (strstr(argv[i],"-h") != NULL)
GiveUsage(argv[0]);
if (strstr(argv[i],"-f") != NULL)
fullscreen = TRUE;
if (strstr(argv[i],"-s") != NULL)
stereo = TRUE;
if (strstr(argv[i],"-d") != NULL)
debug = TRUE;
if (strstr(argv[i],"-c") != NULL)
showconstruct = TRUE;
}
/* Set things up and go */
glutInit(&argc,argv);
if (!stereo)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
else
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STEREO);
glutCreateWindow("Pulsar model");
glutReshapeWindow(768,576);
if (fullscreen)
glutFullScreen();
glutDisplayFunc(Display);
glutReshapeFunc(HandleReshape);
glutVisibilityFunc(HandleVisibility);
glutKeyboardFunc(HandleKeyboard);
glutSpecialFunc(HandleSpecialKeyboard);
glutMouseFunc(HandleMouse);
glutMotionFunc(HandleMouseMotion);
glutSetCursor(GLUT_CURSOR_NONE);
CreateEnvironment();
CameraHome(0);
/* Set up the speed menu */
speedmenu = glutCreateMenu(HandleSpeedMenu);
glutAddMenuEntry("Stop",1);
glutAddMenuEntry("Slow",2);
glutAddMenuEntry("Medium",3);
glutAddMenuEntry("Fast",4);
glutAddMenuEntry("Very fast",5);
/* Set up the spin menu */
spinmenu = glutCreateMenu(HandleSpinMenu);
glutAddMenuEntry("1 degree",1);
glutAddMenuEntry("2 degrees",2);
glutAddMenuEntry("3 degrees",3);
glutAddMenuEntry("5 degrees",4);
/* Set up the main menu */
mainmenu = glutCreateMenu(HandleMainMenu);
glutAddSubMenu("Rotation",speedmenu);
glutAddSubMenu("Camera rotation steps",spinmenu);
glutAddMenuEntry("Toggle construction lines",1);
glutAddMenuEntry("Quit",9);
glutAttachMenu(GLUT_RIGHT_BUTTON);
/* Ready to go! */
glutMainLoop();
return(0);
}
/*
This is where global OpenGL/GLUT settings are made,
that is, things that will not change in time
*/
void CreateEnvironment(void)
{
glEnable(GL_DEPTH_TEST);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_POINT_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
glShadeModel(GL_SMOOTH);
glDisable(GL_DITHER);
glDisable(GL_CULL_FACE);
glLineWidth(1.0);
glPointSize(1.0);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glFrontFace(GL_CW);
glClearColor(0.0,0.0,0.0,0.0); /* Background colour */
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glPixelStorei(GL_UNPACK_ALIGNMENT,1);
glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
}
/*
This is the basic display callback routine
It creates the geometry, lighting, and viewing position
In this case it rotates the camera around the scene
*/
void Display(void)
{
XYZ right,focus;
/* Clear the buffers */
glDrawBuffer(GL_BACK_LEFT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if (stereo) {
glDrawBuffer(GL_BACK_RIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
/* Determine the focal point */
Normalise(&camera.vd);
focus.x = camera.vp.x + camera.focallength * camera.vd.x;
focus.y = camera.vp.y + camera.focallength * camera.vd.y;
focus.z = camera.vp.z + camera.focallength * camera.vd.z;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(camera.aperture,screenwidth/(double)screenheight,0.1,10000.0);
if (stereo) {
/* Derive the two eye positions */
CROSSPROD(camera.vd,camera.vu,right);
Normalise(&right);
right.x *= camera.eyesep / 2.0;
right.y *= camera.eyesep / 2.0;
right.z *= camera.eyesep / 2.0;
glMatrixMode(GL_MODELVIEW);
glDrawBuffer(GL_BACK_RIGHT);
glLoadIdentity();
gluLookAt(camera.vp.x + right.x,
camera.vp.y + right.y,
camera.vp.z + right.z,
focus.x,focus.y,focus.z,
camera.vu.x,camera.vu.y,camera.vu.z);
MakeLighting();
MakeGeometry();
glMatrixMode(GL_MODELVIEW);
glDrawBuffer(GL_BACK_LEFT);
glLoadIdentity();
gluLookAt(camera.vp.x - right.x,
camera.vp.y - right.y,
camera.vp.z - right.z,
focus.x,focus.y,focus.z,
camera.vu.x,camera.vu.y,camera.vu.z);
MakeLighting();
MakeGeometry();
} else {
glMatrixMode(GL_MODELVIEW);
glDrawBuffer(GL_BACK_LEFT);
glLoadIdentity();
gluLookAt(camera.vp.x,
camera.vp.y,
camera.vp.z,
focus.x,focus.y,focus.z,
camera.vu.x,camera.vu.y,camera.vu.z);
MakeLighting();
MakeGeometry();
}
/* glFlush(); This isn't necessary for double buffers */
glutSwapBuffers();
if (windowdump)
WindowDump(screenwidth,screenheight,stereo);
/* Next angle for rotating the pulsar */
rotateangle += rotatespeed;
}
/*
Create the geometry for the pulsar
*/
void MakeGeometry(void)
{
int i,j,k;
double cradius = 5.3; /* Final radius of the cone */
double clength = 30; /* Cone length */
double sradius = 10; /* Final radius of sphere */
double r1,r2; /* Min and Max radius of field lines */
double x,y,z;
XYZ p[4],n[4];
COLOUR grey = {0.7,0.7,0.7};
COLOUR white = {1.0,1.0,1.0};
GLfloat specular[4] = {1.0,1.0,1.0,1.0};
GLfloat shiny[1] = {5.0};
char cmd[64];
glMaterialfv(GL_FRONT_AND_BACK,GL_SPECULAR,specular);
glMaterialfv(GL_FRONT_AND_BACK,GL_SHININESS,shiny);
/* Top level rotation - spin */
glPushMatrix();
glRotatef(rotateangle,0.0,1.0,0.0);
/* Axis of rotation */
if (showconstruct) {
glColor3f(white.r,white.g,white.b);
glBegin(GL_LINES);
glVertex3f(0.0,-60.0,0.0);
glVertex3f(0.0,60.0,0.0);
glEnd();
}
/* Rotation about spin axis */
glPushMatrix();
glRotatef(45.0,0.0,0.0,1.0);
/* Magnetic axis */
if (showconstruct) {
glColor3f(white.r,white.g,white.b);
glBegin(GL_LINES);
glVertex3f(0.0,-60.0,0.0);
glVertex3f(0.0,60.0,0.0);
glEnd();
}
/* Light in center */
glColor3f(white.r,white.g,white.b);
glutSolidSphere(5.0,16,8);
/* Spherical center */
for (i=0;i<360;i+=5) {
for (j=-80;j<80;j+=5) {
p[0].x = sradius * cos(j*DTOR) * cos(i*DTOR);
p[0].y = sradius * sin(j*DTOR);
p[0].z = sradius * cos(j*DTOR) * sin(i*DTOR);
n[0] = p[0];
p[1].x = sradius * cos((j+5)*DTOR) * cos(i*DTOR);
p[1].y = sradius * sin((j+5)*DTOR);
p[1].z = sradius * cos((j+5)*DTOR) * sin(i*DTOR);
n[1] = p[1];
p[2].x = sradius * cos((j+5)*DTOR) * cos((i+5)*DTOR);
p[2].y = sradius * sin((j+5)*DTOR);
p[2].z = sradius * cos((j+5)*DTOR) * sin((i+5)*DTOR);
n[2] = p[2];
p[3].x = sradius * cos(j*DTOR) * cos((i+5)*DTOR);
p[3].y = sradius * sin(j*DTOR);
p[3].z = sradius * cos(j*DTOR) * sin((i+5)*DTOR);
n[3] = p[3];
glBegin(GL_POLYGON);
if (i % 20 == 0)
glColor3f(1.0,0.0,0.0);
else
glColor3f(0.5,0.0,0.0);
for (k=0;k<4;k++) {
glNormal3f(n[k].x,n[k].y,n[k].z);
glVertex3f(p[k].x,p[k].y,p[k].z);
}
glEnd();
}
}
/* Draw the cones */
for (j=-1;j<=1;j+=2) {
for (i=0;i<360;i+=10) {
p[0] = origin;
n[0] = p[0];
n[0].y = -1;
p[1].x = cradius * cos(i*DTOR);
p[1].y = j*clength;
p[1].z = cradius * sin(i*DTOR);
n[1] = p[1];
n[1].y = 0;
p[2].x = cradius * cos((i+10)*DTOR);
p[2].y = j*clength;
p[2].z = cradius * sin((i+10)*DTOR);
n[2] = p[2];
n[2].y = 0;
glBegin(GL_POLYGON);
if (i % 30 == 0)
glColor3f(0.0,0.2,0.0);
else
glColor3f(0.0,0.5,0.0);
for (k=0;k<3;k++) {
glNormal3f(n[k].x,n[k].y,n[k].z);
glVertex3f(p[k].x,p[k].y,p[k].z);
}
glEnd();
}
}
/* Draw the field lines */
r1 = 12;
r2 = 16;
for (j=0;j<360;j+=20) {
glPushMatrix();
glRotatef((double)j,0.0,1.0,0.0);
glBegin(GL_LINE_STRIP);
glColor3f(grey.r,grey.g,grey.b);
for (i=-140;i<140;i++) {
x = r1 + r1 * cos(i*DTOR);
y = r2 * sin(i*DTOR);
z = 0;
glVertex3f(x,y,z);
}
glEnd();
glPopMatrix();
}
glPopMatrix(); /* Pulsar axis rotation */
glPopMatrix(); /* Pulsar spin */
}
/*
Set up the lighing environment
*/
void MakeLighting(void)
{
GLfloat fullambient[4] = {1.0,1.0,1.0,1.0};
GLfloat position[4] = {0.0,0.0,0.0,0.0};
GLfloat ambient[4] = {0.2,0.2,0.2,1.0};
GLfloat diffuse[4] = {1.0,1.0,1.0,1.0};
GLfloat specular[4] = {0.0,0.0,0.0,1.0};
/* Turn off all the lights */
glDisable(GL_LIGHT0);
glDisable(GL_LIGHT1);
glDisable(GL_LIGHT2);
glDisable(GL_LIGHT3);
glDisable(GL_LIGHT4);
glDisable(GL_LIGHT5);
glDisable(GL_LIGHT6);
glDisable(GL_LIGHT7);
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER,GL_TRUE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_FALSE);
/* Turn on the appropriate lights */
glLightModelfv(GL_LIGHT_MODEL_AMBIENT,fullambient);
glLightfv(GL_LIGHT0,GL_POSITION,position);
glLightfv(GL_LIGHT0,GL_AMBIENT,ambient);
glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuse);
glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
glEnable(GL_LIGHT0);
/* Sort out the shading algorithm */
glShadeModel(GL_SMOOTH);
/* Turn lighting on */
glEnable(GL_LIGHTING);
}
/*
Deal with plain key strokes
*/
void HandleKeyboard(unsigned char key,int x, int y)
{
switch (key) {
case ESC: /* Quit */
case 'Q':
case 'q':
exit(0);
break;
case 'c': /* Toggle constructs */
case 'C':
showconstruct = !showconstruct;
break;
case 'h': /* Go home */
case 'H':
CameraHome(0);
break;
case '[': /* Roll anti clockwise */
RotateCamera(0,0,-1);
break;
case ']': /* Roll clockwise */
RotateCamera(0,0,1);
break;
case 'i': /* Translate camera up */
case 'I':
TranslateCamera(0,1);
break;
case 'k': /* Translate camera down */
case 'K':
TranslateCamera(0,-1);
break;
case 'j': /* Translate camera left */
case 'J':
TranslateCamera(-1,0);
break;
case 'l': /* Translate camera right */
case 'L':
TranslateCamera(1,0);
break;
case 'w': /* Write the image to disk */
case 'W':
windowdump = !windowdump;
break;
}
}
/*
Deal with special key strokes
*/
void HandleSpecialKeyboard(int key,int x, int y)
{
switch (key) {
case GLUT_KEY_LEFT:
RotateCamera(-1,0,0);
break;
case GLUT_KEY_RIGHT:
RotateCamera(1,0,0);
break;
case GLUT_KEY_UP:
RotateCamera(0,1,0);
break;
case GLUT_KEY_DOWN:
RotateCamera(0,-1,0);
break;
}
}
/*
Rotate (ix,iy) or roll (iz) the camera about the focal point
ix,iy,iz are flags, 0 do nothing, +- 1 rotates in opposite directions
Correctly updating all camera attributes
*/
void RotateCamera(int ix,int iy,int iz)
{
XYZ vp,vu,vd;
XYZ right;
XYZ newvp,newr;
double radius,dd,radians;
double dx,dy,dz;
vu = camera.vu;
Normalise(&vu);
vp = camera.vp;
vd = camera.vd;
Normalise(&vd);
CROSSPROD(vd,vu,right);
Normalise(&right);
radians = dtheta * PI / 180.0;
/* Handle the roll */
if (iz != 0) {
camera.vu.x += iz * right.x * radians;
camera.vu.y += iz * right.y * radians;
camera.vu.z += iz * right.z * radians;
Normalise(&camera.vu);
return;
}
/* Distance from the rotate point */
dx = camera.vp.x - camera.pr.x;
dy = camera.vp.y - camera.pr.y;
dz = camera.vp.z - camera.pr.z;
radius = sqrt(dx*dx + dy*dy + dz*dz);
/* Determine the new view point */
dd = radius * radians;
newvp.x = vp.x + dd * ix * right.x + dd * iy * vu.x - camera.pr.x;
newvp.y = vp.y + dd * ix * right.y + dd * iy * vu.y - camera.pr.y;
newvp.z = vp.z + dd * ix * right.z + dd * iy * vu.z - camera.pr.z;
Normalise(&newvp);
camera.vp.x = camera.pr.x + radius * newvp.x;
camera.vp.y = camera.pr.y + radius * newvp.y;
camera.vp.z = camera.pr.z + radius * newvp.z;
/* Determine the new right vector */
newr.x = camera.vp.x + right.x - camera.pr.x;
newr.y = camera.vp.y + right.y - camera.pr.y;
newr.z = camera.vp.z + right.z - camera.pr.z;
Normalise(&newr);
newr.x = camera.pr.x + radius * newr.x - camera.vp.x;
newr.y = camera.pr.y + radius * newr.y - camera.vp.y;
newr.z = camera.pr.z + radius * newr.z - camera.vp.z;
camera.vd.x = camera.pr.x - camera.vp.x;
camera.vd.y = camera.pr.y - camera.vp.y;
camera.vd.z = camera.pr.z - camera.vp.z;
Normalise(&camera.vd);
/* Determine the new up vector */
CROSSPROD(newr,camera.vd,camera.vu);
Normalise(&camera.vu);
if (debug)
fprintf(stderr,"Camera position: (%g,%g,%g)\n",
camera.vp.x,camera.vp.y,camera.vp.z);
}
/*
Translate (pan) the camera view point
In response to i,j,k,l keys
Also move the camera rotate location in parallel
*/
void TranslateCamera(int ix,int iy)
{
XYZ vp,vu,vd;
XYZ right;
XYZ newvp,newr;
double radians,delta;
vu = camera.vu;
Normalise(&vu);
vp = camera.vp;
vd = camera.vd;
Normalise(&vd);
CROSSPROD(vd,vu,right);
Normalise(&right);
radians = dtheta * PI / 180.0;
delta = dtheta * camera.focallength / 90.0;
camera.vp.x += iy * vu.x * delta;
camera.vp.y += iy * vu.y * delta;
camera.vp.z += iy * vu.z * delta;
camera.pr.x += iy * vu.x * delta;
camera.pr.y += iy * vu.y * delta;
camera.pr.z += iy * vu.z * delta;
camera.vp.x += ix * right.x * delta;
camera.vp.y += ix * right.y * delta;
camera.vp.z += ix * right.z * delta;
camera.pr.x += ix * right.x * delta;
camera.pr.y += ix * right.y * delta;
camera.pr.z += ix * right.z * delta;
}
/*
Handle mouse events
Right button events are passed to menu handlers
*/
void HandleMouse(int button,int state,int x,int y)
{
if (state == GLUT_DOWN) {
if (button == GLUT_LEFT_BUTTON) {
currentbutton = GLUT_LEFT_BUTTON;
} else if (button == GLUT_MIDDLE_BUTTON) {
currentbutton = GLUT_MIDDLE_BUTTON;
}
}
}
/*
Handle the main menu
*/
void HandleMainMenu(int whichone)
{
switch (whichone) {
case 1:
showconstruct = !showconstruct;
break;
case 9:
exit(0);
break;
}
}
/*
Handle the speed menu
The rotate speed is in degrees
*/
void HandleSpeedMenu(int whichone)
{
switch (whichone) {
case 1: rotatespeed = 0.0; break;
case 2: rotatespeed = 0.3; break;
case 3: rotatespeed = 1; break;
case 4: rotatespeed = 3; break;
case 5: rotatespeed = 10; break;
}
}
/*
Handle the camera spin menu
*/
void HandleSpinMenu(int whichone)
{
switch (whichone) {
case 1: dtheta = 1; break;
case 2: dtheta = 2; break;
case 3: dtheta = 3; break;
case 4: dtheta = 5; break;
}
}
/*
How to handle visibility
*/
void HandleVisibility(int visible)
{
if (visible == GLUT_VISIBLE)
glutIdleFunc(HandleIdle);
else
glutIdleFunc(NULL);
}
/*
What to do on an idle event
*/
void HandleIdle(void)
{
glutPostRedisplay();
}
/*
Handle a window reshape/resize
*/
void HandleReshape(int w,int h)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0,0,(GLsizei)w,(GLsizei)h);
screenwidth = w;
screenheight = h;
}
/*
Display the program usage information
*/
void GiveUsage(char *cmd)
{
fprintf(stderr,"Usage: %s [-h] [-f] [-s] [-c] [-q n]\n",cmd);
fprintf(stderr," -h this text\n");
fprintf(stderr," -f full screen\n");
fprintf(stderr," -s stereo\n");
fprintf(stderr," -c show construction lines\n");
fprintf(stderr,"Key Strokes\n");
fprintf(stderr," arrow keys rotate left/right/up/down\n");
fprintf(stderr," left mouse rotate\n");
fprintf(stderr,"middle mouse roll\n");
fprintf(stderr," c toggle construction lines\n");
fprintf(stderr," i translate up\n");
fprintf(stderr," k translate down\n");
fprintf(stderr," j translate left\n");
fprintf(stderr," l translate right\n");
fprintf(stderr," [ roll clockwise\n");
fprintf(stderr," ] roll anti clockwise\n");
fprintf(stderr," q quit\n");
exit(-1);
}
void Normalise(XYZ *p)
{
double length;
length = sqrt(p->x * p->x + p->y * p->y + p->z * p->z);
if (length != 0) {
p->x /= length;
p->y /= length;
p->z /= length;
} else {
p->x = 0;
p->y = 0;
p->z = 0;
}
}
XYZ CalcNormal(XYZ p,XYZ p1,XYZ p2)
{
XYZ n,pa,pb;
pa.x = p1.x - p.x;
pa.y = p1.y - p.y;
pa.z = p1.z - p.z;
pb.x = p2.x - p.x;
pb.y = p2.y - p.y;
pb.z = p2.z - p.z;
Normalise(&pa);
Normalise(&pb);
n.x = pa.y * pb.z - pa.z * pb.y;
n.y = pa.z * pb.x - pa.x * pb.z;
n.z = pa.x * pb.y - pa.y * pb.x;
Normalise(&n);
return(n);
}
/*
Move the camera to the home position
*/
void CameraHome(int mode)
{
camera.aperture = 50;
camera.focallength = 70;
camera.eyesep = camera.focallength / 20;
camera.pr = origin;
/*
camera.vp.x = camera.focallength;
camera.vp.y = 0;
camera.vp.z = 0;
camera.vd.x = -1;
camera.vd.y = 0;
camera.vd.z = 0;
*/
/* Special camera position so the beam crosses the view */
camera.vp.x = 39;
camera.vp.y = 53;
camera.vp.z = 22;
camera.vd.x = -camera.vp.x;
camera.vd.y = -camera.vp.y;
camera.vd.z = -camera.vp.z;
camera.vu.x = 0;
camera.vu.y = 1;
camera.vu.z = 0;
}
/*
Handle mouse motion
*/
void HandleMouseMotion(int x,int y)
{
static int xlast=-1,ylast=-1;
int dx,dy;
dx = x - xlast;
dy = y - ylast;
if (dx < 0) dx = -1;
else if (dx > 0) dx = 1;
if (dy < 0) dy = -1;
else if (dy > 0) dy = 1;
if (currentbutton == GLUT_LEFT_BUTTON)
RotateCamera(-dx,dy,0);
else if (currentbutton == GLUT_MIDDLE_BUTTON)
RotateCamera(0,0,dx);
xlast = x;
ylast = y;
}
/*
Write the current view to a PPM file
Do the right thing for stereo, ie: two images
*/
int WindowDump(int width,int height,int stereo)
{
int i,j;
FILE *fptr;
static int counter = 0;
char fname[32];
unsigned char *image;
/* Allocate our buffer for the image */
if ((image = malloc(3*width*height*sizeof(char))) == NULL) {
fprintf(stderr,"WindowDump - Failed to allocate memory for image\n");
return(FALSE);
}
glPixelStorei(GL_PACK_ALIGNMENT,4);
/* Open the file */
sprintf(fname,"L_%04d.ppm",counter);
if ((fptr = fopen(fname,"w")) == NULL) {
fprintf(stderr,"WindowDump - Failed to open file for window dump\n");
return(FALSE);
}
/* Copy the image into our buffer */
glReadBuffer(GL_BACK_LEFT);
glReadPixels(0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,image);
/* Write the PPM file */
fprintf(fptr,"P3\n%d %d\n255\n",width,height);
for (j=height-1;j>=0;j--) {
for (i=0;i<width;i++) {
fputc(image[3*j*width+3*i+0],fptr);
fputc(image[3*j*width+3*i+1],fptr);
fputc(image[3*j*width+3*i+2],fptr);
}
}
fclose(fptr);
if (stereo) {
/* Open the file */
sprintf(fname,"R_%04d.ppm",counter);
if ((fptr = fopen(fname,"w")) == NULL) {
fprintf(stderr,"WindowDump - Failed to open file for window dump\n");
return(FALSE);
}
/* Copy the image into our buffer */
glReadBuffer(GL_BACK_RIGHT);
glReadPixels(0,0,width,height,GL_RGB,GL_UNSIGNED_BYTE,image);
/* Write the PPM file */
fprintf(fptr,"P3\n%d %d\n255\n",width,height);
for (j=height-1;j>=0;j--) {
for (i=0;i<width;i++) {
fputc(image[3*j*width+3*i+0],fptr);
fputc(image[3*j*width+3*i+1],fptr);
fputc(image[3*j*width+3*i+2],fptr);
}
}
fclose(fptr);
}
free(image);
counter++;
return(TRUE);
}