2 /* This demo has been modified to use the Bullet C-API.
3 The C-API is minimal, and will develop based on developer feedback.
4 The C++ API is recommended, and compatible with the C-API.
7 /* Copyright (c) Mark J. Kilgard, 1994, 1997. */
9 /* This program is freely distributable without licensing fees
10 and is provided without guarantee or warrantee expressed or
11 implied. This program is -not- in the public domain. */
13 /* Example for PC game developers to show how to *combine* texturing,
14 reflections, and projected shadows all in real-time with OpenGL.
15 Robust reflections use stenciling. Robust projected shadows
16 use both stenciling and polygon offset. PC game programmers
17 should realize that neither stenciling nor polygon offset are
18 supported by Direct3D, so these real-time rendering algorithms
19 are only really viable with OpenGL.
21 The program has modes for disabling the stenciling and polygon
22 offset uses. It is worth running this example with these features
23 toggled off so you can see the sort of artifacts that result.
25 Notice that the floor texturing, reflections, and shadowing
26 all co-exist properly. */
28 /* When you run this program: Left mouse button controls the
29 view. Middle mouse button controls light position (left &
30 right rotates light around dino; up & down moves light
31 position up and down). Right mouse button pops up menu. */
33 /* Check out the comments in the "redraw" routine to see how the
34 reflection blending and surface stenciling is done. You can
35 also see in "redraw" how the projected shadows are rendered,
36 including the use of stenciling and polygon offset. */
38 /* This program is derived from glutdino.c */
40 /* Compile: cc -o dinoshade dinoshade.c -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm */
45 #include <math.h> /* for cos(), sin(), and sqrt() */
46 #ifdef WIN32//for glut.h
57 #if defined(__APPLE__) && !defined (VMDMESA)
58 #include <OpenGL/gl.h>
59 #include <OpenGL/glu.h>
60 #include <GLUT/glut.h>
61 #define GLVOIDPTR GLvoid(*)()
65 #define GLVOIDPTR void(CALLBACK*)()
68 /* Some <math.h> files do not define M_PI... */
70 #define M_PI 3.14159265
74 //#include "../../include/Bullet-C-Api.h"
75 #include "Bullet-C-Api.h"
79 plPhysicsSdkHandle physicsSdk=0;
80 plDynamicsWorldHandle dynamicsWorld=0;
81 plRigidBodyHandle floorRigidBody;
82 plRigidBodyHandle dinoRigidBody;
84 /* Variable controlling various rendering modes. */
85 static int stencilReflection = 1, stencilShadow = 1, offsetShadow = 1;
86 static int renderShadow = 1, renderDinosaur = 1, renderReflection = 1;
87 static int linearFiltering = 0, useMipmaps = 0, useTexture = 1;
88 static int reportSpeed = 0;
89 static int animation = 1;
90 static GLboolean lightSwitch = GL_TRUE;
91 static int directionalLight = 1;
92 static int forceExtension = 0;
94 /* Time varying or user-controled variables. */
95 static float jump = 0.0;
96 static float lightAngle = 0.0, lightHeight = 20;
97 GLfloat angle = -150; /* in degrees */
98 GLfloat angle2 = 30; /* in degrees */
100 int moving, startx, starty;
101 int lightMoving = 0, lightStartX, lightStartY;
104 MISSING, EXTENSION, ONE_DOT_ONE
106 int polygonOffsetVersion;
108 static GLdouble bodyWidth = 3.0;
110 static GLfloat body[][2] = { {0, 3}, {1, 1}, {5, 1}, {8, 4}, {10, 4}, {11, 5},
111 {11, 11.5}, {13, 12}, {13, 13}, {10, 13.5}, {13, 14}, {13, 15}, {11, 16},
112 {8, 16}, {7, 15}, {7, 13}, {8, 12}, {7, 11}, {6, 6}, {4, 3}, {3, 2},
114 static GLfloat arm[][2] = { {8, 10}, {9, 9}, {10, 9}, {13, 8}, {14, 9}, {16, 9},
115 {15, 9.5}, {16, 10}, {15, 10}, {15.5, 11}, {14.5, 10}, {14, 11}, {14, 10},
116 {13, 9}, {11, 11}, {9, 11} };
117 static GLfloat leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0.5}, {9, 0},
118 {12, 0}, {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7} };
119 static GLfloat eye[][2] = { {8.75, 15}, {9, 14.7}, {9.6, 14.7}, {10.1, 15},
120 {9.6, 15.25}, {9, 15.25} };
121 static GLfloat lightPosition[4];
122 static GLfloat lightColor[] = {0.8, 1.0, 0.8, 1.0}; /* green-tinted */
123 static GLfloat skinColor[] = {0.1, 1.0, 0.1, 1.0}, eyeColor[] = {1.0, 0.2, 0.2, 1.0};
126 /* Nice floor texture tiling pattern. */
127 static char *circles[] = {
147 makeFloorTexture(void)
149 GLubyte floorTexture[16][16][3];
154 /* Setup RGB image for the texture. */
155 loc = (GLubyte*) floorTexture;
156 for (t = 0; t < 16; t++) {
157 for (s = 0; s < 16; s++) {
158 if (circles[t][s] == 'x') {
173 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
177 GL_LINEAR_MIPMAP_LINEAR);
178 gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 16, 16,
179 GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
181 if (linearFiltering) {
182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
186 glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0,
187 GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
198 /* Create a matrix that will project the desired shadow. */
200 shadowMatrix(GLfloat shadowMat[4][4],
201 GLfloat groundplane[4],
206 /* Find dot product between light position vector and ground plane normal. */
207 dot = groundplane[X] * lightpos[X] +
208 groundplane[Y] * lightpos[Y] +
209 groundplane[Z] * lightpos[Z] +
210 groundplane[W] * lightpos[W];
212 shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
213 shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
214 shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
215 shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
217 shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
218 shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
219 shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
220 shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
222 shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
223 shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
224 shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
225 shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
227 shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
228 shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
229 shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
230 shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
234 /* Find the plane equation given 3 points. */
236 findPlane(GLfloat plane[4],
237 GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
239 GLfloat vec0[3], vec1[3];
241 /* Need 2 vectors to find cross product. */
242 vec0[X] = v1[X] - v0[X];
243 vec0[Y] = v1[Y] - v0[Y];
244 vec0[Z] = v1[Z] - v0[Z];
246 vec1[X] = v2[X] - v0[X];
247 vec1[Y] = v2[Y] - v0[Y];
248 vec1[Z] = v2[Z] - v0[Z];
250 /* find cross product to get A, B, and C of plane equation */
251 plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
252 plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
253 plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
255 plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
259 extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize,
260 GLdouble thickness, GLuint side, GLuint edge, GLuint whole)
262 static GLUtriangulatorObj *tobj = NULL;
263 GLdouble vertex[3], dx, dy, len;
265 int count = dataSize / (2 * sizeof(GLfloat));
268 tobj = gluNewTess(); /* create and initialize a GLU
269 polygon * * tesselation object */
270 gluTessCallback(tobj, (GLenum)GLU_BEGIN, (GLVOIDPTR)glBegin);
271 gluTessCallback(tobj, (GLenum)GLU_VERTEX, (GLVOIDPTR)glVertex2fv); /* semi-tricky */
272 gluTessCallback(tobj, (GLenum)GLU_END, (GLVOIDPTR)glEnd);
274 glNewList(side, GL_COMPILE);
275 glShadeModel(GL_SMOOTH); /* smooth minimizes seeing
277 gluBeginPolygon(tobj);
278 for (i = 0; i < count; i++) {
279 vertex[0] = data[i][0];
280 vertex[1] = data[i][1];
282 gluTessVertex(tobj, vertex, data[i]);
286 glNewList(edge, GL_COMPILE);
287 glShadeModel(GL_FLAT); /* flat shade keeps angular hands
288 from being "smoothed" */
289 glBegin(GL_QUAD_STRIP);
290 for (i = 0; i <= count; i++) {
291 /* mod function handles closing the edge */
292 glVertex3f(data[i % count][0], data[i % count][1], 0.0);
293 glVertex3f(data[i % count][0], data[i % count][1], thickness);
294 /* Calculate a unit normal by dividing by Euclidean
295 distance. We * could be lazy and use
296 glEnable(GL_NORMALIZE) so we could pass in * arbitrary
297 normals for a very slight performance hit. */
298 dx = data[(i + 1) % count][1] - data[i % count][1];
299 dy = data[i % count][0] - data[(i + 1) % count][0];
300 len = sqrt(dx * dx + dy * dy);
301 glNormal3f(dx / len, dy / len, 0.0);
305 glNewList(whole, GL_COMPILE);
308 glNormal3f(0.0, 0.0, -1.0); /* constant normal for side */
311 glTranslatef(0.0, 0.0, thickness);
313 glNormal3f(0.0, 0.0, 1.0); /* opposite normal for other side */
319 /* Enumerants for refering to display lists. */
321 RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
322 LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE
328 extrudeSolidFromPolygon(body, sizeof(body), bodyWidth,
329 BODY_SIDE, BODY_EDGE, BODY_WHOLE);
330 extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4,
331 ARM_SIDE, ARM_EDGE, ARM_WHOLE);
332 extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2,
333 LEG_SIDE, LEG_EDGE, LEG_WHOLE);
334 extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2,
335 EYE_SIDE, EYE_EDGE, EYE_WHOLE);
345 /* Translate the dinosaur to be at (0,8,0). */
347 plGetOpenGLMatrix(dinoRigidBody,matrix);
348 // plGetPosition(dinoRigidBody,dinoWorldPos);
349 // glTranslatef(-8, 0, -bodyWidth / 2);
350 //glTranslatef(0.0, jump, 0.0);
351 // glTranslatef(dinoWorldPos[0],dinoWorldPos[1],dinoWorldPos[2]);
353 #ifdef BT_USE_DOUBLE_PRECISION
354 glMultMatrixd(matrix);
356 glMultMatrixf(matrix);
358 // glutSolidCube(15);
359 glTranslatef(-8.5, -8.5, 0);
361 glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
362 glCallList(BODY_WHOLE);
363 glTranslatef(0.0, 0.0, bodyWidth);
364 glCallList(ARM_WHOLE);
365 glCallList(LEG_WHOLE);
366 glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
367 glCallList(ARM_WHOLE);
368 glTranslatef(0.0, 0.0, -bodyWidth / 4);
369 glCallList(LEG_WHOLE);
370 glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
371 glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
372 glCallList(EYE_WHOLE);
378 static GLfloat floorVertices[4][3] = {
379 { -20.0, 0.0, 20.0 },
381 { 20.0, 0.0, -20.0 },
382 { -20.0, 0.0, -20.0 },
385 /* Draw a floor (possibly textured). */
389 glDisable(GL_LIGHTING);
392 glEnable(GL_TEXTURE_2D);
396 glTexCoord2f(0.0, 0.0);
397 glVertex3fv(floorVertices[0]);
398 glTexCoord2f(0.0, 16.0);
399 glVertex3fv(floorVertices[1]);
400 glTexCoord2f(16.0, 16.0);
401 glVertex3fv(floorVertices[2]);
402 glTexCoord2f(16.0, 0.0);
403 glVertex3fv(floorVertices[3]);
407 glDisable(GL_TEXTURE_2D);
410 glEnable(GL_LIGHTING);
413 static GLfloat floorPlane[4];
414 static GLfloat floorShadow[4][4];
419 int start = 0, end = 0 ;
422 start = glutGet(GLUT_ELAPSED_TIME);
425 /* Clear; default stencil clears to zero. */
426 if ((stencilReflection && renderReflection) || (stencilShadow && renderShadow)) {
427 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
429 /* Avoid clearing stencil when not using it. */
430 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
433 /* Reposition the light source. */
434 lightPosition[0] = 12*cos(lightAngle);
435 lightPosition[1] = lightHeight;
436 lightPosition[2] = 12*sin(lightAngle);
437 if (directionalLight) {
438 lightPosition[3] = 0.0;
440 lightPosition[3] = 1.0;
443 shadowMatrix(floorShadow, floorPlane, lightPosition);
446 /* Perform scene rotations based on user mouse input. */
447 glRotatef(angle2, 1.0, 0.0, 0.0);
448 glRotatef(angle, 0.0, 1.0, 0.0);
450 /* Tell GL new light source position. */
451 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
453 if (renderReflection) {
454 if (stencilReflection) {
455 /* We can eliminate the visual "artifact" of seeing the "flipped"
456 dinosaur underneath the floor by using stencil. The idea is
457 draw the floor without color or depth update but so that
458 a stencil value of one is where the floor will be. Later when
459 rendering the dinosaur reflection, we will only update pixels
460 with a stencil value of 1 to make sure the reflection only
461 lives on the floor, not below the floor. */
463 /* Don't update color or depth. */
464 glDisable(GL_DEPTH_TEST);
465 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
467 /* Draw 1 into the stencil buffer. */
468 glEnable(GL_STENCIL_TEST);
469 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
470 glStencilFunc(GL_ALWAYS, 1, 0xffffffff);
472 /* Now render floor; floor pixels just get their stencil set to 1. */
475 /* Re-enable update of color and depth. */
476 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
477 glEnable(GL_DEPTH_TEST);
479 /* Now, only render where stencil is set to 1. */
480 glStencilFunc(GL_EQUAL, 1, 0xffffffff); /* draw if ==1 */
481 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
486 /* The critical reflection step: Reflect dinosaur through the floor
487 (the Y=0 plane) to make a relection. */
488 glScalef(1.0, -1.0, 1.0);
490 /* Reflect the light position. */
491 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
493 /* To avoid our normals getting reversed and hence botched lighting
494 on the reflection, turn on normalize. */
495 glEnable(GL_NORMALIZE);
496 glCullFace(GL_FRONT);
498 /* Draw the reflected dinosaur. */
501 /* Disable noramlize again and re-enable back face culling. */
502 glDisable(GL_NORMALIZE);
507 /* Switch back to the unreflected light position. */
508 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
510 if (stencilReflection) {
511 glDisable(GL_STENCIL_TEST);
515 /* Back face culling will get used to only draw either the top or the
516 bottom floor. This let's us get a floor with two distinct
517 appearances. The top floor surface is reflective and kind of red.
518 The bottom floor surface is not reflective and blue. */
520 /* Draw "bottom" of floor in blue. */
521 glFrontFace(GL_CW); /* Switch face orientation. */
522 glColor4f(0.1, 0.1, 0.7, 1.0);
528 /* Draw the floor with stencil value 3. This helps us only
529 draw the shadow once per floor pixel (and only on the
531 glEnable(GL_STENCIL_TEST);
532 glStencilFunc(GL_ALWAYS, 3, 0xffffffff);
533 glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
537 /* Draw "top" of floor. Use blending to blend in reflection. */
539 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
540 glColor4f(0.7, 0.0, 0.0, 0.3);
541 glColor4f(1.0, 1.0, 1.0, 0.3);
545 if (renderDinosaur) {
546 /* Draw "actual" dinosaur, not its reflection. */
552 /* Render the projected shadow. */
556 /* Now, only render where stencil is set above 2 (ie, 3 where
557 the top floor is). Update stencil with 2 where the shadow
558 gets drawn so we don't redraw (and accidently reblend) the
560 glStencilFunc(GL_LESS, 2, 0xffffffff); /* draw if ==1 */
561 glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
564 /* To eliminate depth buffer artifacts, we use polygon offset
565 to raise the depth of the projected shadow slightly so
566 that it does not depth buffer alias with the floor. */
568 switch (polygonOffsetVersion) {
570 #ifdef GL_VERSION_1_1
572 glEnable(GL_POLYGON_OFFSET_FILL);
581 /* Render 50% black shadow color on top of whatever the
582 floor appareance is. */
584 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
585 glDisable(GL_LIGHTING); /* Force the 50% black. */
586 glColor4f(0.0, 0.0, 0.0, 0.5);
589 /* Project the shadow. */
590 glMultMatrixf((GLfloat *) floorShadow);
595 glEnable(GL_LIGHTING);
598 switch (polygonOffsetVersion) {
599 #ifdef GL_VERSION_1_1
601 glDisable(GL_POLYGON_OFFSET_FILL);
610 glDisable(GL_STENCIL_TEST);
615 glDisable(GL_LIGHTING);
616 glColor3f(1.0, 1.0, 0.0);
617 if (directionalLight) {
618 /* Draw an arrowhead. */
619 glDisable(GL_CULL_FACE);
620 glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);
621 glRotatef(lightAngle * -180.0 / M_PI, 0, 1, 0);
622 glRotatef(atan(lightHeight/12) * 180.0 / M_PI, 0, 0, 1);
623 glBegin(GL_TRIANGLE_FAN);
626 glVertex3f(2, -1, 1);
627 glVertex3f(2, -1, -1);
628 glVertex3f(2, 1, -1);
631 /* Draw a white line from light direction. */
632 glColor3f(1.0, 1.0, 1.0);
637 glEnable(GL_CULL_FACE);
639 /* Draw a yellow ball at the light source. */
640 glTranslatef(lightPosition[0], lightPosition[1], lightPosition[2]);
641 glutSolidSphere(1.0, 5, 5);
643 glEnable(GL_LIGHTING);
650 end = glutGet(GLUT_ELAPSED_TIME);
651 printf("Speed %.3g frames/sec (%d ms)\n", 1000.0/(end-start), end-start);
659 mouse(int button, int state, int x, int y)
661 if (button == GLUT_LEFT_BUTTON) {
662 if (state == GLUT_DOWN) {
667 if (state == GLUT_UP) {
671 if (button == GLUT_MIDDLE_BUTTON) {
672 if (state == GLUT_DOWN) {
677 if (state == GLUT_UP) {
688 angle = angle + (x - startx);
689 angle2 = angle2 + (y - starty);
694 if (0){//lightMoving) {
695 lightAngle += (x - lightStartX)/40.0;
696 lightHeight += (lightStartY - y)/20.0;
703 /* Advance time varying state when idle callback registered. */
707 static float time = 0.0;
708 static float prevtime = 0.0;
712 time = glutGet(GLUT_ELAPSED_TIME) / 500.0;
713 dtime = time - prevtime;
715 jump = 4.0 * fabs(sin(time)*0.5);
721 plStepSimulation(dynamicsWorld,dtime);
727 M_NONE, M_MOTION, M_LIGHT, M_TEXTURE, M_SHADOWS, M_REFLECTION, M_DINOSAUR,
728 M_STENCIL_REFLECTION, M_STENCIL_SHADOW, M_OFFSET_SHADOW,
729 M_POSITIONAL, M_DIRECTIONAL, M_PERFORMANCE
733 controlLights(int value)
739 animation = 1 - animation;
747 lightSwitch = !lightSwitch;
751 glDisable(GL_LIGHT0);
755 useTexture = !useTexture;
758 renderShadow = 1 - renderShadow;
761 renderReflection = 1 - renderReflection;
764 renderDinosaur = 1 - renderDinosaur;
766 case M_STENCIL_REFLECTION:
767 stencilReflection = 1 - stencilReflection;
769 case M_STENCIL_SHADOW:
770 stencilShadow = 1 - stencilShadow;
772 case M_OFFSET_SHADOW:
773 offsetShadow = 1 - offsetShadow;
776 directionalLight = 0;
779 directionalLight = 1;
782 reportSpeed = 1 - reportSpeed;
788 /* When not visible, stop animating. Restart when visible again. */
792 if (vis == GLUT_VISIBLE) {
801 /* Press any key to redraw; good when motion stopped and
802 performance reporting on. */
805 key(unsigned char c, int x, int y)
808 exit(0); /* IRIS GLism, Escape quits. */
813 /* Press any key to redraw; good when motion stopped and
814 performance reporting on. */
817 special(int k, int x, int y)
823 supportsOneDotOne(void)
828 version = (char *) glGetString(GL_VERSION);
829 if (sscanf(version, "%d.%d", &major, &minor) == 2)
830 return ((major > 1) || (major >= 1 && minor >= 1));
831 return 0; /* OpenGL version string malformed! */
836 main(int argc, char **argv)
839 plCollisionShapeHandle floorShape;
840 plCollisionShapeHandle dinoShape,dinoChildShape;
841 plVector3 floorPos,childPos;
843 plQuaternion childOrn,dinoOrient;
845 void* user_data=NULL;
847 physicsSdk = plNewBulletSdk();
848 dynamicsWorld = plCreateDynamicsWorld(physicsSdk);
850 //create ground plane
852 floorShape = plNewConvexHullShape();
857 plAddVertex(floorShape,floorVertices[i][0],floorVertices[i][1],floorVertices[i][2]);
861 floorShape = plNewBoxShape(120,0,120);
863 floorRigidBody = plCreateRigidBody(user_data,0.f,floorShape);
868 plSetPosition(floorRigidBody,floorPos);
869 plAddRigidBody(dynamicsWorld,floorRigidBody);
871 //create dino rigidbody
872 dinoChildShape = plNewBoxShape(8.5,8.5,8.5);
873 dinoShape = plNewCompoundShape();
882 plAddChildShape(dinoShape,dinoChildShape,childPos,childOrn);
884 dinoPos[0] = -10; dinoPos[1] = 28; dinoPos[2] = 0;
885 dinoRigidBody = plCreateRigidBody(0,1.0,dinoShape);
886 plSetPosition(dinoRigidBody,dinoPos);
887 plSetEuler(0,0,3.15*0.20,dinoOrient);
888 plSetOrientation(dinoRigidBody,dinoOrient);
890 plAddRigidBody(dynamicsWorld,dinoRigidBody);
892 printf("BulletDino\n");
893 glutInit(&argc, argv);
895 for (i=1; i<argc; i++) {
896 if (!strcmp("-linear", argv[i])) {
898 } else if (!strcmp("-mipmap", argv[i])) {
900 } else if (!strcmp("-ext", argv[i])) {
905 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL | GLUT_MULTISAMPLE);
908 /* In GLUT 4.0, you'll be able to do this an be sure to
909 get 2 bits of stencil if the machine has it for you. */
910 glutInitDisplayString("samples stencil>=2 rgb double depth");
913 glutCreateWindow("Shadowy Leapin' Lizards");
915 if (glutGet(GLUT_WINDOW_STENCIL_SIZE) <= 1) {
916 printf("dinoshade: Sorry, I need at least 2 bits of stencil.\n");
920 /* Register GLUT callbacks. */
921 glutDisplayFunc(redraw);
922 glutMouseFunc(mouse);
923 glutMotionFunc(motion);
924 glutVisibilityFunc(visible);
925 glutKeyboardFunc(key);
926 glutSpecialFunc(special);
928 glutCreateMenu(controlLights);
930 glutAddMenuEntry("Toggle motion", M_MOTION);
931 glutAddMenuEntry("-----------------------", M_NONE);
932 glutAddMenuEntry("Toggle light", M_LIGHT);
933 glutAddMenuEntry("Toggle texture", M_TEXTURE);
934 glutAddMenuEntry("Toggle shadows", M_SHADOWS);
935 glutAddMenuEntry("Toggle reflection", M_REFLECTION);
936 glutAddMenuEntry("Toggle dinosaur", M_DINOSAUR);
937 glutAddMenuEntry("-----------------------", M_NONE);
938 glutAddMenuEntry("Toggle reflection stenciling", M_STENCIL_REFLECTION);
939 glutAddMenuEntry("Toggle shadow stenciling", M_STENCIL_SHADOW);
940 glutAddMenuEntry("Toggle shadow offset", M_OFFSET_SHADOW);
941 glutAddMenuEntry("----------------------", M_NONE);
942 glutAddMenuEntry("Positional light", M_POSITIONAL);
943 glutAddMenuEntry("Directional light", M_DIRECTIONAL);
944 glutAddMenuEntry("-----------------------", M_NONE);
945 glutAddMenuEntry("Toggle performance", M_PERFORMANCE);
946 glutAttachMenu(GLUT_RIGHT_BUTTON);
949 #ifdef GL_VERSION_1_1
950 if (supportsOneDotOne() && !forceExtension) {
951 polygonOffsetVersion = ONE_DOT_ONE;
952 glPolygonOffset(-2.0, -1.0);
957 polygonOffsetVersion = MISSING;
958 printf("\ndinoshine: Missing polygon offset.\n");
959 printf(" Expect shadow depth aliasing artifacts.\n\n");
963 glEnable(GL_CULL_FACE);
964 glEnable(GL_DEPTH_TEST);
965 glEnable(GL_TEXTURE_2D);
968 glMatrixMode(GL_PROJECTION);
969 gluPerspective( /* field of view in degree */ 40.0,
970 /* aspect ratio */ 1.0,
971 /* Z near */ 20.0, /* Z far */ 100.0);
972 glMatrixMode(GL_MODELVIEW);
973 gluLookAt(0.0, 8.0, 60.0, /* eye is at (0,0,30) */
974 0.0, 8.0, 0.0, /* center is at (0,0,0) */
975 0.0, 1.0, 0.); /* up is in postivie Y direction */
977 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
978 glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColor);
979 glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
980 glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
982 glEnable(GL_LIGHTING);
986 /* Setup floor plane for projected shadow calculations. */
987 findPlane(floorPlane, floorVertices[1], floorVertices[2], floorVertices[3]);
991 plDeleteDynamicsWorld(dynamicsWorld);
992 plDeletePhysicsSdk(physicsSdk);
995 return 0; /* ANSI C requires main to return int. */