#include "stdafx.h" #define GL_PI 3.1415f #define ALTP -150.f GLfloat xRot = 0.45f; GLfloat yRot = 0.35f; GLboolean bCull = glIsEnabled(GL_CULL_FACE); GLboolean bDepth = glIsEnabled(GL_DEPTH_TEST); GLboolean bOutline = (GLboolean)true; #define ALPHA 0.75f #define DELTATRANS 0.05f GLenum shademode = GL_FLAT; GLfloat ex = 0.0f; GLfloat ey = 0.0f; GLfloat ez = -600.0f; GLfloat cx = 0.0f; GLfloat cy = 0.0f; GLfloat cz = 0.0f; GLfloat deltatrans = DELTATRANS; GLfloat delta = 0.01f; GLfloat deltaR = 0.01f; GLfloat vP[] = { 0.f, 1.f, 0.f, -ALTP }; GLfloat vluz[] = { 0.f, 250.f, -50.f, 1.f }; GLfloat wluz[4]; GLfloat msombra[16]; #define checkImageWidth 256 #define checkImageHeight 256 #define subImageWidth 64 #define subImageHeight 64 static GLubyte checkImage[checkImageHeight][checkImageWidth][4]; //static GLubyte otherImage[checkImageHeight][checkImageWidth][4]; static GLubyte subImage[subImageHeight][subImageWidth][4]; static GLuint texName[1]; /////////////////////////////////////////////////////////// void makeCheckImages(void) { int i, j, c; for (i = 0; i < checkImageHeight; i++) { for (j = 0; j < checkImageWidth; j++) { c = ((((i & 0x8) == 0) ^ ((j & 0x8)) == 0)) * 255; checkImage[i][j][0] = (GLubyte)c; checkImage[i][j][1] = (GLubyte)c; checkImage[i][j][2] = (GLubyte)c; checkImage[i][j][3] = (GLubyte)255; //c = ((((i&0x10)==0)^((j&0x10))==0))*255; // otherImage[i][j][0] = (GLubyte) 0; // otherImage[i][j][1] = (GLubyte) 0; // otherImage[i][j][2] = (GLubyte) c; // otherImage[i][j][3] = (GLubyte) 255; } } for (i = 0; i < subImageHeight; i++) { for (j = 0; j < subImageWidth; j++) { c = ((((i & 0x4) == 0) ^ ((j & 0x4)) == 0)) * 255; subImage[i][j][0] = (GLubyte)c; subImage[i][j][1] = (GLubyte)0; subImage[i][j][2] = (GLubyte)0; subImage[i][j][3] = (GLubyte)255; } } } void Buff_Light() { wluz[0] = vluz[0]; wluz[1] = vluz[1]; wluz[2] = vluz[2]; wluz[3] = vluz[3]; } void SetLightPos() { vluz[0] = wluz[0]; vluz[1] = wluz[1]; vluz[2] = wluz[2]; vluz[3] = wluz[3]; //glLightfv(GL_LIGHT0, GL_POSITION, lightPos); //gltMakeShadowMatrix(vGroundPlane, lightPos, shadowMat); } 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 SetupRC() { // Black background glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set color shading model to flat glShadeModel(shademode); makeCheckImages(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glGenTextures(1, texName); glBindTexture(GL_TEXTURE_2D, texName[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, checkImageWidth, checkImageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, checkImage); glTexSubImage2D(GL_TEXTURE_2D, 0, 48, 170, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glTexSubImage2D(GL_TEXTURE_2D, 0, 48, 48, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glTexSubImage2D(GL_TEXTURE_2D, 0, 170, 48, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); glTexSubImage2D(GL_TEXTURE_2D, 0, 170, 170, subImageWidth, subImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, subImage); // Clockwise-wound polygons are front facing; this is reversed // because we are using triangle fans } void cuadro_sin_color(){ glBegin(GL_QUADS); glVertex3f(1.0f, 1.0f, .0f); glVertex3f(1.0f, -1.0f, .0f); glVertex3f(-1.0f, -1.0f, .0f); glVertex3f(-1.0f, 1.0f, .0f); glEnd(); } void cuadro_con_texture(){ glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); glBindTexture(GL_TEXTURE_2D, texName[0]); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(1.0f, 1.0f, .0f); //glVertex3f( 400.0f, -150.0f, -700.0f); //glVertex3f(-2.0, -1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(1.0f, -1.0f, .0f); //glVertex3f(-400.0f, -150.0f, -700.0f); //glVertex3f(-2.0, 1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(-1.0f, -1.0f, .0f); //glVertex3f(-400.0f, -150.0f, 200.0f); //glVertex3f(0.0, 1.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex3f(-1.0f, 1.0f, .0f); //glVertex3f(400.0f, -150.0f, 200.0f);//glVertex3f(0.0, -1.0, 0.0); glEnd(); // glFlush(); glDisable(GL_TEXTURE_2D); //glBegin(GL_QUADS); //glVertex3f(1.0f, 1.0f, .0f); //glVertex3f(1.0f, -1.0f, .0f); //glVertex3f(-1.0f, -1.0f, .0f); //glVertex3f(-1.0f, 1.0f, .0f); glEnd(); } void rayas_sobre_cuadro_sin_color(){ glBegin(GL_LINES); int i; for (i = 0; i <= 10; i++) { glVertex3f(1.0f - i / 5.f, 1.0f, .0f); glVertex3f(1.0f - i / 5.f, -1.0f, .0f); } for (i = 0; i <= 10; i++) { glVertex3f(1.0f, 1.0f - i / 5.f, .0f); glVertex3f(-1.0f, 1.0f - i / 5.f, .0f); } glEnd(); } // Called to draw scene void luz(){ glColor4f(1.f, 1.f, .0f, 1.f); glPushMatrix(); glTranslatef(vluz[0]/*0.f*/, vluz[1]/*250.f*/, vluz[2]/*-50.f*/); glScalef(5.f, 5.f, 5.f); //piso 3 veces mas ancho que cubo glutSolidSphere(1., 20, 20); glPopMatrix(); } void piso(){ /*función agregada 23/05/2018*/ glColor4f(.7f, .7f, .7f, ALPHA); glPushMatrix(); glTranslatef(0.f, -vP[3]/*-150.f*/, 50.f); glRotatef(270.f, 1.f, 0.f, 0.f); //la version glRotatef(90.f, 1.f, 0.f, 0.f); // voltea el piso al la cara invisible glScalef(250.f, 250.f, 250.f); //piso 3 veces mas ancho que cubo cuadro_sin_color(); glColor4f(.0f, .0f, .0f, ALPHA); glDisable(GL_DEPTH_TEST); rayas_sobre_cuadro_sin_color(); if (bDepth) glEnable(GL_DEPTH_TEST); glPopMatrix(); } void objetos_mundo_sin_color(){ //primera cara glPushMatrix(); glTranslatef(0.f, 0.f, 50.f); glScalef(50.f, 50.f, 50.f); cuadro_sin_color(); glPopMatrix(); //2a cara glPushMatrix(); glRotatef(90.f, 0.f, 1.f, 0.f); glPushMatrix(); glTranslatef(0.f, 0.f, 50.f); glScalef(50.f, 50.f, 50.f); cuadro_sin_color(); glPopMatrix(); glPopMatrix(); //3a cara glPushMatrix(); glRotatef(180.f, 0.f, 1.f, 0.f); glPushMatrix(); glTranslatef(0.f, 0.f, 50.f); glScalef(50.f, 50.f, 50.f); cuadro_sin_color(); glPopMatrix(); glPopMatrix(); //4a cara glPushMatrix(); glRotatef(270.f, 0.f, 1.f, 0.f); glPushMatrix(); glTranslatef(0.f, 0.f, 50.f); glScalef(50.f, 50.f, 50.f); cuadro_sin_color(); glPopMatrix(); glPopMatrix(); } void SombradeMiMundo(){ glPushMatrix(); gltMakeShadowMatrix(vP/*GLfloat vPlaneEquation[]*/, vluz/*GLfloat vLightPos[]*/, msombra/*GLfloat destMat[]*/); glMultMatrixf(msombra); objetos_mundo_sin_color(); glPopMatrix(); } void objetos_mundo(){ //primera cara glColor4f(0.0f, 1.0f, 0.0f, ALPHA); glPushMatrix(); glTranslatef(0.f, 0.f, 50.f); glScalef(50.f, 50.f, 50.f); cuadro_sin_color(); glPopMatrix(); //2a cara glColor4f(1.0f, 1.0f, 0.0f, ALPHA); glPushMatrix(); glRotatef(90.f, 0.f, 1.f, 0.f); glPushMatrix(); glTranslatef(0.f, 0.f, 50.f); glScalef(50.f, 50.f, 50.f); cuadro_sin_color(); glPopMatrix(); glPopMatrix(); //3a cara glColor4f(1.0f, .0f, 0.0f, ALPHA); glPushMatrix(); glRotatef(180.f, 0.f, 1.f, 0.f); glPushMatrix(); glTranslatef(0.f, 0.f, 50.f); glScalef(50.f, 50.f, 50.f); cuadro_sin_color(); glPopMatrix(); glPopMatrix(); //4a cara glPushMatrix(); glRotatef(270.f, 0.f, 1.f, 0.f); glPushMatrix(); glTranslatef(0.f, 0.f, 50.f); glScalef(50.f, 50.f, 50.f); cuadro_con_texture(); glPopMatrix(); glPopMatrix(); } void StencilConfig() {// step 1 // turning off writing to the color buffer and depth buffer so we only // write to stencil buffer glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glDepthMask(GL_FALSE); // enable stencil buffer glEnable(GL_STENCIL_TEST); // write a one to the stencil buffer everywhere we are about to draw glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); // this is to always pass a one to the stencil buffer where we draw glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); // render the plane which the shadow will be on // color and depth buffer are disabled, only the stencil buffer // will be modified piso(); // turn the color and depth buffers back on glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); // until stencil test is diabled, only write to areas where the // stencil buffer has a one. This is to draw the shadow only on // the floor. glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); // don't modify the contents of the stencil buffer glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // end step 1 } void RenderScene(void) { // Reset coordinate system glLoadIdentity(); gluLookAt(ex, ey, ez, cx, cy, cz, 0.0, 1.0, 0.0); // Clear the window and the depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Turn culling on if flag is set if (bCull) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); // Enable depth testing if flag is set if (bDepth) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); // 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); // Save matrix state and do the rotation glPushMatrix(); glRotatef(xRot, 1.0f, 0.0f, 0.0f); glRotatef(yRot, 0.0f, 1.0f, 0.0f); /////////// glFrontFace(GL_CW); // cambiar orientacion de poligonos para invertir los lados delanteros y traseros glPushMatrix(); // recordar la matriz actual /* dibujar mundo invertido */ glScalef(1.0f, -1.0f, 1.0f); glTranslatef(0.0f, -2.0f*ALTP/*-? */, 0.0f); StencilConfig(); luz(); objetos_mundo(); glDisable(GL_STENCIL_TEST); /* restaurar el mundo normal*/ glPopMatrix(); //restaurar matriz glFrontFace(GL_CCW); // restaurar orientación ////////// glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); piso(); glDisable(GL_BLEND); luz(); objetos_mundo(); glColor4f(0.3f, 0.3f, 0.3f, ALPHA); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_DEPTH_TEST); StencilConfig(); SombradeMiMundo(); glDisable(GL_STENCIL_TEST); glDisable(GL_BLEND); if (bDepth) glEnable(GL_DEPTH_TEST); glPopMatrix(); // Flush drawing commands 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); 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, 1500.0); glMatrixMode(GL_MODELVIEW); } void SpecialKeys(int key, int x, int y) { GLfloat dx, dy, dz; if (key == GLUT_KEY_F7)//Move light toward the center of ground { Buff_Light(); dx = cx - wluz[0]; dy = cy - wluz[1]; dz = cz - wluz[2]; dx *= (1.0 - deltatrans); dy *= (1.0 - deltatrans); dz *= (1.0 - deltatrans); wluz[0] = cx - dx; wluz[1] = cy - dy; wluz[2] = cz - dz; SetLightPos(); // Calculate new projection matrix to draw shadow on the ground glutPostRedisplay(); return; } if (key == GLUT_KEY_F8)//Move light outward the center of ground { Buff_Light(); dx = cx - wluz[0]; dy = cy - wluz[1]; dz = cz - wluz[2]; dx /= (1.0 - deltatrans); dy /= (1.0 - deltatrans); dz /= (1.0 - deltatrans); wluz[0] = cx - dx; wluz[1] = cy - dy; wluz[2] = cz - dz; SetLightPos(); // Calculate new projection matrix to draw shadow on the ground glutPostRedisplay(); return; } if (key == GLUT_KEY_UP) {//increase distance from camera to origin ex *= (1.0f + deltaR); ey *= (1.0f + deltaR); ez *= (1.0f + deltaR); } if (key == GLUT_KEY_DOWN) {//reduce distance from camera to origin (close up) ex *= (1.0f - deltaR); ey *= (1.0f - deltaR); ez *= (1.0f - deltaR); } if (key == GLUT_KEY_LEFT) //Rotate camera around origin in Oxz plane { dx = -ez; dz = ex; GLfloat s = sqrtf(ex*ex + ey*ey + ez*ez); ex += delta*dx; ez += delta*dz; GLfloat s1 = sqrtf(ex*ex + ey*ey + ez*ez) / s; ex /= s1; ey /= s1; ey /= s1; } if (key == GLUT_KEY_RIGHT) //Rotate camera around origin in Oxz plane { dx = -ez; dz = ex; GLfloat s = sqrtf(ex*ex + ey*ey + ez*ez); ex -= delta*dx; ez -= delta*dz; GLfloat s1 = sqrtf(ex*ex + ey*ey + ez*ez) / s; ex /= s1; ey /= s1; ey /= s1; } if (key == GLUT_KEY_F1) bCull = !bCull; if (key == GLUT_KEY_F2)bDepth = !bDepth; if (key == GLUT_KEY_F3)bOutline = !bOutline; if (key == GLUT_KEY_F4) { if (shademode == GL_FLAT){ shademode = GL_SMOOTH; } else { if (shademode == GL_SMOOTH){ shademode = GL_FLAT; } }; glShadeModel(shademode); } // Refresh the Window glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE /*GLUT_SINGLE*/ | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL); glutInitWindowSize(200, 200); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); glutDisplayFunc(RenderScene); glutReshapeFunc(ChangeSize); glutSpecialFunc(SpecialKeys); SetupRC(); glutMainLoop(); return 0; }