00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <math.h>
00042 #include <GL/glut.h>
00043
00044
00045 #ifndef M_PI
00046 #define M_PI 3.14159265
00047 #endif
00048
00049
00050 static int stencilReflection = 1, stencilShadow = 1, offsetShadow = 1;
00051 static int renderShadow = 1, renderDinosaur = 1, renderReflection = 1;
00052 static int linearFiltering = 0, useMipmaps = 0, useTexture = 1;
00053 static int reportSpeed = 0;
00054 static int animation = 1;
00055 static GLboolean lightSwitch = GL_TRUE;
00056 static int directionalLight = 1;
00057 static int forceExtension = 0;
00058
00059
00060 static float jump = 0.0;
00061 static float lightAngle = 0.0, lightHeight = 20;
00062 GLfloat angle = -150;
00063 GLfloat angle2 = 30;
00064
00065 int moving, startx, starty;
00066 int lightMoving = 0, lightStartX, lightStartY;
00067
00068 enum {
00069 MISSING, EXTENSION, ONE_DOT_ONE
00070 };
00071 int polygonOffsetVersion;
00072
00073 static GLdouble bodyWidth = 3.0;
00074
00075 static GLfloat body[][2] = { {0, 3}, {1, 1}, {5, 1}, {8, 4}, {10, 4}, {11, 5},
00076 {11, 11.5}, {13, 12}, {13, 13}, {10, 13.5}, {13, 14}, {13, 15}, {11, 16},
00077 {8, 16}, {7, 15}, {7, 13}, {8, 12}, {7, 11}, {6, 6}, {4, 3}, {3, 2},
00078 {1, 2} };
00079 static GLfloat arm[][2] = { {8, 10}, {9, 9}, {10, 9}, {13, 8}, {14, 9}, {16, 9},
00080 {15, 9.5}, {16, 10}, {15, 10}, {15.5, 11}, {14.5, 10}, {14, 11}, {14, 10},
00081 {13, 9}, {11, 11}, {9, 11} };
00082 static GLfloat leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0.5}, {9, 0},
00083 {12, 0}, {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7} };
00084 static GLfloat eye[][2] = { {8.75, 15}, {9, 14.7}, {9.6, 14.7}, {10.1, 15},
00085 {9.6, 15.25}, {9, 15.25} };
00086 static GLfloat lightPosition[4];
00087 static GLfloat lightColor[] = {0.8, 1.0, 0.8, 1.0};
00088 static GLfloat skinColor[] = {0.1, 1.0, 0.1, 1.0}, eyeColor[] = {1.0, 0.2, 0.2, 1.0};
00089
00090
00091
00092 static char *circles[] = {
00093 "....xxxx........",
00094 "..xxxxxxxx......",
00095 ".xxxxxxxxxx.....",
00096 ".xxx....xxx.....",
00097 "xxx......xxx....",
00098 "xxx......xxx....",
00099 "xxx......xxx....",
00100 "xxx......xxx....",
00101 ".xxx....xxx.....",
00102 ".xxxxxxxxxx.....",
00103 "..xxxxxxxx......",
00104 "....xxxx........",
00105 "................",
00106 "................",
00107 "................",
00108 "................",
00109 };
00110
00111 static void
00112 makeFloorTexture(void)
00113 {
00114 GLubyte floorTexture[16][16][3];
00115 GLubyte *loc;
00116 int s, t;
00117
00118
00119 loc = (GLubyte*) floorTexture;
00120 for (t = 0; t < 16; t++) {
00121 for (s = 0; s < 16; s++) {
00122 if (circles[t][s] == 'x') {
00123
00124 loc[0] = 0x1f;
00125 loc[1] = 0x8f;
00126 loc[2] = 0x1f;
00127 } else {
00128
00129 loc[0] = 0xaa;
00130 loc[1] = 0xaa;
00131 loc[2] = 0xaa;
00132 }
00133 loc += 3;
00134 }
00135 }
00136
00137 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
00138
00139 if (useMipmaps) {
00140 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
00141 GL_LINEAR_MIPMAP_LINEAR);
00142 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 16, 16,
00143 GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
00144 } else {
00145 if (linearFiltering) {
00146 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00147 } else {
00148 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00149 }
00150 glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0,
00151 GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
00152 }
00153 }
00154
00155 enum {
00156 X, Y, Z, W
00157 };
00158 enum {
00159 A, B, C, D
00160 };
00161
00162
00163 void
00164 shadowMatrix(GLfloat shadowMat[4][4],
00165 GLfloat groundplane[4],
00166 GLfloat lightpos[4])
00167 {
00168 GLfloat dot;
00169
00170
00171 dot = groundplane[X] * lightpos[X] +
00172 groundplane[Y] * lightpos[Y] +
00173 groundplane[Z] * lightpos[Z] +
00174 groundplane[W] * lightpos[W];
00175
00176 shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
00177 shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
00178 shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
00179 shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
00180
00181 shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
00182 shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
00183 shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
00184 shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
00185
00186 shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
00187 shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
00188 shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
00189 shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
00190
00191 shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
00192 shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
00193 shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
00194 shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
00195
00196 }
00197
00198
00199 void
00200 findPlane(GLfloat plane[4],
00201 GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
00202 {
00203 GLfloat vec0[3], vec1[3];
00204
00205
00206 vec0[X] = v1[X] - v0[X];
00207 vec0[Y] = v1[Y] - v0[Y];
00208 vec0[Z] = v1[Z] - v0[Z];
00209
00210 vec1[X] = v2[X] - v0[X];
00211 vec1[Y] = v2[Y] - v0[Y];
00212 vec1[Z] = v2[Z] - v0[Z];
00213
00214
00215 plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
00216 plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
00217 plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
00218
00219 plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
00220 }
00221
00222 void
00223 extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
00224 GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
00225 {
00226 static GLUtriangulatorObj *tobj = NULL;
00227 GLdouble vertex[3], dx, dy, len;
00228 int i;
00229 int count = (int) (dataSize / (2 * sizeof(GLfloat)));
00230
00231 if (tobj == NULL) {
00232 tobj = gluNewTess();
00233
00234 gluTessCallback(tobj, GLU_BEGIN, glBegin);
00235 gluTessCallback(tobj, GLU_VERTEX, glVertex2fv);
00236 gluTessCallback(tobj, GLU_END, glEnd);
00237 }
00238 glNewList(side, GL_COMPILE);
00239 glShadeModel(GL_SMOOTH);
00240
00241 gluBeginPolygon(tobj);
00242 for (i = 0; i < count; i++) {
00243 vertex[0] = data[i][0];
00244 vertex[1] = data[i][1];
00245 vertex[2] = 0;
00246 gluTessVertex(tobj, vertex, data[i]);
00247 }
00248 gluEndPolygon(tobj);
00249 glEndList();
00250 glNewList(edge, GL_COMPILE);
00251 glShadeModel(GL_FLAT);
00252
00253 glBegin(GL_QUAD_STRIP);
00254 for (i = 0; i <= count; i++) {
00255
00256 glVertex3f(data[i % count][0], data[i % count][1], 0.0);
00257 glVertex3f(data[i % count][0], data[i % count][1], thickness);
00258
00259
00260
00261
00262 dx = data[(i + 1) % count][1] - data[i % count][1];
00263 dy = data[i % count][0] - data[(i + 1) % count][0];
00264 len = sqrt(dx * dx + dy * dy);
00265 glNormal3f(dx / len, dy / len, 0.0);
00266 }
00267 glEnd();
00268 glEndList();
00269 glNewList(whole, GL_COMPILE);
00270 glFrontFace(GL_CW);
00271 glCallList(edge);
00272 glNormal3f(0.0, 0.0, -1.0);
00273 glCallList(side);
00274 glPushMatrix();
00275 glTranslatef(0.0, 0.0, thickness);
00276 glFrontFace(GL_CCW);
00277 glNormal3f(0.0, 0.0, 1.0);
00278 glCallList(side);
00279 glPopMatrix();
00280 glEndList();
00281 }
00282
00283
00284 typedef enum {
00285 RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
00286 LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE
00287 } displayLists;
00288
00289 static void
00290 makeDinosaur(void)
00291 {
00292 extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
00293 BODY_SIDE, BODY_EDGE, BODY_WHOLE);
00294 extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
00295 ARM_SIDE, ARM_EDGE, ARM_WHOLE);
00296 extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
00297 LEG_SIDE, LEG_EDGE, LEG_WHOLE);
00298 extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
00299 EYE_SIDE, EYE_EDGE, EYE_WHOLE);
00300 }
00301
00302 static void
00303 drawDinosaur(void)
00304
00305 {
00306 glPushMatrix();
00307
00308 glTranslatef(-8, 0, -bodyWidth / 2);
00309 glTranslatef(0.0, jump, 0.0);
00310 glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
00311 glCallList(BODY_WHOLE);
00312 glTranslatef(0.0, 0.0, bodyWidth);
00313 glCallList(ARM_WHOLE);
00314 glCallList(LEG_WHOLE);
00315 glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
00316 glCallList(ARM_WHOLE);
00317 glTranslatef(0.0, 0.0, -bodyWidth / 4);
00318 glCallList(LEG_WHOLE);
00319 glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
00320 glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
00321 glCallList(EYE_WHOLE);
00322 glPopMatrix();
00323 }
00324
00325 static GLfloat floorVertices[4][3] = {
00326 { -20.0, 0.0, 20.0 },
00327 { 20.0, 0.0, 20.0 },
00328 { 20.0, 0.0, -20.0 },
00329 { -20.0, 0.0, -20.0 },
00330 };
00331
00332
00333 static void
00334 drawFloor(void)
00335 {
00336 glDisable(GL_LIGHTING);
00337
00338 if (useTexture) {
00339 glEnable(GL_TEXTURE_2D);
00340 }
00341
00342 glBegin(GL_QUADS);
00343 glTexCoord2f(0.0, 0.0);
00344 glVertex3fv(floorVertices[0]);
00345 glTexCoord2f(0.0, 16.0);
00346 glVertex3fv(floorVertices[1]);
00347 glTexCoord2f(16.0, 16.0);
00348 glVertex3fv(floorVertices[2]);
00349 glTexCoord2f(16.0, 0.0);
00350 glVertex3fv(floorVertices[3]);
00351 glEnd();
00352
00353 if (useTexture) {
00354 glDisable(GL_TEXTURE_2D);
00355 }
00356
00357 glEnable(GL_LIGHTING);
00358 }
00359
00360 static GLfloat floorPlane[4];
00361 static GLfloat floorShadow[4][4];
00362
00363 static void
00364 redraw(void)
00365 {
00366 int start, end;
00367
00368 if (reportSpeed) {
00369 start = glutGet(GLUT_ELAPSED_TIME);
00370 }
00371
00372
00373 if ((stencilReflection && renderReflection) || (stencilShadow && renderShadow)) {
00374 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
00375 } else {
00376
00377 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00378 }
00379
00380
00381 lightPosition[0] = 12*cos(lightAngle);
00382 lightPosition[1] = lightHeight;
00383 lightPosition[2] = 12*sin(lightAngle);
00384 if (directionalLight) {
00385 lightPosition[3] = 0.0;
00386 } else {
00387 lightPosition[3] = 1.0;
00388 }
00389
00390 shadowMatrix(floorShadow, floorPlane, lightPosition);
00391
00392 glPushMatrix();
00393
00394 glRotatef(angle2, 1.0, 0.0, 0.0);
00395 glRotatef(angle, 0.0, 1.0, 0.0);
00396
00397
00398 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
00399
00400 if (renderReflection) {
00401 if (stencilReflection) {
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 glDisable(GL_DEPTH_TEST);
00412 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
00413
00414
00415 glEnable(GL_STENCIL_TEST);
00416 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
00417 glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
00418
00419
00420 drawFloor();
00421
00422
00423 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00424 glEnable(GL_DEPTH_TEST);
00425
00426
00427 glStencilFunc(GL_EQUAL, 1, 0xffffffff);
00428 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
00429 }
00430
00431 glPushMatrix();
00432
00433
00434
00435 glScalef(1.0, -1.0, 1.0);
00436
00437
00438 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
00439
00440
00441
00442 glEnable(GL_NORMALIZE);
00443 glCullFace(GL_FRONT);
00444
00445
00446 drawDinosaur();
00447
00448
00449 glDisable(GL_NORMALIZE);
00450 glCullFace(GL_BACK);
00451
00452 glPopMatrix();
00453
00454
00455 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
00456
00457 if (stencilReflection) {
00458 glDisable(GL_STENCIL_TEST);
00459 }
00460 }
00461
00462
00463
00464
00465
00466
00467
00468 glFrontFace(GL_CW);
00469 glColor4f(0.1, 0.1, 0.7, 1.0);
00470 drawFloor();
00471 glFrontFace(GL_CCW);
00472
00473 if (renderShadow) {
00474 if (stencilShadow) {
00475
00476
00477
00478 glEnable(GL_STENCIL_TEST);
00479 glStencilFunc(GL_ALWAYS, 3, 0xffffffff);
00480 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
00481 }
00482 }
00483
00484
00485 glEnable(GL_BLEND);
00486 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00487 glColor4f(0.7, 0.0, 0.0, 0.3);
00488 glColor4f(1.0, 1.0, 1.0, 0.3);
00489 drawFloor();
00490 glDisable(GL_BLEND);
00491
00492 if (renderDinosaur) {
00493
00494 drawDinosaur();
00495 }
00496
00497 if (renderShadow) {
00498
00499
00500
00501 if (stencilShadow) {
00502
00503
00504
00505
00506
00507 glStencilFunc(GL_LESS, 2, 0xffffffff);
00508 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
00509 }
00510
00511
00512
00513
00514 if (offsetShadow) {
00515 switch (polygonOffsetVersion) {
00516 case EXTENSION:
00517 #ifdef GL_EXT_polygon_offset
00518 glEnable(GL_POLYGON_OFFSET_EXT);
00519 break;
00520 #endif
00521 #ifdef GL_VERSION_1_1
00522 case ONE_DOT_ONE:
00523 glEnable(GL_POLYGON_OFFSET_FILL);
00524 break;
00525 #endif
00526 case MISSING:
00527
00528 break;
00529 }
00530 }
00531
00532
00533
00534 glEnable(GL_BLEND);
00535 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00536 glDisable(GL_LIGHTING);
00537 glColor4f(0.0, 0.0, 0.0, 0.5);
00538
00539 glPushMatrix();
00540
00541 glMultMatrixf((GLfloat *) floorShadow);
00542 drawDinosaur();
00543 glPopMatrix();
00544
00545 glDisable(GL_BLEND);
00546 glEnable(GL_LIGHTING);
00547
00548 if (offsetShadow) {
00549 switch (polygonOffsetVersion) {
00550 #ifdef GL_EXT_polygon_offset
00551 case EXTENSION:
00552 glDisable(GL_POLYGON_OFFSET_EXT);
00553 break;
00554 #endif
00555 #ifdef GL_VERSION_1_1
00556 case ONE_DOT_ONE:
00557 glDisable(GL_POLYGON_OFFSET_FILL);
00558 break;
00559 #endif
00560 case MISSING:
00561
00562 break;
00563 }
00564 }
00565 if (stencilShadow) {
00566 glDisable(GL_STENCIL_TEST);
00567 }
00568 }
00569
00570 glPushMatrix();
00571 glDisable(GL_LIGHTING);
00572 glColor3f(1.0, 1.0, 0.0);
00573 if (directionalLight) {
00574
00575 glDisable(GL_CULL_FACE);
00576 glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);
00577 glRotatef(lightAngle * -180.0 / M_PI, 0, 1, 0);
00578 glRotatef(atan(lightHeight/12) * 180.0 / M_PI, 0, 0, 1);
00579 glBegin(GL_TRIANGLE_FAN);
00580 glVertex3f(0, 0, 0);
00581 glVertex3f(2, 1, 1);
00582 glVertex3f(2, -1, 1);
00583 glVertex3f(2, -1, -1);
00584 glVertex3f(2, 1, -1);
00585 glVertex3f(2, 1, 1);
00586 glEnd();
00587
00588 glColor3f(1.0, 1.0, 1.0);
00589 glBegin(GL_LINES);
00590 glVertex3f(0, 0, 0);
00591 glVertex3f(5, 0, 0);
00592 glEnd();
00593 glEnable(GL_CULL_FACE);
00594 } else {
00595
00596 glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);
00597 glutSolidSphere(1.0, 5, 5);
00598 }
00599 glEnable(GL_LIGHTING);
00600 glPopMatrix();
00601
00602 glPopMatrix();
00603
00604 if (reportSpeed) {
00605 glFinish();
00606 end = glutGet(GLUT_ELAPSED_TIME);
00607 printf("Speed %.3g frames/sec (%d ms)\n", 1000.0/(end-start), end-start);
00608 }
00609
00610 glutSwapBuffers();
00611 }
00612
00613
00614 static void
00615 mouse(int button, int state, int x, int y)
00616 {
00617 if (button == GLUT_LEFT_BUTTON) {
00618 if (state == GLUT_DOWN) {
00619 moving = 1;
00620 startx = x;
00621 starty = y;
00622 }
00623 if (state == GLUT_UP) {
00624 moving = 0;
00625 }
00626 }
00627 if (button == GLUT_MIDDLE_BUTTON) {
00628 if (state == GLUT_DOWN) {
00629 lightMoving = 1;
00630 lightStartX = x;
00631 lightStartY = y;
00632 }
00633 if (state == GLUT_UP) {
00634 lightMoving = 0;
00635 }
00636 }
00637 }
00638
00639
00640 static void
00641 motion(int x, int y)
00642 {
00643 if (moving) {
00644 angle = angle + (x - startx);
00645 angle2 = angle2 + (y - starty);
00646 startx = x;
00647 starty = y;
00648 glutPostRedisplay();
00649 }
00650 if (lightMoving) {
00651 lightAngle += (x - lightStartX)/40.0;
00652 lightHeight += (lightStartY - y)/20.0;
00653 lightStartX = x;
00654 lightStartY = y;
00655 glutPostRedisplay();
00656 }
00657 }
00658
00659
00660 static void
00661 idle(void)
00662 {
00663 static float time = 0.0;
00664
00665 time = glutGet(GLUT_ELAPSED_TIME) / 500.0;
00666
00667 jump = 4.0 * fabs(sin(time)*0.5);
00668 if (!lightMoving) {
00669 lightAngle += 0.03;
00670 }
00671 glutPostRedisplay();
00672 }
00673
00674 enum {
00675 M_NONE, M_MOTION, M_LIGHT, M_TEXTURE, M_SHADOWS, M_REFLECTION, M_DINOSAUR,
00676 M_STENCIL_REFLECTION, M_STENCIL_SHADOW, M_OFFSET_SHADOW,
00677 M_POSITIONAL, M_DIRECTIONAL, M_PERFORMANCE
00678 };
00679
00680 static void
00681 controlLights(int value)
00682 {
00683 switch (value) {
00684 case M_NONE:
00685 return;
00686 case M_MOTION:
00687 animation = 1 - animation;
00688 if (animation) {
00689 glutIdleFunc(idle);
00690 } else {
00691 glutIdleFunc(NULL);
00692 }
00693 break;
00694 case M_LIGHT:
00695 lightSwitch = !lightSwitch;
00696 if (lightSwitch) {
00697 glEnable(GL_LIGHT0);
00698 } else {
00699 glDisable(GL_LIGHT0);
00700 }
00701 break;
00702 case M_TEXTURE:
00703 useTexture = !useTexture;
00704 break;
00705 case M_SHADOWS:
00706 renderShadow = 1 - renderShadow;
00707 break;
00708 case M_REFLECTION:
00709 renderReflection = 1 - renderReflection;
00710 break;
00711 case M_DINOSAUR:
00712 renderDinosaur = 1 - renderDinosaur;
00713 break;
00714 case M_STENCIL_REFLECTION:
00715 stencilReflection = 1 - stencilReflection;
00716 break;
00717 case M_STENCIL_SHADOW:
00718 stencilShadow = 1 - stencilShadow;
00719 break;
00720 case M_OFFSET_SHADOW:
00721 offsetShadow = 1 - offsetShadow;
00722 break;
00723 case M_POSITIONAL:
00724 directionalLight = 0;
00725 break;
00726 case M_DIRECTIONAL:
00727 directionalLight = 1;
00728 break;
00729 case M_PERFORMANCE:
00730 reportSpeed = 1 - reportSpeed;
00731 break;
00732 }
00733 glutPostRedisplay();
00734 }
00735
00736
00737 static void
00738 visible(int vis)
00739 {
00740 if (vis == GLUT_VISIBLE) {
00741 if (animation)
00742 glutIdleFunc(idle);
00743 } else {
00744 if (!animation)
00745 glutIdleFunc(NULL);
00746 }
00747 }
00748
00749
00750
00751
00752 static void
00753 key(unsigned char c, int x, int y)
00754 {
00755 if (c == 27) {
00756 exit(0);
00757 }
00758 glutPostRedisplay();
00759 }
00760
00761
00762
00763
00764 static void
00765 special(int k, int x, int y)
00766 {
00767 glutPostRedisplay();
00768 }
00769
00770 static int
00771 supportsOneDotOne(void)
00772 {
00773 const char *version;
00774 int major, minor;
00775
00776 version = (char *) glGetString(GL_VERSION);
00777 if (sscanf(version, "%d.%d", &major, &minor) == 2)
00778 return major >= 1 && minor >= 1;
00779 return 0;
00780 }
00781
00782 int
00783 main(int argc, char **argv)
00784 {
00785 int i;
00786
00787 glutInit(&argc, argv);
00788
00789 for (i=1; i<argc; i++) {
00790 if (!strcmp("-linear", argv[i])) {
00791 linearFiltering = 1;
00792 } else if (!strcmp("-mipmap", argv[i])) {
00793 useMipmaps = 1;
00794 } else if (!strcmp("-ext", argv[i])) {
00795 forceExtension = 1;
00796 }
00797 }
00798
00799 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL | GLUT_MULTISAMPLE);
00800
00801 #if 1
00802
00803
00804 glutInitDisplayString("samples stencil>=2 rgb double depth");
00805 #endif
00806
00807 glutCreateWindow("Shadowy Leapin' Lizards");
00808
00809 if (glutGet(GLUT_WINDOW_STENCIL_SIZE) <= 1) {
00810 printf("dinoshade: Sorry, I need at least 2 bits of stencil.\n");
00811 exit(1);
00812 }
00813
00814
00815 glutDisplayFunc(redraw);
00816 glutMouseFunc(mouse);
00817 glutMotionFunc(motion);
00818 glutVisibilityFunc(visible);
00819 glutKeyboardFunc(key);
00820 glutSpecialFunc(special);
00821
00822 glutCreateMenu(controlLights);
00823
00824 glutAddMenuEntry("Toggle motion", M_MOTION);
00825 glutAddMenuEntry("-----------------------", M_NONE);
00826 glutAddMenuEntry("Toggle light", M_LIGHT);
00827 glutAddMenuEntry("Toggle texture", M_TEXTURE);
00828 glutAddMenuEntry("Toggle shadows", M_SHADOWS);
00829 glutAddMenuEntry("Toggle reflection", M_REFLECTION);
00830 glutAddMenuEntry("Toggle dinosaur", M_DINOSAUR);
00831 glutAddMenuEntry("-----------------------", M_NONE);
00832 glutAddMenuEntry("Toggle reflection stenciling", M_STENCIL_REFLECTION);
00833 glutAddMenuEntry("Toggle shadow stenciling", M_STENCIL_SHADOW);
00834 glutAddMenuEntry("Toggle shadow offset", M_OFFSET_SHADOW);
00835 glutAddMenuEntry("----------------------", M_NONE);
00836 glutAddMenuEntry("Positional light", M_POSITIONAL);
00837 glutAddMenuEntry("Directional light", M_DIRECTIONAL);
00838 glutAddMenuEntry("-----------------------", M_NONE);
00839 glutAddMenuEntry("Toggle performance", M_PERFORMANCE);
00840 glutAttachMenu(GLUT_RIGHT_BUTTON);
00841 makeDinosaur();
00842
00843 #ifdef GL_VERSION_1_1
00844 if (supportsOneDotOne() && !forceExtension) {
00845 polygonOffsetVersion = ONE_DOT_ONE;
00846 glPolygonOffset(-2.0, -1.0);
00847 } else
00848 #endif
00849 {
00850 #ifdef GL_EXT_polygon_offset
00851
00852 if (glutExtensionSupported("GL_EXT_polygon_offset")) {
00853 polygonOffsetVersion = EXTENSION;
00854 glPolygonOffsetEXT(-0.1, -0.002);
00855 } else
00856 #endif
00857 {
00858 polygonOffsetVersion = MISSING;
00859 printf("\ndinoshine: Missing polygon offset.\n");
00860 printf(" Expect shadow depth aliasing artifacts.\n\n");
00861 }
00862 }
00863
00864 glEnable(GL_CULL_FACE);
00865 glEnable(GL_DEPTH_TEST);
00866 glEnable(GL_TEXTURE_2D);
00867 glLineWidth(3.0);
00868
00869 glMatrixMode(GL_PROJECTION);
00870 gluPerspective( 40.0,
00871 1.0,
00872 20.0, 100.0);
00873 glMatrixMode(GL_MODELVIEW);
00874 gluLookAt(0.0, 8.0, 60.0,
00875 0.0, 8.0, 0.0,
00876 0.0, 1.0, 0.);
00877
00878 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
00879 glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
00880 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
00881 glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
00882 glEnable(GL_LIGHT0);
00883 glEnable(GL_LIGHTING);
00884
00885 makeFloorTexture();
00886
00887
00888 findPlane(floorPlane, floorVertices[1], floorVertices[2], floorVertices[3]);
00889
00890 glutMainLoop();
00891 return 0;
00892 }