Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Лабораторная работа №62 / main
.c#include <GL/glut.h>
#include <stdlib.h>
/* Create a single component texture map */
GLfloat *
make_texture(int maxs, int maxt)
{
int s, t;
static GLfloat *texture;
texture = (GLfloat *) malloc(maxs * maxt * sizeof(GLfloat));
for (t = 0; t < maxt; t++) {
for (s = 0; s < maxs; s++) {
texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
}
}
return texture;
}
enum {
LIGHT=1, FLOOR
};
enum {
X, Y, Z, W
};
enum {
A, B, C, D
};
GLfloat LIGHTPOS_X = 0.f;
GLfloat LIGHTPOS_Y = 50.f;
GLfloat LIGHTPOS_Z = -450.f;
const int TEXDIM = 256;
GLint TEAPOT_X = 0.f;
GLint TEAPOT_Y = -20.f;
GLint TEAPOT_Z = -400.f;
/* create a matrix that will project the desired shadow */
void
shadowmatrix(GLfloat shadowMat[4][4],
GLfloat groundplane[4],
GLfloat lightpos[4])
{
GLfloat dot;
/* find dot product between light position vector and ground plane normal */
dot = groundplane[X] * lightpos[X] +
groundplane[Y] * lightpos[Y] +
groundplane[Z] * lightpos[Z] +
groundplane[W] * lightpos[W];
shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
}
/* find the plane equation given 3 points */
void
findplane(GLfloat plane[4],
GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
{
GLfloat vec0[3], vec1[3];
/* need 2 vectors to find cross product */
vec0[X] = v1[X] - v0[X];
vec0[Y] = v1[Y] - v0[Y];
vec0[Z] = v1[Z] - v0[Z];
vec1[X] = v2[X] - v0[X];
vec1[Y] = v2[Y] - v0[Y];
vec1[Z] = v2[Z] - v0[Z];
/* find cross product to get A, B, and C of plane equation */
plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
}
/* material properties for objects in scene */
static GLfloat wall_mat[] =
{.7f, .75f, 1.f, 0.f};
static GLfloat teapot_mat[] =
{.6f, .1f, 0.1f, 0.f};
static GLfloat cube_mat[] =
{.15f, .1f, 0.4f, 0.7f};
static GLfloat amb_color[] =
{0.8f,0.8f,0.8f,0.5f};
static GLfloat light_dir[] =
{-100.0f,-100.0f,-520.0f,1.0f};
void
shadowColor(void)
{
glColor4f(0.15f, 0.15f, 0.15f, 0.25f);
}
enum {
NONE, SHADOW
};
int rendermode = NONE;
void
teapot(int blend)
{
glPushMatrix();
glTranslatef(0.0,-100.0+25.0,-400.0);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cube_mat);
if(blend) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}
glutSolidCube(50.);
if(blend) {
glDisable(GL_BLEND);
}
glTranslatef(0.0, 46.0,0.0 );
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, teapot_mat);
glMaterialfv(GL_FRONT, GL_SPECULAR, teapot_mat);
glMaterialf(GL_FRONT, GL_SHININESS, 0.2 * 128.0);
glutSolidSphere(20.f,100,100);
// glutSolidTeapot(30.f);
glPopMatrix();
}
void
menu(int mode)
{
rendermode = mode;
glutPostRedisplay();
}
GLfloat leftwallshadow[4][4];
GLfloat rightwallshadow[4][4];
GLfloat backwallshadow[4][4];
GLfloat floorshadow[4][4];
GLfloat lightpos[4];
void
redraw(void)
{
GLfloat *tex;
GLUquadricObj *sphere;
GLfloat plane[4];
GLfloat v0[3], v1[3], v2[3];
////CALCULATING SHADOWS///////////
lightpos[X] = LIGHTPOS_X;
lightpos[Y] = LIGHTPOS_Y;
lightpos[Z] = LIGHTPOS_Z;
lightpos[3] = 1.f;
/* make shadow matricies */
/* 3 points on floor */
v0[X] = -100.f;
v0[Y] = -100.f;
v0[Z] = -320.f;
v1[X] = 100.f;
v1[Y] = -100.f;
v1[Z] = -320.f;
v2[X] = 100.f;
v2[Y] = -100.f;
v2[Z] = -520.f;
findplane(plane, v0, v1, v2);
shadowmatrix(floorshadow, plane, lightpos);
/* 3 points on left wall */
v0[X] = -100.f;
v0[Y] = -100.f;
v0[Z] = -320.f;
v1[X] = -100.f;
v1[Y] = -100.f;
v1[Z] = -520.f;
v2[X] = -100.f;
v2[Y] = 100.f;
v2[Z] = -520.f;
findplane(plane, v0, v1, v2);
shadowmatrix(leftwallshadow, plane, lightpos);
/* 3 points on right wall */
v0[X] = 100.f;
v0[Y] = 100.f;
v0[Z] = -320.f;
v1[X] = 100.f;
v1[Y] = 100.f;
v1[Z] = -520.f;
v2[X] = 100.f;
v2[Y] = -100.f;
v2[Z] = -520.f;
findplane(plane, v0, v1, v2);
shadowmatrix(rightwallshadow, plane, lightpos);
/* 3 points on back wall */
v0[X] = -100.f;
v0[Y] = 100.f;
v0[Z] = -520.f;
v1[X] = 100.f;
v1[Y] = 100.f;
v1[Z] = -520.f;
v2[X] = 100.f;
v2[Y] = -100.f;
v2[Z] = -520.f;
plane[A] = 0.0;
plane[B] = 0.0;
plane[C] = 1.0;
plane[D] = 520.0;
shadowmatrix(backwallshadow, plane, lightpos);
/* place light 0 in the right place */
glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
glLightfv(GL_LIGHT0, GL_DIFFUSE, amb_color);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_dir);
/* remove back faces to speed things up */
glCullFace(GL_BACK);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
/* make display lists for sphere and cone; for efficiency */
glNewList(LIGHT, GL_COMPILE);
sphere = gluNewQuadric();
gluSphere(sphere, 5.f, 20, 20);
gluDeleteQuadric(sphere);
glEndList();
glNewList(FLOOR, GL_COMPILE);
glEndList();
/* load pattern for current 2d texture */
tex = make_texture(TEXDIM, TEXDIM);
glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
free(tex);
//////////////////////////////////
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
/* Note: wall verticies are ordered so they are all front facing this lets
me do back face culling to speed things up. */
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
/* back wall */
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_EQUAL, 1, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glBegin(GL_QUADS);
glNormal3f(0.f, 0.f, 1.f);
glVertex3f(-100.f, -100.f, -520.f);
glVertex3f(100.f, -100.f, -520.f);
glVertex3f(100.f, 100.f, -520.f);
glVertex3f(-100.f, 100.f, -520.f);
glEnd();
glStencilFunc(GL_EQUAL,1,1);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
shadowColor();
glPushMatrix();
glMultMatrixf((GLfloat *) backwallshadow);
teapot(0);
glPopMatrix();
glDisable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
/* floor */
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
/* make the floor textured */
glEnable(GL_TEXTURE_2D);
/* Since we want to turn texturing on for floor only, we have to make floor
a separate glBegin()/glEnd() sequence. You can't turn texturing on and
off between begin and end calls */
glBegin(GL_QUADS);
glNormal3f(0.f, 1.f, 0.f);
glTexCoord2i(0, 0);
glVertex3f(-100.f, -100.f, -320.f);
glTexCoord2i(1, 0);
glVertex3f(100.f, -100.f, -320.f);
glTexCoord2i(1, 1);
glVertex3f(100.f, -100.f, -520.f);
glTexCoord2i(0, 1);
glVertex3f(-100.f, -100.f, -520.f);
glEnd();
glDisable(GL_TEXTURE_2D);
glStencilFunc(GL_NEVER,1,1);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
shadowColor();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glPushMatrix();
glMultMatrixf((GLfloat *) floorshadow);
teapot(0);
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glDisable(GL_STENCIL_TEST);
/* walls */
/* left wall */
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glBegin(GL_QUADS);
glNormal3f(1.f, 0.f, 0.f);
glVertex3f(-100.f, -100.f, -320.f);
glVertex3f(-100.f, -100.f, -520.f);
glVertex3f(-100.f, 100.f, -520.f);
glVertex3f(-100.f, 100.f, -320.f);
glEnd();
glStencilFunc(GL_EQUAL,1,1);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
shadowColor();
glPushMatrix();
glMultMatrixf((GLfloat *) leftwallshadow);
teapot(0);
glPopMatrix();
glDisable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
/* right wall */
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glBegin(GL_QUADS);
glNormal3f(-1.f, 0.f, 0.f);
glVertex3f(100.f, -100.f, -320.f);
glVertex3f(100.f, 100.f, -320.f);
glVertex3f(100.f, 100.f, -520.f);
glVertex3f(100.f, -100.f, -520.f);
glEnd();
glStencilFunc(GL_EQUAL,1,1);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
shadowColor();
glPushMatrix();
glMultMatrixf((GLfloat *) rightwallshadow);
teapot(0);
glPopMatrix();
glDisable(GL_BLEND);
glDisable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
/* ceiling */
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
glBegin(GL_QUADS);
glNormal3f(0.f, -1.f, 0.f);
glVertex3f(-100.f, 100.f, -320.f);
glVertex3f(-100.f, 100.f, -520.f);
glVertex3f(100.f, 100.f, -520.f);
glVertex3f(100.f, 100.f, -320.f);
glEnd();
glPushMatrix();
glTranslatef(lightpos[X], lightpos[Y], lightpos[Z]);
glDisable(GL_LIGHTING);
glColor3f(1.f, 1.f, .7f);
glCallList(LIGHT);
glEnable(GL_LIGHTING);
glPopMatrix();
teapot(1);
glutSwapBuffers(); /* high end machines may need this */
}
/* ARGSUSED1 */
void
key(int key, int x, int y)
{
switch (key) {
case GLUT_KEY_DOWN:
if (LIGHTPOS_Z < -325) LIGHTPOS_Z+=5.f;
break;
case GLUT_KEY_UP:
if (LIGHTPOS_Z > -515) LIGHTPOS_Z-=5.f;
break;
case GLUT_KEY_RIGHT:
if (LIGHTPOS_X < 95) LIGHTPOS_X+=5.f;
break;
case GLUT_KEY_LEFT:
if (LIGHTPOS_X > -95) LIGHTPOS_X-=5.f;
break;
default:
break;
}
glutPostRedisplay();
}
/* Parse arguments, and set up interface between OpenGL and window system */
int
main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL | GLUT_DOUBLE);
(void) glutCreateWindow("projection shadows");
glutDisplayFunc(redraw);
glutSpecialFunc(key);
glutCreateMenu(menu);
glutAddMenuEntry("No Shadows", NONE);
glutAddMenuEntry("Shadows", SHADOW);
glutAttachMenu(GLUT_RIGHT_BUTTON);
/* draw a perspective scene */
glMatrixMode(GL_PROJECTION);
glFrustum(-100., 100., -100., 100., 320., 520.);
glMatrixMode(GL_MODELVIEW);
/* turn on features */
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glutMainLoop();
return 0; /* ANSI C requires main to return int. */
}