projshadow.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:9k
源码类别:

GIS编程

开发平台:

Visual C++

  1. /* projshadow.c - by Tom McReynolds, SGI */
  2. /* Rendering shadows using projective shadows. */
  3. #include <GL/glut.h>
  4. #include <stdlib.h>
  5. /* Create a single component texture map */
  6. GLfloat *
  7. make_texture(int maxs, int maxt)
  8. {
  9.   int s, t;
  10.   static GLfloat *texture;
  11.   texture = (GLfloat *) malloc(maxs * maxt * sizeof(GLfloat));
  12.   for (t = 0; t < maxt; t++) {
  13.     for (s = 0; s < maxs; s++) {
  14.       texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
  15.     }
  16.   }
  17.   return texture;
  18. }
  19. enum {
  20.   SPHERE = 1, CONE, LIGHT, LEFTWALL, FLOOR
  21. };
  22. enum {
  23.   X, Y, Z, W
  24. };
  25. enum {
  26.   A, B, C, D
  27. };
  28. /* create a matrix that will project the desired shadow */
  29. void
  30. shadowmatrix(GLfloat shadowMat[4][4],
  31.   GLfloat groundplane[4],
  32.   GLfloat lightpos[4])
  33. {
  34.   GLfloat dot;
  35.   /* find dot product between light position vector and ground plane normal */
  36.   dot = groundplane[X] * lightpos[X] +
  37.     groundplane[Y] * lightpos[Y] +
  38.     groundplane[Z] * lightpos[Z] +
  39.     groundplane[W] * lightpos[W];
  40.   shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
  41.   shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
  42.   shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
  43.   shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
  44.   shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
  45.   shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
  46.   shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
  47.   shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
  48.   shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
  49.   shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
  50.   shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
  51.   shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
  52.   shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
  53.   shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
  54.   shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
  55.   shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
  56. }
  57. /* find the plane equation given 3 points */
  58. void
  59. findplane(GLfloat plane[4],
  60.   GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
  61. {
  62.   GLfloat vec0[3], vec1[3];
  63.   /* need 2 vectors to find cross product */
  64.   vec0[X] = v1[X] - v0[X];
  65.   vec0[Y] = v1[Y] - v0[Y];
  66.   vec0[Z] = v1[Z] - v0[Z];
  67.   vec1[X] = v2[X] - v0[X];
  68.   vec1[Y] = v2[Y] - v0[Y];
  69.   vec1[Z] = v2[Z] - v0[Z];
  70.   /* find cross product to get A, B, and C of plane equation */
  71.   plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
  72.   plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
  73.   plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
  74.   plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
  75. }
  76. void 
  77. sphere(void)
  78. {
  79.   glPushMatrix();
  80.   glTranslatef(60.f, -50.f, -360.f);
  81.   glCallList(SPHERE);
  82.   glPopMatrix();
  83. }
  84. void 
  85. cone(void)
  86. {
  87.   glPushMatrix();
  88.   glTranslatef(-40.f, -40.f, -400.f);
  89.   glCallList(CONE);
  90.   glPopMatrix();
  91. }
  92. enum {
  93.   NONE, SHADOW
  94. };
  95. int rendermode = NONE;
  96. void
  97. menu(int mode)
  98. {
  99.   rendermode = mode;
  100.   glutPostRedisplay();
  101. }
  102. GLfloat leftwallshadow[4][4];
  103. GLfloat floorshadow[4][4];
  104. GLfloat lightpos[] =
  105. {50.f, 50.f, -320.f, 1.f};
  106. void
  107. redraw(void)
  108. {
  109.   /* material properties for objects in scene */
  110.   static GLfloat wall_mat[] =
  111.   {1.f, 1.f, 1.f, 1.f};
  112.   static GLfloat sphere_mat[] =
  113.   {1.f, .5f, 0.f, 1.f};
  114.   static GLfloat cone_mat[] =
  115.   {0.f, .5f, 1.f, 1.f};
  116.   glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  117.   /* Note: wall verticies are ordered so they are all front facing this lets
  118.      me do back face culling to speed things up.  */
  119.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
  120.   /* floor */
  121.   /* make the floor textured */
  122.   glEnable(GL_TEXTURE_2D);
  123.   /* Since we want to turn texturing on for floor only, we have to make floor 
  124.      a separate glBegin()/glEnd() sequence. You can't turn texturing on and
  125.      off between begin and end calls */
  126.   glBegin(GL_QUADS);
  127.   glNormal3f(0.f, 1.f, 0.f);
  128.   glTexCoord2i(0, 0);
  129.   glVertex3f(-100.f, -100.f, -320.f);
  130.   glTexCoord2i(1, 0);
  131.   glVertex3f(100.f, -100.f, -320.f);
  132.   glTexCoord2i(1, 1);
  133.   glVertex3f(100.f, -100.f, -520.f);
  134.   glTexCoord2i(0, 1);
  135.   glVertex3f(-100.f, -100.f, -520.f);
  136.   glEnd();
  137.   glDisable(GL_TEXTURE_2D);
  138.   if (rendermode == SHADOW) {
  139.     glDisable(GL_DEPTH_TEST);
  140.     glDisable(GL_LIGHTING);
  141.     glColor3f(0.f, 0.f, 0.f);  /* shadow color */
  142.     glPushMatrix();
  143.     glMultMatrixf((GLfloat *) floorshadow);
  144.     cone();
  145.     glPopMatrix();
  146.     glPushMatrix();
  147.     glMultMatrixf((GLfloat *) floorshadow);
  148.     sphere();
  149.     glPopMatrix();
  150.     glEnable(GL_DEPTH_TEST);
  151.     glEnable(GL_LIGHTING);
  152.   }
  153.   /* walls */
  154.   if (rendermode == SHADOW) {
  155.     glEnable(GL_STENCIL_TEST);
  156.     glStencilFunc(GL_ALWAYS, 1, 0);
  157.     glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
  158.   }
  159.   glBegin(GL_QUADS);
  160.   /* left wall */
  161.   glNormal3f(1.f, 0.f, 0.f);
  162.   glVertex3f(-100.f, -100.f, -320.f);
  163.   glVertex3f(-100.f, -100.f, -520.f);
  164.   glVertex3f(-100.f, 100.f, -520.f);
  165.   glVertex3f(-100.f, 100.f, -320.f);
  166.   glEnd();
  167.   if (rendermode == SHADOW) {
  168.     glStencilFunc(GL_EQUAL, 1, 1);
  169.     glDisable(GL_DEPTH_TEST);
  170.     glDisable(GL_LIGHTING);
  171.     glColor3f(0.f, 0.f, 0.f);  /* shadow color */
  172.     glDisable(GL_DEPTH_TEST);
  173.     glPushMatrix();
  174.     glMultMatrixf((GLfloat *) leftwallshadow);
  175.     cone();
  176.     glPopMatrix();
  177.     glEnable(GL_DEPTH_TEST);
  178.     glDisable(GL_STENCIL_TEST);
  179.     glEnable(GL_DEPTH_TEST);
  180.     glEnable(GL_LIGHTING);
  181.   }
  182.   glBegin(GL_QUADS);
  183.   /* right wall */
  184.   glNormal3f(-1.f, 0.f, 0.f);
  185.   glVertex3f(100.f, -100.f, -320.f);
  186.   glVertex3f(100.f, 100.f, -320.f);
  187.   glVertex3f(100.f, 100.f, -520.f);
  188.   glVertex3f(100.f, -100.f, -520.f);
  189.   /* ceiling */
  190.   glNormal3f(0.f, -1.f, 0.f);
  191.   glVertex3f(-100.f, 100.f, -320.f);
  192.   glVertex3f(-100.f, 100.f, -520.f);
  193.   glVertex3f(100.f, 100.f, -520.f);
  194.   glVertex3f(100.f, 100.f, -320.f);
  195.   /* back wall */
  196.   glNormal3f(0.f, 0.f, 1.f);
  197.   glVertex3f(-100.f, -100.f, -520.f);
  198.   glVertex3f(100.f, -100.f, -520.f);
  199.   glVertex3f(100.f, 100.f, -520.f);
  200.   glVertex3f(-100.f, 100.f, -520.f);
  201.   glEnd();
  202.   glPushMatrix();
  203.   glTranslatef(lightpos[X], lightpos[Y], lightpos[Z]);
  204.   glDisable(GL_LIGHTING);
  205.   glColor3f(1.f, 1.f, .7f);
  206.   glCallList(LIGHT);
  207.   glEnable(GL_LIGHTING);
  208.   glPopMatrix();
  209.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
  210.   cone();
  211.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  212.   sphere();
  213.   glutSwapBuffers();    /* high end machines may need this */
  214. }
  215. /* ARGSUSED1 */
  216. void 
  217. key(unsigned char key, int x, int y)
  218. {
  219.   if (key == '33')
  220.     exit(0);
  221. }
  222. const int TEXDIM = 256;
  223. /* Parse arguments, and set up interface between OpenGL and window system */
  224. int
  225. main(int argc, char *argv[])
  226. {
  227.   GLfloat *tex;
  228.   GLUquadricObj *sphere, *cone, *base;
  229.   GLfloat plane[4];
  230.   GLfloat v0[3], v1[3], v2[3];
  231.   glutInit(&argc, argv);
  232.   glutInitWindowSize(512, 512);
  233.   glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL | GLUT_DOUBLE);
  234.   (void) glutCreateWindow("projection shadows");
  235.   glutDisplayFunc(redraw);
  236.   glutKeyboardFunc(key);
  237.   glutCreateMenu(menu);
  238.   glutAddMenuEntry("No Shadows", NONE);
  239.   glutAddMenuEntry("Shadows", SHADOW);
  240.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  241.   /* draw a perspective scene */
  242.   glMatrixMode(GL_PROJECTION);
  243.   glFrustum(-100., 100., -100., 100., 320., 640.);
  244.   glMatrixMode(GL_MODELVIEW);
  245.   /* turn on features */
  246.   glEnable(GL_DEPTH_TEST);
  247.   glEnable(GL_LIGHTING);
  248.   glEnable(GL_LIGHT0);
  249.   /* make shadow matricies */
  250.   /* 3 points on floor */
  251.   v0[X] = -100.f;
  252.   v0[Y] = -100.f;
  253.   v0[Z] = -320.f;
  254.   v1[X] = 100.f;
  255.   v1[Y] = -100.f;
  256.   v1[Z] = -320.f;
  257.   v2[X] = 100.f;
  258.   v2[Y] = -100.f;
  259.   v2[Z] = -520.f;
  260.   findplane(plane, v0, v1, v2);
  261.   shadowmatrix(floorshadow, plane, lightpos);
  262.   /* 3 points on left wall */
  263.   v0[X] = -100.f;
  264.   v0[Y] = -100.f;
  265.   v0[Z] = -320.f;
  266.   v1[X] = -100.f;
  267.   v1[Y] = -100.f;
  268.   v1[Z] = -520.f;
  269.   v2[X] = -100.f;
  270.   v2[Y] = 100.f;
  271.   v2[Z] = -520.f;
  272.   findplane(plane, v0, v1, v2);
  273.   shadowmatrix(leftwallshadow, plane, lightpos);
  274.   /* place light 0 in the right place */
  275.   glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  276.   /* remove back faces to speed things up */
  277.   glCullFace(GL_BACK);
  278.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  279.   /* make display lists for sphere and cone; for efficiency */
  280.   glNewList(SPHERE, GL_COMPILE);
  281.   sphere = gluNewQuadric();
  282.   gluSphere(sphere, 20.f, 20, 20);
  283.   gluDeleteQuadric(sphere);
  284.   glEndList();
  285.   glNewList(LIGHT, GL_COMPILE);
  286.   sphere = gluNewQuadric();
  287.   gluSphere(sphere, 5.f, 20, 20);
  288.   gluDeleteQuadric(sphere);
  289.   glEndList();
  290.   glNewList(CONE, GL_COMPILE);
  291.   cone = gluNewQuadric();
  292.   base = gluNewQuadric();
  293.   glRotatef(-90.f, 1.f, 0.f, 0.f);
  294.   gluDisk(base, 0., 20., 20, 1);
  295.   gluCylinder(cone, 20., 0., 60., 20, 20);
  296.   gluDeleteQuadric(cone);
  297.   gluDeleteQuadric(base);
  298.   glEndList();
  299.   glNewList(FLOOR, GL_COMPILE);
  300.   glEndList();
  301.   glNewList(LEFTWALL, GL_COMPILE);
  302.   glEndList();
  303.   /* load pattern for current 2d texture */
  304.   tex = make_texture(TEXDIM, TEXDIM);
  305.   glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
  306.   free(tex);
  307.   glutMainLoop();
  308.   return 0;             /* ANSI C requires main to return int. */
  309. }