Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
12
Добавлен:
01.05.2014
Размер:
17.61 Кб
Скачать
//		Lab 6 in computer graphics.
//      Konstantin Filippov
//		SPb ETU LETI / MOEVM 2007


#include <GL/glut.h>
#include <stdlib.h>
#include "texture.h"

enum {SPHERE = 1, CONE, LIGHT};

enum {X, Y, Z, W};
enum {A, B, C, D};

GLfloat dxCone = -40;
GLfloat dyCone = -40;
GLfloat dzCone = -400;
GLfloat dxShere = 60;
GLfloat dyShere = -50;
GLfloat dzShere = -360;
int sphereStripple = 8;
/* 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]);
}


void sphere(float dx, float dy, float dz)
{
    glPushMatrix();
    glTranslatef(dx, dy, dz);
    glCallList(SPHERE);
    glPopMatrix();
}

void cone(float dx, float dy, float dz)
{
    glPushMatrix();
    glTranslatef(dx, dy, dz);
    glCallList(CONE);
    glPopMatrix();

}

enum {NONE, SHADOW};

//int rendermode = NONE;
int rendermode = SHADOW;

void menu(int mode)
{
  rendermode = mode;
  glutPostRedisplay();
}

GLfloat leftwallshadow[4][4];
GLfloat floorshadow[4][4];
GLfloat rightwallshadow[4][4];
GLfloat backwallshadow[4][4];
GLfloat ceilingshadow[4][4];

GLfloat x = 0;
GLfloat y = 0;
GLfloat z = 0;
GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f};
GLfloat plane[4];
GLfloat v0[3], v1[3], v2[3];
void redraw(void)
{
    /* material properties for objects in scene */
    static GLfloat wall_mat[] = {0.8f, 1.f, 1.f, 1.f};
    static GLfloat sphere_mat[] = {1.f, 1.0f, .1f, .5f};
    static GLfloat cone_mat[] = {0.2f, .5f, .3f, .8f};

    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);

    /* floor */
    if(rendermode == SHADOW)
    {
      /* glClear(GL_STENCIL_BUFFER_BIT); *//* set all stencil bits to 0 */
      glEnable(GL_STENCIL_TEST);
      glStencilFunc(GL_ALWAYS, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    }	
    //glEnable(GL_TEXTURE_2D);
    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);


    if(rendermode == SHADOW) {
    /* clear stencil buffer where shadow is cast */
      glStencilFunc(GL_EQUAL, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
      glDisable(GL_DEPTH_TEST);
      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);

      glPushMatrix();
      glMultMatrixf((GLfloat *)floorshadow);
      cone(dxCone, dyCone, dzCone);
      glPopMatrix();


	  glEnable(GL_POLYGON_STIPPLE);
      glPushMatrix();
      glMultMatrixf((GLfloat *)floorshadow);
      sphere(dxShere, dyShere, dzShere);
      glPopMatrix();
      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);



      /* draw unlit wall where stencil == 0 */
      glDisable(GL_LIGHT0);
      glStencilFunc(GL_EQUAL, 0, 1);
      glDepthFunc(GL_LEQUAL);

      glEnable(GL_TEXTURE_2D);
      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);

      glDepthFunc(GL_LESS);
      glDisable(GL_STENCIL_TEST);
      glEnable(GL_LIGHT0);
    }

    /* walls */

    if(rendermode == SHADOW) {
      glClear(GL_STENCIL_BUFFER_BIT); /* set all stencil bits to 0 */
      glEnable(GL_STENCIL_TEST);
      glStencilFunc(GL_ALWAYS, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    }

    /* set stencil = 1 for entire visible wall */
    /* (masking out floor) */
    glBegin(GL_QUADS);
    /* left wall */
    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();

    if(rendermode == SHADOW) {
      /* clear stencil buffer where shadow is cast */
      glStencilFunc(GL_EQUAL, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
      glDisable(GL_DEPTH_TEST);
      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
      glPushMatrix();
      glMultMatrixf((GLfloat *)leftwallshadow);
      cone(dxCone, dyCone, dzCone);
	  sphere(dxShere, dyShere, dzShere);
      glPopMatrix();
      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      glEnable(GL_DEPTH_TEST);
      glEnable(GL_LIGHTING);
    
      /* draw unlit wall where stencil == 0 */
      glDisable(GL_LIGHT0);
      glStencilFunc(GL_EQUAL, 0, 1);
      glDepthFunc(GL_LEQUAL);

      glBegin(GL_QUADS);
      /* left wall */
      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();

      glDepthFunc(GL_LESS);
      glDisable(GL_STENCIL_TEST);
      glEnable(GL_LIGHT0);
    }


	if(rendermode == SHADOW) {
      glClear(GL_STENCIL_BUFFER_BIT); /* set all stencil bits to 0 */
      glEnable(GL_STENCIL_TEST);
      glStencilFunc(GL_ALWAYS, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    }

    /* set stencil = 1 for entire visible wall */
    /* (masking out floor) */
    glBegin(GL_QUADS);
    /* right wall */
	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();

    if(rendermode == SHADOW) {
      /* clear stencil buffer where shadow is cast */
      glStencilFunc(GL_EQUAL, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
      glDisable(GL_DEPTH_TEST);
      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
      glPushMatrix();
      glMultMatrixf((GLfloat *)rightwallshadow);
      cone(dxCone, dyCone, dzCone);
	  sphere(dxShere, dyShere, dzShere);
      glPopMatrix();
      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      glEnable(GL_DEPTH_TEST);
      glEnable(GL_LIGHTING);
    
      /* draw unlit wall where stencil == 0 */
      glDisable(GL_LIGHT0);
      glStencilFunc(GL_EQUAL, 0, 1);
      glDepthFunc(GL_LEQUAL);

      glBegin(GL_QUADS);
      /* right wall */
	  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();

      glDepthFunc(GL_LESS);
      glDisable(GL_STENCIL_TEST);
      glEnable(GL_LIGHT0);
    }

	if(rendermode == SHADOW) {
      glClear(GL_STENCIL_BUFFER_BIT); /* set all stencil bits to 0 */
      glEnable(GL_STENCIL_TEST);
      glStencilFunc(GL_ALWAYS, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    }

    /* set stencil = 1 for entire visible wall */
    /* (masking out floor) */
    glBegin(GL_QUADS);
    /* ceiling */
    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();

    if(rendermode == SHADOW) {
      /* clear stencil buffer where shadow is cast */
      glStencilFunc(GL_EQUAL, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
      glDisable(GL_DEPTH_TEST);
      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
      glPushMatrix();
      glMultMatrixf((GLfloat *)ceilingshadow);
      cone(dxCone, dyCone, dzCone);
	  sphere(dxShere, dyShere, dzShere);
      glPopMatrix();
      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      glEnable(GL_DEPTH_TEST);
      glEnable(GL_LIGHTING);
    
      /* draw unlit wall where stencil == 0 */
      glDisable(GL_LIGHT0);
      glStencilFunc(GL_EQUAL, 0, 1);
      glDepthFunc(GL_LEQUAL);

      glBegin(GL_QUADS);
      /* ceiling */
      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();

      glDepthFunc(GL_LESS);
      glDisable(GL_STENCIL_TEST);
      glEnable(GL_LIGHT0);
    }

	if(rendermode == SHADOW) {
      glClear(GL_STENCIL_BUFFER_BIT); /* set all stencil bits to 0 */
      glEnable(GL_STENCIL_TEST);
      glStencilFunc(GL_ALWAYS, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    }

    /* set stencil = 1 for entire visible wall */
    /* (masking out floor) */
    glBegin(GL_QUADS);
    /* back wall */
    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();

    if(rendermode == SHADOW) {
      /* clear stencil buffer where shadow is cast */
      glStencilFunc(GL_EQUAL, 1, 1);
      glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO);
      glDisable(GL_DEPTH_TEST);
      glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
      glPushMatrix();
      glMultMatrixf((GLfloat *)backwallshadow);
      cone(dxCone, dyCone, dzCone);
	  sphere(dxShere, dyShere, dzShere);
      glPopMatrix();
      glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
      glEnable(GL_DEPTH_TEST);
      glEnable(GL_LIGHTING);
    
      /* draw unlit wall where stencil == 0 */
      glDisable(GL_LIGHT0);
      glStencilFunc(GL_EQUAL, 0, 1);
      glDepthFunc(GL_LEQUAL);

      glBegin(GL_QUADS);
      /* back wall */
      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();

      glDepthFunc(GL_LESS);
      glDisable(GL_STENCIL_TEST);
      glEnable(GL_LIGHT0);
    }

    glPushMatrix();
    //glTranslatef(lightpos[X], lightpos[Y], lightpos[Z]);
    glDisable(GL_LIGHTING);
    glColor3f(1.f, 1.f, .7f);
    glCallList(LIGHT);
    glEnable(GL_LIGHTING);
    glPopMatrix();

	glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
	/* 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] = -320.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 ceiling */
      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(ceilingshadow, 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;

	  findplane(plane, v0, v1, v2);
      shadowmatrix(backwallshadow, plane, lightpos);


    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
    cone(dxCone, dyCone, dzCone);

    glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
    sphere(dxShere, dyShere, dzShere);

    glutSwapBuffers(); /* high end machines may need this */
}

void key(unsigned char key, int x, int y) 
{
    switch(key) 
	{
    case 'q': 
		dxCone = dxCone - 10;
	break;
	case 'w': 
		dxCone = dxCone + 10;
	break;
	case 'a': 
		dyCone = dyCone - 10;
	break;
	case 's': 
		dyCone = dyCone + 10;
	break;
	case 'z': 
		dzCone = dzCone - 10;
	break;
	case 'x': 
		dzCone = dzCone + 10;
	break;

	case 'e': 
		dxShere = dxShere - 10;
	break;
	case 'r': 
		dxShere = dxShere + 10;
	break;
	case 'd': 
		dyShere= dyShere - 10;
	break;
	case 'f': 
		dyShere = dyShere + 10;
	break;
	case 'c': 
		dzShere = dzShere - 10;
	break;
	case 'v': 
		dzShere = dzShere + 10;
	break;

	case 't': 
		lightpos[0] = lightpos[0] - 10;
	break;
	case 'y': 
		lightpos[0] = lightpos[0] + 10;
	break;
	case 'g': 
		lightpos[1] = lightpos[1] - 10;
	break;
	case 'h': 
		lightpos[1] = lightpos[1] + 10;
	break;
	case 'b': 
		lightpos[2] = lightpos[2] - 10;
	break;
	case 'n': 
		lightpos[2] = lightpos[2] + 10;
	break;

    case '\033': 
		exit(0); 
	break;
	default:
		//help();
	break;
    }

}

const int TEXDIM = 256;

main(int argc, char *argv[])
{
    int texwid, texht, texcomps;
	
    unsigned int *tex;
    GLUquadricObj *sphere, *cone, *base;
    //GLfloat plane[4];
    //GLfloat v0[3], v1[3], v2[3];

    glutInit(&argc, argv);
    glutInitWindowSize(512, 512);
    glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL|GLUT_DOUBLE);
    (void)glutCreateWindow("KG Lab 6 Task 1.5");
    glutDisplayFunc(redraw);
    glutKeyboardFunc(key);
	glutIdleFunc(redraw); 
	        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/*
    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., 640.); 
    glMatrixMode(GL_MODELVIEW);

    /* turn on features */
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);

    /* place light 0 in the right place */

    //glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

    /* remove back faces to speed things up */
    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    /* make display lists for sphere and cone; for efficiency */

    glNewList(SPHERE, GL_COMPILE);
    sphere = gluNewQuadric();
    gluSphere(sphere, 20.f, 20, 20);
    gluDeleteQuadric(sphere);
    glEndList();

    glNewList(LIGHT, GL_COMPILE);
    sphere = gluNewQuadric();
    gluSphere(sphere, 5.f, 20, 20);
    gluDeleteQuadric(sphere);
    glEndList();

    glNewList(CONE, GL_COMPILE);
    cone = gluNewQuadric();
    base = gluNewQuadric();
    glRotatef(-90.f, 1.f, 0.f, 0.f);

    gluDisk(base, 0., 20., 20, 1);
    gluCylinder(cone, 20., 0., 60., 20, 20);
    gluDeleteQuadric(cone);
    gluDeleteQuadric(base);
    glEndList();

    tex = read_texture("wood0.rgb", &texwid, &texht, &texcomps);

    glTexImage2D(GL_TEXTURE_2D, 0, texcomps, texwid, texht, 0, GL_RGBA, 
		 GL_UNSIGNED_BYTE, tex);
    free(tex);

    glutMainLoop();
    return 0;
}
Соседние файлы в папке Лабораторная работа №6
  • #
    01.05.2014388 б12Makefile.sgi
  • #
    01.05.2014815 б12Makefile.win
  • #
    01.05.20142.12 Кб12projshadow.001
  • #
    01.05.201417.61 Кб12projshadow.c
  • #
    01.05.20142.17 Кб13projshadow.dsp
  • #
    01.05.2014545 б12projshadow.dsw
  • #
    01.05.201441.98 Кб12projshadow.ncb
  • #
    01.05.201425.46 Кб12projshadow.obj
  • #
    01.05.201448.64 Кб12projshadow.opt