#include "stdafx.h" GLfloat xRot = 0.45f; GLfloat yRot = 0.35f; GLboolean bCull = glIsEnabled(GL_CULL_FACE); GLboolean bDepth = glIsEnabled(GL_DEPTH_TEST); GLboolean bOutline = (GLboolean)true; GLenum shademode = GL_FLAT; GLfloat ex = 0.0f; GLfloat ey = 0.0f; GLfloat ez = -120.0f; GLfloat delta = 0.01f; GLfloat deltaR = 0.01f; GLfloat piso[] = { 0, 1/*-1? */, 0, 50 /*-50?*/ }; GLfloat foco[] = { 15., 75., 0. , 1. }; GLfloat MatrizSombra[16]; /////////////////////////////////////////////////////////// GLfloat colors[][3] = { { .5,0.0,0.5 },{ 1.0,0.0,0.0 }, { 1.0,1.0,0.0 },{ 0.0,1.0,0.0 },{ 0.0,0.0,1.0 }, { 1.0,0.0,1.0 },{ 1.0,1.0,1.0 },{ 0.0,1.0,1.0 }, { 0.0,.0,.0 } }; //TEXTURA #define checkImageWidth 256 #define checkImageHeight 256 #define subImageWidth 64 #define subImageHeight 64 static GLubyte checkImage[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; } } 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 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 cuadrado_fijo() { glBegin(GL_POLYGON); glVertex2f(1., 1.); glVertex2f(1., -1.); glVertex2f(-1., -1.); glVertex2f(-1., 1.); glEnd(); } void cuadrado_fijo_para_cara_3() { glBegin(GL_POLYGON); glTexCoord2f(0.0, 0.0); glVertex2f(1., 1.); glTexCoord2f(0.0, 1.0); glVertex2f(1., -1.); glTexCoord2f(1.0, 1.0); glVertex2f(-1., -1.); glTexCoord2f(1.0, 0.0); glVertex2f(-1., 1.); glEnd(); } void cuadrado_fijo_piso() { glBegin(GL_POLYGON); glVertex3f(1., 0, 1.); glVertex3f(-1., 0, 1.); glVertex3f(-1., 0, -1.); glVertex3f(1., 0, -1.); glEnd(); } void linea() { glBegin(GL_LINES); glVertex3f(1, 0, 1); glVertex3f(-1, 0, 1); glEnd(); } #define NumLineas 10 void setLineas() { glColor3fv(colors[6]); for (int i = 0; i > -NumLineas; i--) { glPushMatrix(); glTranslatef(0, 0, i * 2. / (NumLineas - 1)); linea(); glPopMatrix(); } } #define ALFA 0.75 void pis() { glColor4f(0.6, 0.6, 0.6, ALFA); glPushMatrix(); glTranslatef(0, -piso[3]/*piso[3]?*/, 0); glScalef(65., 65., 55.); cuadrado_fijo_piso(); glDisable(GL_DEPTH_TEST); setLineas(); if (bDepth) glEnable(GL_DEPTH_TEST); glPopMatrix(); } void colorcube_sincolor1(void) { /*1 cara*/ glPushMatrix(); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); /*2 cara*/ glPushMatrix(); glRotatef(90., 1., 0, 0); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); /*3 cara*/ glPushMatrix(); glRotatef(180., 1., 0, 0); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); /*4 cara*/ glPushMatrix(); glRotatef(270., 1., 0, 0); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); /*5 cara*/ glPushMatrix(); glRotatef(90., 0., 0., 1.); glRotatef(270., 1., 0, 0); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); /*6 cara*/ glPushMatrix(); glRotatef(270., 0., 0., 1.); glRotatef(270., 1., 0, 0); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); } void colorcube1(void) { /*1 cara*/ glColor3fv(colors[0]); glPushMatrix(); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); /*2 cara*/ glColor3fv(colors[1]); glPushMatrix(); glRotatef(90., 1., 0, 0); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); /*3 cara*/ glEnable(GL_TEXTURE_2D); // Habilita el texturizado bidimensional glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); // Establece los parametros del entorno de textura. glBindTexture(GL_TEXTURE_2D, texName[0]); //glColor3fv(colors[2]); glPushMatrix(); glRotatef(180., 1., 0, 0); glTranslatef(0., 0., 1.); cuadrado_fijo_para_cara_3();// cuadrado_fijo(); glPopMatrix(); glDisable(GL_TEXTURE_2D); /*4 cara*/ glColor3fv(colors[3]); glPushMatrix(); glRotatef(270., 1., 0, 0); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); /*5 cara*/ glColor3fv(colors[6]); glPushMatrix(); glRotatef(90., 0., 0., 1.); glRotatef(270., 1., 0, 0); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); /*6 cara*/ glColor3fv(colors[5]); glPushMatrix(); glRotatef(270., 0., 0., 1.); glRotatef(270., 1., 0, 0); glTranslatef(0., 0., 1.); cuadrado_fijo(); glPopMatrix(); } void ObjCurva() { // OBJETO CURVEADO. glColor3f(0, 1, 0.5); glTranslatef(0.0, 0.0, 2.5); //glRotatef(85.0, 1.0, 1.0, 1.0); glEvalMesh2(GL_FILL, 0, 20, 0, 20); } void objetos_del_mundo_sin_color() { glPushMatrix(); glScalef(15., 15., 15.); colorcube_sincolor1(); glPopMatrix(); } void SombradeCubo(GLfloat datosdeLuz[], GLfloat datosdePlano[]) { glColor4f(0.3, 0.3, 0.3, ALFA); glPushMatrix(); gltMakeShadowMatrix(datosdePlano, datosdeLuz, MatrizSombra); glMultMatrixf(MatrizSombra); objetos_del_mundo_sin_color(); //Objetos_de_MiMundo(); glPopMatrix(); } void objetos_del_mundo() { glPushMatrix(); glScalef(15., 15., 15.); colorcube1(); ObjCurva(); glPopMatrix(); } void foc() { glColor3fv(colors[2]); glPushMatrix(); glTranslatef(foco[0], foco[1], foco[2]); glutSolidSphere(3, 20, 20); glPopMatrix(); } void Stencil_Config() { // 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 pis(); // 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); } void SetupRC() { // Black background glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glShadeModel(GL_SMOOTH); glEnable(GL_DEPTH_TEST); 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); glFrontFace(GL_CW); } void RenderScene(void) { // Reset coordinate system glLoadIdentity(); gluLookAt(ex, ey, ez, 0.0, 0.0, 0.0, 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); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); Stencil_Config(); /*mundo reflejado*/ glFrontFace(GL_CCW); //invertir orientacion para mundo reflejado glPushMatrix(); //transformacion de reflejo glTranslatef(0., -piso[3], 0.); glScalef(1., -1., 1.); glTranslatef(0., piso[3], 0.); /*foco*/ foc(); /*objetos del mundo*/ objetos_del_mundo(); glPopMatrix(); glFrontFace(GL_CW); /*fin mundo reflejado*/ /*piso*/ pis(); /*sombra objetos del mundo*/ glDisable(GL_DEPTH_TEST); SombradeCubo(foco, piso); if (bDepth) glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); glDisable(GL_STENCIL_TEST); /*objetos del mundo normal*/ objetos_del_mundo(); /*foco*/ foc(); glPopMatrix(); // Flush drawing commands glFlush(); // 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); // if (w <= h) // glOrtho(-4.0, 4.0, -4.0 * (GLfloat)h / (GLfloat)w, // 4.0 * (GLfloat)h / (GLfloat)w, -4.0, 4.0); // else // glOrtho(-4.0 * (GLfloat)w / (GLfloat)h, // 4.0 * (GLfloat)w / (GLfloat)h, -4.0, 4.0, -4.0, 4.0); //glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0); gluPerspective(60.0, 1.0, 1.5, 500.0); glMatrixMode(GL_MODELVIEW); } void SpecialKeys(int key, int x, int y) { GLfloat dx, dz; 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); } //Subir foco if (key == GLUT_KEY_F5) { foco[1] = (1. + delta) * foco[1]/* + 5*/; } //Bajar foco if (key == GLUT_KEY_F6) { foco[1] = (1. - delta) * foco[1]/* - 5*/; } if (key == GLUT_KEY_F7) //Rotate camera around origin in Oyz plane { GLfloat dy; dz = -ey; dy = ez; GLfloat s = sqrtf(ex * ex + ey * ey + ez * ez); ez += delta * dz; ey += delta * dy; GLfloat s1 = sqrtf(ex * ex + ey * ey + ez * ez) / s; ex /= s1; ey /= s1; ey /= s1; } if (key == GLUT_KEY_F8) //Rotate camera around origin in Oyz plane { GLfloat dy; dz = -ey; dy = ez; GLfloat s = sqrtf(ex * ex + ey * ey + ez * ez); ez -= delta * dz; ey -= delta * dy; GLfloat s1 = sqrtf(ex * ex + ey * ey + ez * ez) / s; ex /= s1; ey /= s1; ey /= s1; } /* //otra version subir/bajar la camara: if (key == GLUT_KEY_F7)xRot -= 1.0f; if (key == GLUT_KEY_F8)xRot += 1.0f;*/ // Refresh the Window glutPostRedisplay(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(/*GLUT_DOUBLE*/GLUT_SINGLE | GLUT_RGB | GLUT_STENCIL | GLUT_DEPTH); glutInitWindowSize(600, 600); glutInitWindowPosition(100, 100); glutCreateWindow(argv[0]); glutDisplayFunc(RenderScene); glutReshapeFunc(ChangeSize); glutSpecialFunc(SpecialKeys); SetupRC(); glutMainLoop(); return 0; }