|
|
extern "C" { #include <windows.h>
#include <GL/glaux.h>
#include <GL/glu.h>
#include <GL/gl.h>
}
#ifdef GLX_MOTIF
#include <GL/glx.h>
#endif
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "Unitdisk.hxx"
#include "scene.hxx"
const GLfloat I[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
Color white; Color black;
const double M_2PI = 2.0 * M_PI; const float scene_fudge = .000001;
// Lights are native to the xz plane and are rotated into position -
// shadows and refraction will not have to be changed if lights are
// just rotating about the z axis
light lights[] = { {{1, 0, 0, 1}, {0, 0, 0, 0}, {1, 0, 0, 0}, {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, "Red", 1}, {{0, 1, 0, 1}, {0, 0, 0, 0}, {0, 1, 0, 0}, {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, "Green", 1}, {{0, 0, 1, 1}, {0, 0, 0, 0}, {0, 0, 1, 0}, {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, "Blue", 1} };
GLfloat light_init_position[nlights][4] = { {1.5, 0, 2.5, 1}, {1, 0, 3, 1}, {2, 0, 3, 1} };
GLfloat light_init_rotation[nlights] = {135, 0, 90}; GLfloat light_rotation[nlights];
Color world_ambient(.25, .25, .25);
GLfloat index = indices[def_refraction_index].index;
GLfloat square_ambient[4] = {.25, .25, .25, 1}; GLfloat square_diffuse[4] = {1, 1, 1, 1}; GLfloat square_specular[4] = {0, 0, 0, 1};
const GLfloat fov = 45.0; GLfloat aspect = 1.0; GLfloat eyep[3] = {-6, 0, 6}; GLfloat lookp[3] = {0, 0, 1};
#ifdef GLX_MOTIF
static GLXContext glx_context; #endif
const int max_args = 20;
static int list_square; static int lists_shadows; static int lists_refraction; static int lists_lights = 5; static int list_sphere = 4; static int list_spheredisk = 9; static int list_lights_on = 6; static int list_lights_off = 7; static int list_light_draw = 8;
int draw_square = 1; int draw_shadows = 1; int draw_refraction = 1; int draw_sphere = 1; int draw_lights = 1; int draw_texture = 0;
int possible_divisions[] = {10, 20, 30, 40};
// Sphere is stored as floats - more efficient
GLfloat *spherepts = NULL; int nspherepts = 0; int spherediv = 0; Point sphere_position = {0, 0, 1, 1}; GLfloat sphere_size = .5; const GLfloat sphere_ambient[4] = {0, 0, 0, 0}; const GLfloat sphere_specular[4] = {0, 0, 0, 0}; Unitdisk sphere_disk; static void sphere_build(); static void sphere_list_init(); static void sphere_draw();
static void square_list_init();
static void lights_init_onoff(); static void lights_init_position(); static void lights_init_position(int i); static void lights_list_init(); static void lights_list_init(int n);
static void light_draw_list_init();
Unitdisk disks[nlights]; int diskdiv = possible_divisions[def_divisions_index]; static void disk_build(); static void disk_build(int disk);
Unitdisk shadows[nlights]; static void shadow_list_init(); static void shadow_list_init(int n); static void shadow_draw(int n);
Unitdisk refraction[nlights]; static void refraction_list_init(); static void refraction_list_init(int n);
static void shadow_refraction_full_build(); static void shadow_refraction_full_build(int n);
void scene_init();
#ifdef MYDEBUG
void lists_init(); void lights_init(); int lights_move(int light, float dr, float dphi, float dtheta, int update);
void lights_move_update(int light, int dr, int dphi, int dtheta); #else
static void lists_init(); static void lights_init(); static int lights_move(int light, float dr, float dphi, float dtheta, int update); static void lights_move_update(int light, int dr, int dphi, int dtheta); #endif
void scene_draw();
void texture_init(); AUX_RGBImageRec *teximage = NULL;
inline float sign(float a) { // This is badly written so let's not call it too often, 'k?
return (a > 0) ? (float)1 : (a < 0) ? (float) -1 : (float) 0; }
inline double degrees(double a) { return (a * 180.0 / M_PI); }
inline double radians(double a) { return (a * M_PI / 180.0); }
inline double degrees_clamp(double a) { while (a < 0.0) a += 360.0; while (a > 360.0) a -= 360.0; return a; }
inline double radians_clamp(double a) { while (a < 0.0) a += M_2PI; while (a > M_2PI) a -= M_2PI; return a; }
void scene_init() { int i;
white.c[0] = white.c[1] = white.c[2] = white.c[3] = 1; black.c[0] = black.c[1] = black.c[2] = 0; black.c[3] = 1;
lists_init();
for (i = 0; i < nlights; i++) { lights[i].pos = light_init_position[i]; light_rotation[i] = light_init_rotation[i]; lights_init_position(i); }
divisions_change(possible_divisions[def_divisions_index]);
lights_init_onoff(); lights_init(); lights_init_position();
texture_init();
glClearStencil(0);
// This is for profiling
// exit(0);
}
static void scene_project() { glMatrixMode(GL_PROJECTION); gluPerspective(fov, aspect, 0.01, 20.0); gluLookAt(eyep[0], eyep[1], eyep[2], lookp[0], lookp[1], lookp[2], 1, 0, 0); }
static void scene_rasterize() { int i;
glLoadName(name_square); if (draw_square) { if (draw_texture) glEnable(GL_TEXTURE_2D); glCallList(list_square); glDisable(GL_TEXTURE_2D); } if (draw_shadows) for (i = 0; i < nlights; i++) if (lights[i].on) { glPushMatrix(); glRotatef(-light_rotation[i], 0, 0, 1); glCallList(lists_shadows + i); glPopMatrix(); } if (draw_refraction) for (i = 0; i < nlights; i++) if (lights[i].on) { glPushMatrix(); glRotatef(-light_rotation[i], 0, 0, 1); glCallList(lists_refraction + i); glPopMatrix(); }
glLoadName(name_sphere); /* Drawing the sphere here makes the sphere visible through itself when we
* do the refraction redraw hack -- for now, just don't draw it */ // if (draw_sphere) glCallList(list_sphere);
for (i = 0; i < nlights; i++) if (draw_lights) glCallList(lists_lights + i); }
/* This draws an image of the scene seen through the sphere */ static void scene_draw_refracted() { int i;
if (!draw_sphere) return;
/* Draw an image of the sphere into the stencil plane -
* must do this every time in case the lights have moved in front * of it */ glEnable(GL_STENCIL_TEST); glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); glStencilFunc(GL_ALWAYS, 0x1, 0x1); glStencilOp(GL_REPLACE, GL_KEEP, GL_REPLACE);
glColorMask(0, 0, 0, 0);
glMatrixMode(GL_PROJECTION); glLoadIdentity(); scene_project();
glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glCallList(list_sphere); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST);
glColorMask(1, 1, 1, 1);
/* Set up a transform with a wider field of view - this is inaccurate
* but I don't have time to do it right */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(fov * index, aspect, 0.01, 20.0); gluLookAt(eyep[0], eyep[1], eyep[2], lookp[0], lookp[1], lookp[2], 1, 0, 0); glMatrixMode(GL_MODELVIEW); glLoadIdentity();
/* Set up the stencil stuff which will be used to draw the image */ glStencilFunc(GL_NOTEQUAL, 0x0, 0xffffffff); glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
/* Draw the image, gambling that we'll never see anything but the
* floor through the table */ glLoadName(name_sphere); if (draw_texture) glEnable(GL_TEXTURE_2D); if (draw_square) glCallList(list_square); if (draw_shadows) for (i = 0; i < nlights; i++) if (lights[i].on) { glPushMatrix(); glRotatef(-light_rotation[i], 0, 0, 1); glCallList(lists_shadows + i); glPopMatrix(); } if (draw_refraction) for (i = 0; i < nlights; i++) if (lights[i].on) { glPushMatrix(); glRotatef(-light_rotation[i], 0, 0, 1); glCallList(lists_refraction + i); glPopMatrix(); } glDisable(GL_TEXTURE_2D);
/* Draw the sphere to make it look like it
* has some substance */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); scene_project(); glCallList(list_spheredisk);
glDisable(GL_STENCIL_TEST); }
void scene_draw() { glMatrixMode(GL_PROJECTION); glLoadIdentity();
glMatrixMode(GL_MODELVIEW); glLoadIdentity();
scene_project();
/* Should draw an image of the square into the stencil buffer
* to make sure that refractions which are not on the square do not get * drawn, but it can wait. */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); scene_rasterize();
scene_draw_refracted();
}
const int pick_maxz = 0xffffffff;
int scene_pick(GLdouble x, GLdouble y) { GLuint buffer[128]; GLint vp[4], nhits, nnames; GLuint minz, hit = name_background; GLint i, j;
glMatrixMode(GL_MODELVIEW); glLoadIdentity();
glMatrixMode(GL_PROJECTION); glLoadIdentity();
glGetIntegerv(GL_VIEWPORT, vp);
glSelectBuffer(128, buffer); glRenderMode(GL_SELECT);
// Where is this supposed to go, anyway?
gluPickMatrix(x, vp[3] - y, 1, 1, vp);
scene_project();
glMatrixMode(GL_MODELVIEW);
glInitNames(); glPushName(name_background); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); scene_rasterize(); glFlush(); nhits = glRenderMode(GL_RENDER);
minz = pick_maxz; for (i = j = 0; j < nhits; j++) { nnames = buffer[i]; i++; if (buffer[i] < minz) { minz = buffer[i]; hit = buffer[i + 1 + nnames]; } i++; i += nnames + 1; } if (minz == pick_maxz) return name_background; else return hit; }
void scene_reset_lights() { int i; for (i = 0; i < nlights; i++) { lights[i].pos = light_init_position[i]; light_rotation[i] = light_init_rotation[i]; } lights_init_position(); lights_list_init(); }
static void square_list_init() { GLfloat x, y, inc; int i, j; glNewList(list_square, GL_COMPILE); glLoadName(name_square); glNormal3f(0, 0, 1); glEnable(GL_LIGHTING); glCallList(list_lights_on); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, square_ambient); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, square_diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, square_specular); inc = (GLfloat) (10.0 / diskdiv); glEnable(GL_CULL_FACE);
for (i = 0, y = -5.0; i < diskdiv; i++, y += inc) { glBegin(GL_TRIANGLE_STRIP); for (j = 0, x = -5.0; j <= diskdiv; j++, x += inc) { glTexCoord2f(x, y + inc); glVertex2f(x, y + inc); glTexCoord2f(x, y); glVertex2f(x, y); } glEnd(); }
glDisable(GL_CULL_FACE); glCallList(list_lights_off); glDisable(GL_LIGHTING); glEndList(); }
static void spheredisk_list_init() { glNewList(list_spheredisk, GL_COMPILE); glEnable(GL_BLEND); glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); glEnable(GL_LIGHTING); glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); glEnable(GL_COLOR_MATERIAL); glMaterialfv(GL_AMBIENT, GL_FRONT_AND_BACK, sphere_ambient); glMaterialfv(GL_SPECULAR, GL_FRONT_AND_BACK, sphere_specular); glCallList(list_lights_on); sphere_disk.draw(); glCallList(list_lights_off); glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); glDisable(GL_BLEND); glEndList(); }
void lights_onoff(int light, int val) { lights[light].on = val; lights_init_onoff(); lights_list_init(light); square_list_init(); }
void refraction_change(GLfloat refraction) { if (refraction == index) return; index = refraction; shadow_refraction_full_build(); refraction_list_init(); }
void divisions_change(int divisions) { Point eye, look;
if (divisions != spherediv) { spherediv = divisions;
light_draw_list_init(); lights_list_init();
sphere_disk.set_divisions(spherediv, spherediv); sphere_disk.fill_points(); sphere_disk.set_colors(white); sphere_disk.scale_alpha_by_z(); eye = eyep; look = lookp; sphere_disk.face_direction((eye - look).unit()); sphere_disk.copy_normals_from_points(); sphere_disk.scale_translate(sphere_size, sphere_position); sphere_build(); sphere_list_init();
diskdiv = divisions; disk_build(); shadow_refraction_full_build(); square_list_init(); spheredisk_list_init(); shadow_list_init(); refraction_list_init(); } }
int scene_move(int name, float dr, float dphi, float dtheta, int update) { switch(name) { case name_background: return 0; case name_square: return 0; case name_sphere: return 0; default: if (name < name_lights || name > name_lights + nlights) return 0; return lights_move(name - name_lights, dr, dphi, dtheta, update); } }
void scene_move_update(int name, int dr, int dphi, int dtheta) { switch(name) { case name_background: break; case name_square: break; case name_sphere: break; default: if (name < name_lights || name > name_lights + nlights) break; lights_move_update(name - name_lights, dr, dphi, dtheta); break; } }
#ifdef MYDEBUG
void lights_init_onoff() #else
static void lights_init_onoff() #endif
{ int i;
glNewList(list_lights_on, GL_COMPILE); for (i = 0; i < nlights; i++) if (lights[i].on) glEnable(GL_LIGHT0 + i); else glDisable(GL_LIGHT0 + i); glEndList();
glNewList(list_lights_off, GL_COMPILE); for (i = 0; i < nlights; i++) glDisable(GL_LIGHT0 + i); glEndList(); }
#ifdef MYDEBUG
void lights_init_position() #else
static void lights_init_position() #endif
{ int i;
for (i = 0; i < nlights; i++) lights_init_position(i);
}
static void lights_init_position(int i) { Point l, d;
glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity();
l = lights[i].pos; l.pt[0] = (GLfloat)(lights[i].pos.pt[0] * cos((double)radians(light_rotation[i]))); l.pt[1] = (GLfloat)(lights[i].pos.pt[0] * -sin((double)radians(light_rotation[i]))); d = (sphere_position - l).unit(); glLightfv(GL_LIGHT0 + i, GL_POSITION, l.pt); glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, d.pt); }
static void lights_list_init() { int i; for (i = 0; i < nlights; i++) lights_list_init(i); }
static void lights_list_init(int n) { Color c;
glNewList(lists_lights + n, GL_COMPILE); if (lights[n].on) { glLoadName(name_lights + n);
glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); glCallList(list_lights_on);
c = lights[n].diffuse; glMaterialfv(GL_BACK, GL_AMBIENT, c.c); glMaterialfv(GL_BACK, GL_DIFFUSE, black.c); glMaterialfv(GL_BACK, GL_SPECULAR, black.c);
glMaterialfv(GL_FRONT, GL_AMBIENT, (c * .75).c); glMaterialfv(GL_FRONT, GL_DIFFUSE, white.c); glMaterialfv(GL_FRONT, GL_SPECULAR, white.c);
glMatrixMode(GL_MODELVIEW); glPushMatrix(); glRotatef(-light_rotation[n], 0, 0, 1); glTranslatef(lights[n].pos.pt[0], lights[n].pos.pt[1], lights[n].pos.pt[2]); glRotatef((GLfloat)-degrees(atan2((double)(lights[n].pos.pt[2] - sphere_position.pt[2]), (double)(lights[n].pos.pt[0]))), 0, 1, 0); glCallList(list_light_draw); glPopMatrix();
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0); glDisable(GL_LIGHTING); glCallList(list_lights_off); glDisable(GL_DEPTH_TEST); } else { /* 5.0.1 for Elans seems to object strongly to replacing
* empty display lists, so will put a placeholder command * in here */ glColor3f(0, 0, 0); } glEndList(); }
static void light_draw_list_init() { float c, s; int t;
glNewList(list_light_draw, GL_COMPILE); glEnable(GL_NORMALIZE); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glScalef(.25, .15, .15); glBegin(GL_QUAD_STRIP); for (t = 0; t <= spherediv; t++) { c = (float) cos((double)(M_2PI * (float)t / (float)spherediv)); s = (float) sin((double)(M_2PI * (float)t / (float)spherediv)); glNormal3f((GLfloat).25, (GLfloat)(.968*s), (GLfloat)(.968*c)); glVertex3f((GLfloat)0, (GLfloat)s, (GLfloat)c); glVertex3f((GLfloat)1, (GLfloat)(.75*s), (GLfloat)(.75*c)); } glEnd(); glNormal3f(1, 0, 0); glBegin(GL_TRIANGLE_STRIP); for (t = 0; t <= spherediv; t++) { c = (float)cos((double)(M_2PI * (float)t / (float)spherediv)); s = (float)sin((double)(M_2PI * (float)t / (float)spherediv)); glVertex3f((GLfloat)1, (GLfloat)(.75*s), (GLfloat)(.75*c)); glVertex3f(1, 0, 0); } glEnd(); glPopMatrix(); glDisable(GL_NORMALIZE); glEndList(); }
#ifdef MYDEBUG
void lights_init() #else
static void lights_init() #endif
{ int i;
for (i = 0; i < nlights; i++) { glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lights[i].diffuse); glLightfv(GL_LIGHT0 + i, GL_SPECULAR, black.c); glLightfv(GL_LIGHT0 + i, GL_AMBIENT, black.c); glLightf(GL_LIGHT0 + i, GL_SPOT_EXPONENT, 4); glLightf(GL_LIGHT0 + i, GL_SPOT_CUTOFF, 90); }
glLightfv(GL_LIGHT0 + nlights, GL_DIFFUSE, black.c); glLightfv(GL_LIGHT0 + nlights, GL_SPECULAR, black.c); glLightfv(GL_LIGHT0 + nlights, GL_AMBIENT, world_ambient.c); glEnable(GL_LIGHT0 + nlights);
/* GL_LIGHT0 + nlights + 1 willl eventually be used to draw the
* refractions - stay tuned. */ glLightfv(GL_LIGHT0 + nlights + 1, GL_DIFFUSE, black.c); glLightfv(GL_LIGHT0 + nlights + 1, GL_SPECULAR, black.c); glLightfv(GL_LIGHT0 + nlights + 1, GL_AMBIENT, white.c); }
#ifdef MYDEBUG
int lights_move(int light, float dr, float dphi, float dtheta, #else
static int lights_move(int light, float dr, float dphi, float dtheta,
#endif
int update) { float cphi, sphi, x, y; Point l, dl;
if (!(dr || dphi || dtheta)) return 0;
l = lights[light].pos - sphere_position;
if (dr) { dl = l + l*dr; if (dl.mag() > sphere_size) l = dl; }
if (dphi) { cphi = (float)cos((double)dphi); sphi = (float)sin((double)dphi); y = -l.pt[0]*sphi + l.pt[2]*cphi;
/* This hack keeps with light from getting below the sphere -
* the projection sections would completely get messed up if this ever * happened - sphere_size is multiplied by two as a fudge factor*/ if (y < 2.0*sphere_size) { dphi = (float)atan2((double)(l.pt[2] - 2.0*sphere_size), (double)l.pt[0]); cphi = (float)cos((double)dphi); sphi = (float)sin((double)dphi);
} x = l.pt[0]; l.pt[0] = x*cphi + l.pt[2]*sphi; l.pt[2] = -x*sphi + l.pt[2]*cphi; }
if (dtheta) { light_rotation[light] += (GLfloat)degrees((double)dtheta); light_rotation[light] = (GLfloat)degrees_clamp((double)light_rotation[light]); }
lights[light].pos = l + sphere_position; lights[light].pos.pt[3] = 1;
lights_init_position(light); lights_list_init(light);
if (update) lights_move_update(light, dr ? 1 : 0, dphi ? 1 : 0, dtheta ? 1 : 0); return 1; }
#ifdef MYDEBUG
void lights_move_update(int light, int dr, int dphi, #else
static void lights_move_update(int light, int dr, int dphi, #endif
int dtheta) { if (dr) { disk_build(light); shadow_refraction_full_build(light); shadow_list_init(light); refraction_list_init(light); } else if (dphi) { shadow_refraction_full_build(light); shadow_list_init(light); refraction_list_init(light); } else if (dtheta) { }
}
#ifdef MYDEBUG
int get_lists(int size) #else
static int get_lists(int size) #endif
{ int i; i = glGenLists(size); if (size && !i) { fprintf(stderr, "Unable to allocate display lists.\n"); exit(1); } return i; }
#ifdef MYDEBUG
void lists_init() #else
static void lists_init() #endif
{ list_square = get_lists(1); lists_shadows = get_lists(nlights); lists_refraction = get_lists(nlights); lists_lights = get_lists(nlights); list_sphere = get_lists(1); list_spheredisk = get_lists(1); list_lights_on = get_lists(1); list_lights_off = get_lists(1); list_light_draw = get_lists(1); // sphere_build();
}
static inline int sphere_npoints() { return (spherediv+1)*spherediv*3; }
void sphere_build() { int nspherepts; int r, t, index; float c, s; delete spherepts; nspherepts = sphere_npoints(); if (nspherepts == 0) return; spherepts = new GLfloat[nspherepts];
index = 0; for (r = 0; r <= spherediv; r++) { spherepts[index++] = (GLfloat)sin((double)(M_PI * (float)r / (float)spherediv)); spherepts[index++] = 0; spherepts[index++] = (GLfloat)-cos((double)(M_PI * (float)r / (float)spherediv)); } for (t = 1; t < spherediv; t++) { c = (float)cos((double)(2.0 * M_PI * (float)t / (float)spherediv)); s = (float)sin((double)(2.0 * M_PI * (float)t / (float)spherediv)); for (r = 0; r <= spherediv; r++) { spherepts[index++] = c*spherepts[r*3]; spherepts[index++] = s*spherepts[r*3]; spherepts[index++] = spherepts[r*3 + 2]; } }
}
void sphere_list_init() { glNewList(list_sphere, GL_COMPILE); sphere_disk.draw_by_perimeter(); glEndList(); }
void sphere_draw() { int r, t, p1, p2;
for (t = 1; t < spherediv; t++) { glBegin(GL_QUAD_STRIP); p1 = (t - 1) * (spherediv + 1); p2 = t * (spherediv + 1); for (r = 0; r <= spherediv; r++, p1++, p2++) { glNormal3fv(&spherepts[p1*3]); glVertex3fv(&spherepts[p1*3]); glNormal3fv(&spherepts[p2*3]); glVertex3fv(&spherepts[p2*3]); } glEnd(); }
glBegin(GL_QUAD_STRIP); p1 = (spherediv + 1) * (spherediv - 1); p2 = 0; for (r = 0; r <= spherediv; r++, p1++, p2++) { glNormal3fv(&spherepts[p1*3]); glVertex3fv(&spherepts[p1*3]); glNormal3fv(&spherepts[p2*3]); glVertex3fv(&spherepts[p2*3]); } glEnd(); }
static void disk_build() { int i; for (i = 0; i < nlights; i++) disk_build(i); }
static void disk_build(int disk) { Point light; light = lights[disk].pos;
disks[disk].free_points_normals(); disks[disk].free_colors();
disks[disk].set_divisions(diskdiv, diskdiv); disks[disk].set_angle((float)(2.0 * acos((double)(sphere_size / light.dist(sphere_position))))); disks[disk].fill_points(); }
static void shadow_list_init() { int i; for (i = 0; i < nlights; i++) shadow_list_init(i); }
static void shadow_list_init(int n) { Color c(square_ambient[0], square_ambient[1], square_ambient[2]);
c *= world_ambient;
glNewList(lists_shadows + n, GL_COMPILE); glColorMask(lights[n].shadow_mask[0], lights[n].shadow_mask[1], lights[n].shadow_mask[2], lights[n].shadow_mask[3]); glDisable(GL_DEPTH_TEST); glColor3fv(c.c); shadows[n].draw_by_perimeter(0, 0, 1); glColorMask(1, 1, 1, 1); glEndList(); }
static void refraction_list_init() { int i; for (i = 0; i < nlights; i++) refraction_list_init(i); }
static void refraction_list_init(int n) { /* This could be loads simpler if it weren't for the texture mapping -
* that's where all this weirdness with GL_LIGHT0 + nlights + 1 comes * in */ glNewList(lists_refraction + n, GL_COMPILE);
glEnable(GL_LIGHTING); glCallList(list_lights_off); /* This is white ambient light */ glEnable(GL_LIGHT0 + nlights + 1); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, black.c); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black.c); glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT); glEnable(GL_COLOR_MATERIAL);
glBlendFunc(GL_ONE, GL_ONE); glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST); refraction[n].draw();
glDisable(GL_BLEND);
glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHT0 + nlights + 1); glDisable(GL_LIGHTING);
glEndList(); }
static void shadow_refraction_full_build() { int i; for (i = 0; i < nlights; i++) shadow_refraction_full_build(i); }
/* This entire function is written a bit oddly... */ static void shadow_refraction_full_build(int n) { Color c; float dist_light; Point dlight, zaxis;
/* Make sure that we're starting over from scratch */ shadows[n].free_points_normals(); shadows[n].free_colors(); refraction[n].free_points_normals(); refraction[n].free_colors();
dlight = lights[n].pos - sphere_position; dist_light = dlight.mag(); dlight.unitize(); zaxis.pt[0] = 0; zaxis.pt[1] = 0; zaxis.pt[2] = 1;
shadows[n].set_divisions(disks[n].get_rdivisions(), disks[n].get_tdivisions()); refraction[n].set_divisions(disks[n].get_rdivisions(), disks[n].get_tdivisions());
shadows[n].alloc_points(); shadows[n].face_direction(dlight, disks[n]); shadows[n].scale_translate(sphere_size, sphere_position);
c = square_diffuse; c *= lights[n].diffuse;
refraction[n].copy_points(disks[n]); refraction[n].set_colors(c); refraction[n].scale_colors_by_z();
refraction[n].scale(sphere_size); refraction[n].refract_normals(zaxis * dist_light, index); refraction[n].face_direction(dlight);
refraction[n].project_borrow_points(shadows[n]); refraction[n].free_normals(); shadows[n].project(lights[n].pos); if (index != 1.0) refraction[n].scale_colors_by_darea(shadows[n]); }
int scene_load_texture(char *texfile) { #ifdef TEXTURE
teximage = auxRGBImageLoad(texfile); #else
teximage = NULL; #endif
if (teximage == NULL) return 0; else return 1; }
void texture_init() { if (teximage == NULL) return;
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, teximage->sizeX, teximage->sizeY, GL_RGB, GL_UNSIGNED_BYTE, teximage->data);
glMatrixMode(GL_TEXTURE); glLoadIdentity(); glRotatef(90, 0, 0, 1); /* This scales the texture so that it fits on the square */ glTranslatef(.5, .5, 0); glScalef(2, 2, 1); glMatrixMode(GL_MODELVIEW);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); }
|