#include "stdafx.h" GLboolean bCull = (GLboolean)true, bDepth= (GLboolean)true, bOutline=(GLboolean)true, bShade= (GLboolean)true; GLfloat ambientLight[] = { 0.3f, 0.3f, 0.3f, 1.0f }, diffuseLight[] = { 0.7f, 0.7f, 0.7f, 1.0f }, specular[] = { 1.0f, 1.0f, 1.0f, 1.0f}, specref[] = { 1.0f, 1.0f, 1.0f, 1.0f }, // The light is positioned by this code, located in the ChangeSize function: lightPos[] = { 35.0f, 35.0f, 25.0f, 1.0f }, //{ -30.f, 4.0f, 15.0f, 1.0f }; fLightPosMirror[4], ex=0.0f, ey=1.0f, ez=30.0f, cx=0.0f, cy=-0.4f, cz=0.0, deltaC=0.1f, delta= 0.01f, deltaR= 0.01f, deltatrans=0.05f, shadowMat[16], vGroundPlane[4];// = {0.0f, 1.0f, 0.0f, 0.4f}; GLsizei wSize=500, hSize =500; #define NUM_SPHERES 50 GLTFrame spheres[NUM_SPHERES]; GLfloat yground = -0.4f; GLfloat yRot = 0.0f; // Rotation angle for animation GLfloat fExtent = 20.0f; void gltMakeShadowMatrix(GLfloat vPlaneEquation[], GLfloat vLightPos[], GLfloat destMat[]) { GLfloat dot; // Dot product of plane and light position dot = vPlaneEquation[0]*vLightPos[0] + vPlaneEquation[1]*vLightPos[1] + vPlaneEquation[2]*vLightPos[2] + vPlaneEquation[3]*vLightPos[3]; // Now do the projection // First column destMat[0] = dot - vLightPos[0] * vPlaneEquation[0]; destMat[4] = 0.0f - vLightPos[0] * vPlaneEquation[1]; destMat[8] = 0.0f - vLightPos[0] * vPlaneEquation[2]; destMat[12] = 0.0f - vLightPos[0] * vPlaneEquation[3]; // Second column destMat[1] = 0.0f - vLightPos[1] * vPlaneEquation[0]; destMat[5] = dot - vLightPos[1] * vPlaneEquation[1]; destMat[9] = 0.0f - vLightPos[1] * vPlaneEquation[2]; destMat[13] = 0.0f - vLightPos[1] * vPlaneEquation[3]; // Third Column destMat[2] = 0.0f - vLightPos[2] * vPlaneEquation[0]; destMat[6] = 0.0f - vLightPos[2] * vPlaneEquation[1]; destMat[10] = dot - vLightPos[2] * vPlaneEquation[2]; destMat[14] = 0.0f - vLightPos[2] * vPlaneEquation[3]; // Fourth Column destMat[3] = 0.0f - vLightPos[3] * vPlaneEquation[0]; destMat[7] = 0.0f - vLightPos[3] * vPlaneEquation[1]; destMat[11] = 0.0f - vLightPos[3] * vPlaneEquation[2]; destMat[15] = dot - vLightPos[3] * vPlaneEquation[3]; } void fLightMirr() {fLightPosMirror[0]=lightPos[0]; fLightPosMirror[1]=yground -lightPos[1]; fLightPosMirror[2]=lightPos[2]; fLightPosMirror[3]=lightPos[3]; } void gltInitFrame(GLTFrame *f) {f->vLocation[0]=0.0f; f->vLocation[1]=0.0f; f->vLocation[2]=0.0f; f->vRotation[0]=0.0f; f->vRotation[1]=0.0f; f->vRotation[2]=0.0f; return; } void gltApplyActorTransform(GLTFrame *sphere) { glLoadIdentity (); glTranslatef(sphere->vLocation[0], sphere->vLocation[1], sphere->vLocation[2]); } //// Draw a gridded ground // void DrawGround(void) { GLfloat fStep = 1.0f, wf=20.0f; GLint iLine, jLine, number_steps= 2.0*fExtent/fStep, i,j; GLfloat fi,fj, fk, fn=2.0f*(GLfloat)number_steps, col; glBegin(GL_QUADS); for(iLine = -fExtent, i=0, fi=1.0f; iLine <= fExtent; iLine += fStep, i++, fi++) for(jLine = -fExtent, j=0, fj=1.0f; jLine <= fExtent; jLine += fStep, j++, fj++) { fk=(GLfloat) ((i+j)%2); col=(fk*(fi+fj)+wf)/(fn+wf); glNormal3f(0.0f, 1.0f, 0.0f); glColor3f(col,col,col); glVertex3f(iLine, yground, jLine); col=(fk*(fi+fj+1.0f)+wf)/(fn+wf); glColor3f(col,col,col); glVertex3f(iLine, yground, jLine+fStep); col=(fk*(fi+fj+2.0f)+wf)/(fn+wf); glColor3f(col,col,col); glVertex3f(iLine+fStep, yground, jLine+fStep); col=(fk*(fi+fj+1.0f)+wf)/(fn+wf); glColor3f(col,col,col); glVertex3f(iLine+fStep, yground, jLine); } glEnd(); } void SetupRC() { int iSphere; vGroundPlane[0] = 0.0f, vGroundPlane[1] = 1.0f, vGroundPlane[2] = 0.0f, vGroundPlane[3] = -yground; // Randomly place the sphere inhabitants for(iSphere = 0; iSphere < NUM_SPHERES; iSphere++) { gltInitFrame(&spheres[iSphere]); // Initialize the frame // Pick a random location between -20 and 20 at .1 increments spheres[iSphere].vLocation[0] = (float)((rand() % 400) - 200) * 0.1f; spheres[iSphere].vLocation[1] = 0.1f; spheres[iSphere].vLocation[2] = (float)((rand() % 400) - 200) * 0.1f; } // Bluish background glClearColor(0.0f, 0.0f, .50f, 1.0f ); // Set color shading model to flat glShadeModel(GL_FLAT); // Clockwise-wound polygons are front facing; this is reversed // because we are using triangle fans glFrontFace(GL_CCW); // Enable lighting glEnable(GL_LIGHTING); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST);/* glPolygonMode(GL_FRONT, GL_FILL); glPolygonMode(GL_BACK, GL_LINE)*/; glPolygonMode(GL_BACK,GL_FILL); // the light source GL_LIGHT0 is enabled: // Set up and enable light 0 glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight); glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight); glLightfv(GL_LIGHT0,GL_SPECULAR,specular); glEnable(GL_LIGHT0); glLightfv(GL_LIGHT0,GL_POSITION,lightPos); // Enable color tracking glEnable(GL_COLOR_MATERIAL); // Front material ambient and diffuse colors track glColor glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE); // All materials hereafter have full specular reflectivity // with a high shine glMaterialfv(GL_FRONT, GL_SPECULAR,specref); glMateriali(GL_FRONT,GL_SHININESS,128); // Light blue background glClearColor(0.0f, 0.0f, 1.0f, 1.0f ); // Calculate projection matrix to draw shadow on the ground gltMakeShadowMatrix(vGroundPlane, lightPos, shadowMat); } // Called to draw scene void Draw_Objects_Shadow(void) { glColor3f(0.25f, 0.25f, 0.25f); // Draw the randomly located spheres for(int i = 0; i < NUM_SPHERES; i++) { glPushMatrix(); gltApplyActorTransform(&spheres[i]); glutSolidSphere(0.1f, 13, 26); glPopMatrix(); } glPushMatrix(); glTranslatef(0.0f, 0.0f, -2.5f); glPushMatrix(); glRotatef(-yRot * 2.0f, 0.0f, 1.0f, 0.0f); glTranslatef(1.0f, 0.0f, 0.0f); glutSolidSphere(0.1f, 13, 26); glPopMatrix(); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glTranslatef(0.0f, 0.1f, 0.0f); glutSolidTorus(0.15, 0.35, 40, 20); // gltDrawTorus(0.35, 0.15, 40, 20); //void glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius, //GLint nsides, GLint rings); glPopMatrix(); } void Draw_Objects_Color(void) { // Draw the randomly located spheres for(int i = 0; i < NUM_SPHERES; i++) { glPushMatrix(); gltApplyActorTransform(&spheres[i]); glutSolidSphere(0.1f, 13, 26); glPopMatrix(); } glPushMatrix(); glTranslatef(0.0f, 0.0f, -2.5f); glPushMatrix(); glRotatef(-yRot * 2.0f, 0.0f, 1.0f, 0.0f); glTranslatef(1.0f, 0.0f, 0.0f); glColor3f(0.0f, 0.5f, 0.5f); glutSolidSphere(0.1f, 13, 26); glPopMatrix(); glRotatef(yRot, 0.0f, 1.0f, 0.0f); glColor3f(1.0f, 0.0f, 0.0f); glTranslatef(0.0f, 0.1f, 0.0f); glutSolidTorus(0.15, 0.35, 40, 20); //void glutSolidTorus(GLdouble innerRadius, //GLdouble outerRadius, GLint nsides, GLint rings); glPopMatrix(); } void RenderScene(void) { // Reset coordinate system glLoadIdentity(); gluLookAt (ex, ey, ez, cx, cy, cz, 0.0, 1.0, 0.0); yRot += 0.5f; // Clear the window with current clearing color glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); // Draw the ground DrawGround(); glPopMatrix(); // Save matrix state and do the rotation glPushMatrix(); // First disable lighting and save the projection state glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); // Multiply by shadow projection matrix glMultMatrixf((GLfloat *)shadowMat); glPushMatrix(); // Draw the ground Draw_Objects_Shadow(); glPopMatrix(); // Restore transformations glPopMatrix(); /* end shadows*/ glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glPushMatrix(); Draw_Objects_Color(); glPopMatrix(); // Draw the light source glPushMatrix(); glTranslatef(lightPos[0],lightPos[1], lightPos[2]); glColor3ub(255,255,0); glutSolidSphere(0.1f,10,10); glPopMatrix(); // Do the buffer Swap glutSwapBuffers(); } // Called by GLUT library when the window has changed size void ChangeSize(GLsizei w, GLsizei h) { // Set Viewport to window dimensions glViewport(0, 0, (GLsizei)w, (GLsizei)h); wSize=(GLsizei)w; hSize=(GLsizei)h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); //glOrtho (-100.0, 100.0, -100, 100, -270.0, 270.0); //glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); gluPerspective(60.0, 1.0, 1.5, 700.0); glMatrixMode (GL_MODELVIEW); } void SpecialKeys(int key, int x, int y) {GLfloat dx, dy, dz, dx0, dy0, dz0; if(key == GLUT_KEY_UP) {//increase distance from camera to origin dx=cx-ex; dy=cy-ey; dz=cz-ez; ex-=deltaR*dx; ey-=deltaR*dy; ez-=deltaR*dz; glutPostRedisplay(); return; } if(key == GLUT_KEY_DOWN) {//reduce distance from camera to origin (close up) dx=cx-ex; dy=cy-ey; dz=cz-ez; ex+=deltaR*dx; ey+=deltaR*dy; ez+=deltaR*dz; glutPostRedisplay(); return; } if(key == GLUT_KEY_LEFT) //Rotate (+) camera around origin in Oxz plane { dx0=cz-ez; dz0= ex - cx; dx=cx-ex; dz=cz-ez; GLfloat s=sqrtf(dx*dx+dz*dz); dx+=delta*dx0; dz+=delta*dz0; GLfloat s1=sqrtf(dx*dx+dz*dz)/s; dx/=s1; dz/=s1; ex=cx-dx; ez=cz-dz; glutPostRedisplay();return; } if(key == GLUT_KEY_RIGHT) //Rotate (-) camera around origin in Oxz plane {dx0=cz-ez; dz0= ex - cx; dx=cx-ex; dz=cz-ez; GLfloat s=sqrtf(dx*dx+dz*dz); dx-=delta*dx0; dz-=delta*dz0; GLfloat s1=sqrtf(dx*dx+dz*dz)/s; dx/=s1; dz/=s1; ex=cx-dx; ez=cz-dz; glutPostRedisplay();return;} if(key == GLUT_KEY_F5)//Rotate camera around origin in Oyz plane { dy0=cz-ez; dz0= ey - cy; dy=cy-ey; dz=cz-ez; GLfloat s=sqrtf(dy*dy+dz*dz); dy+=delta*dy0; dz+=delta*dz0; GLfloat s1=sqrtf(dy*dy+dz*dz)/s; dy/=s1; dz/=s1; ey=cy-dy; ez=cz-dz; glutPostRedisplay();return;} if(key == GLUT_KEY_F6)//Rotate camera around origin in Oyz plane {dy0=cz-ez; dz0= ey - cy; dy=cy-ey; dz=cz-ez; GLfloat s=sqrtf(dy*dy+dz*dz); dy-=delta*dy0; dz-=delta*dz0; GLfloat s1=sqrtf(dy*dy+dz*dz)/s; dy/=s1; dz/=s1; ey=cy-dy; ez=cz-dz; glutPostRedisplay();return;} if(key == GLUT_KEY_F7)//Move light toward the center of ground { dx=cx-lightPos[0]; dy=cy-lightPos[1]; dz=cz-lightPos[2]; dx*=(1.0-deltatrans); dy*=(1.0-deltatrans); dz*=(1.0-deltatrans); lightPos[0]=cx-dx; lightPos[1]=cy-dy; lightPos[2]=cz-dz; fLightMirr(); // Calculate new projection matrix to draw shadow on the ground gltMakeShadowMatrix(vGroundPlane, lightPos, shadowMat); glutPostRedisplay();return; } if(key == GLUT_KEY_F8)//Move light outward the center of ground { dx=cx-lightPos[0]; dy=cy-lightPos[1]; dz=cz-lightPos[2]; dx/=(1.0-deltatrans); dy/=(1.0-deltatrans); dz/=(1.0-deltatrans); lightPos[0]=cx-dx; lightPos[1]=cy-dy; lightPos[2]=cz-dz; fLightMirr(); // Calculate new projection matrix to draw shadow on the ground gltMakeShadowMatrix(vGroundPlane, lightPos, shadowMat); glutPostRedisplay();return; } if(key == GLUT_KEY_F9)//Rotate (+) light around ... in the vertical plane { dy0=cz-lightPos[2]; dz0= lightPos[1] - cy; dy=cy-lightPos[1]; dz=cz-lightPos[2]; GLfloat s=sqrtf(dy*dy+dz*dz); dy+=delta*dy0; dz+=delta*dz0; GLfloat s1=sqrtf(dy*dy+dz*dz)/s; dy/=s1; dz/=s1; lightPos[1]=cy-dy; lightPos[2]=cz-dz; fLightMirr(); gltMakeShadowMatrix(vGroundPlane, lightPos, shadowMat); glutPostRedisplay();return; } if(key == GLUT_KEY_F10)//Rotate (-) light around ... in the vertical plane {dy0=cz-lightPos[2]; dz0= lightPos[1] - cy; dy=cy-lightPos[1]; dz=cz-lightPos[2]; GLfloat s=sqrtf(dy*dy+dz*dz); dy-=delta*dy0; dz-=delta*dz0; GLfloat s1=sqrtf(dy*dy+dz*dz)/s; dy/=s1; dz/=s1; lightPos[1]=cy-dy; lightPos[2]=cz-dz; fLightMirr(); gltMakeShadowMatrix(vGroundPlane, lightPos, shadowMat); glutPostRedisplay();return; } if(key == GLUT_KEY_F11)//Rote light around ... in the horizontal plane { dy=-lightPos[2]; dz= lightPos[0]; GLfloat s=sqrtf(lightPos[0]*lightPos[0]+lightPos[1]*lightPos[1] +lightPos[2]*lightPos[2]); lightPos[0]+=delta*dy; lightPos[2]+=delta*dz; GLfloat s1=sqrtf(lightPos[0]*lightPos[0]+lightPos[1]*lightPos[1] +lightPos[2]*lightPos[2])/s; lightPos[0]/=s1; lightPos[1]/=s1; lightPos[2]/=s1; fLightMirr(); gltMakeShadowMatrix(vGroundPlane, lightPos, shadowMat); glutPostRedisplay();return; } if(key == GLUT_KEY_F12)//Move light in horiz. plane { dy=lightPos[0]; dz= lightPos[2]; lightPos[0]+=delta*dy; lightPos[2]+=delta*dz; // Calculate new projection matrix to draw shadow on the ground fLightMirr(); gltMakeShadowMatrix(vGroundPlane, lightPos, shadowMat); glutPostRedisplay();return; } if(key == GLUT_KEY_F1){ bCull=!bCull; // Turn on/off culling on if flag is set if(bCull) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); glutPostRedisplay();return; } if(key == GLUT_KEY_F2){bDepth=!bDepth; if(bDepth) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); glutPostRedisplay();return; } if(key == GLUT_KEY_F3){bOutline=!bOutline; // Draw the back side as a wireframe only, if flag is set if(bOutline)glPolygonMode(GL_BACK,GL_LINE); else glPolygonMode(GL_BACK,GL_FILL); glutPostRedisplay(); return; } if(key == GLUT_KEY_F4) {bShade=!bShade; if(bShade){glShadeModel(GL_FLAT);} else {glShadeModel(GL_SMOOTH);} glutPostRedisplay(); return; } } void mouse(int button, int state, int x, int y) { switch (button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) { cx-=(x-wSize/2)*deltaC; cy-=(y-hSize/2)*deltaC; glutPostRedisplay(); return; //glutIdleFunc(spinDisplay); } break; case GLUT_MIDDLE_BUTTON: if (state == GLUT_DOWN) glutIdleFunc(NULL); break; default: break; } } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB); glutInitWindowSize (wSize, hSize); glutInitWindowPosition (100, 100); glutCreateWindow (argv[0]); glutDisplayFunc(RenderScene); glutReshapeFunc(ChangeSize); glutSpecialFunc (SpecialKeys); glutMouseFunc(mouse); SetupRC(); glutMainLoop(); return 0; }