Trabajo en Equipo Luz y Sombras:
Este programa es para aplicar luz y sombras a un objeto en movimiento, el objeto va proyectando su sombra tanto en el piso como en las paredes.Capturas de Pantalla:
Código:
#include <stdio.h>#include <stdlib.h>
#include <string.h>
#include <math.h>
//#include <GLut/gutil.h>
#include <GL/glut.h>
//#include <Opengl/gl.h>
static float salto = 0.0, rotar=0;
static float lightAngle = 0.0, lightHeight = 15;
GLfloat angle = -150;
GLfloat angle2 = 30;
int moving, startx, starty;
float a=0;
static GLdouble tamanio = 4.0;
static GLfloat posicionLuz[4];
static GLfloat posicionAve[3];
static GLfloat colorLuz[] = {1, 1, 1, 1.0};///x,y,z y si es posicional
static GLfloat planoPiso[4];///plano del piso
static GLfloat sombraPiso[4][4];///transformacion objeto-sombra
enum {X, Y, Z, W};
enum {A, B, C, D};
char *textura[] = {
"..................",
"..................",
".......xxxx.......",
".....xxxxxxxx......",
"....xxxxxxxxxx.....",
"....xxx....xxx.....",
"...xxx......xxx....",
"...xxxoo..ooxxx....",
"...xxxoo..ooxxx....",
"...xxx......xxx....",
"....xxx....xxx.....",
"....xxxxxxxxxx.....",
".....xxxxxxxx......",
"..................",
"..................",
"..................",
};
void texturaPiso(void)
{
GLubyte floorTexture[16][16][3];
GLubyte *col;
int s, t;
// Crear RGB para textura
col = (GLubyte*) floorTexture;
for (t = 0; t < 16; t++) {
for (s = 0; s < 16; s++) {
if (textura[t][s] == 'x') {
col[0] = 0;
col[1] = 250;
col[2] = 0;
} else if (textura[t][s] == 'o') {
col[0] = 0;
col[1] = 250;
col[2] = 0;
}else {
col[0] =0;
col[1] =250;
col[2] =0;
}
col += 3;
}
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, 3, 16, 16, 0,
GL_RGB, GL_UNSIGNED_BYTE, floorTexture);
}
/* Matriz de proyeccion de la sombre */
void shadowMatrix(GLfloat shadowMat[4][4],
GLfloat groundplane[4],
GLfloat lightpos[4])
{
GLfloat dot;
// Producto punto entre vector light position y la normal de ground plane
dot = groundplane[X] * lightpos[X] +
groundplane[Y] * lightpos[Y] +
groundplane[Z] * lightpos[Z] +
groundplane[W] * lightpos[W];
shadowMat[0][0] = dot - lightpos[X] * groundplane[X];
shadowMat[1][0] = 0.f - lightpos[X] * groundplane[Y];
shadowMat[2][0] = 0.f - lightpos[X] * groundplane[Z];
shadowMat[3][0] = 0.f - lightpos[X] * groundplane[W];
shadowMat[X][1] = 0.f - lightpos[Y] * groundplane[X];
shadowMat[1][1] = dot - lightpos[Y] * groundplane[Y];
shadowMat[2][1] = 0.f - lightpos[Y] * groundplane[Z];
shadowMat[3][1] = 0.f - lightpos[Y] * groundplane[W];
shadowMat[X][2] = 0.f - lightpos[Z] * groundplane[X];
shadowMat[1][2] = 0.f - lightpos[Z] * groundplane[Y];
shadowMat[2][2] = dot - lightpos[Z] * groundplane[Z];
shadowMat[3][2] = 0.f - lightpos[Z] * groundplane[W];
shadowMat[X][3] = 0.f - lightpos[W] * groundplane[X];
shadowMat[1][3] = 0.f - lightpos[W] * groundplane[Y];
shadowMat[2][3] = 0.f - lightpos[W] * groundplane[Z];
shadowMat[3][3] = dot - lightpos[W] * groundplane[W];
}
/* Ecuación del plano dados 3 puntos. */
void defPlano(GLfloat plane[4],GLfloat v0[3], GLfloat v1[3], GLfloat v2[3])
{
GLfloat vec0[3], vec1[3];
/* Producto cruz entre 2 vectores. */
vec0[X] = v1[X] - v0[X];
vec0[Y] = v1[Y] - v0[Y];
vec0[Z] = v1[Z] - v0[Z];
vec1[X] = v2[X] - v0[X];
vec1[Y] = v2[Y] - v0[Y];
vec1[Z] = v2[Z] - v0[Z];
/* Encontrar producto cruz para A, B, y C en la ec. del plano */
plane[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
plane[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
plane[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];
plane[D] = -(plane[A] * v0[X] + plane[B] * v0[Y] + plane[C] * v0[Z]);
}
void dibujarCastillo(GLfloat x , GLfloat y ,GLfloat ambr , GLfloat ambg, GLfloat ambb,GLfloat difr, GLfloat difg, GLfloat difb, GLfloat specr, GLfloat specg ,GLfloat specb,GLfloat brillo)
{
float mat[4];
//glPushMatrix();
glTranslatef(x,y,0) ;
mat[3] = 1 ;
mat[0] = ambr;
mat[1] = ambg;
mat[2] = ambb;
glMaterialfv(GL_FRONT, GL_AMBIENT, mat) ;
mat[0] = difr;
mat[1] = difg;
mat[2] = difb;
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat) ;
mat[0] = specr;
mat[1] = specg;
mat[2] = specb;
glMaterialfv(GL_FRONT , GL_SPECULAR, mat) ;
glMaterialf(GL_FRONT, GL_SHININESS , brillo * 128) ;
glDisable(GL_LIGHTING);
/*Base superior.*/
glPushMatrix();
glColor3f(1, 1, 1);
glTranslatef(0.0, 0.11, 0.0);
glScalef(1.5, 0.3, 2.0);
glutSolidCube(0.1);
glPopMatrix();
/*Base media.*/
glPushMatrix();
glColor3f(1.0, 0.0, 0.0);
glScalef(1.0, 2.0, 1.5);
glutSolidCube(0.1);
glPopMatrix();
/*Base inferior.*/
glPushMatrix();
glColor3f(1, 1, 1);
glTranslatef(0.0, -0.11, 0.0);
glScalef(1.5, 0.3, 2.0);
glutSolidCube(0.1);
glPopMatrix();
//glPopMatrix();
glPopAttrib();
glEnable(GL_LIGHTING);
}
void dibujarAve()
{
/*Atributos del ave.*/
glPushMatrix();
glTranslatef(posicionAve[0], posicionAve[1], posicionAve[2]);
//glRotated(a,1,1,0);
glRotated(a,1,0,1);
GLfloat mat_p_ambient[] = {1,0.4,0,1};
GLfloat mat_p_diffuse[] = {1,0.4,0,1};
GLfloat mat_pspecular[] = {0.7,0,0,1};
GLfloat mat_pshininess[] = {18.2};
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_pspecular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_pshininess);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_p_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_p_diffuse);
glShadeModel(GL_SMOOTH);
//glTranslatef(15,15,5);
/*Se declara un objeto que almacena una superficie cuadrica.*/
GLUquadricObj *quad;
/*Se hace la instancia del objeto.*/
quad = gluNewQuadric();
/*Se define el estilo de la superficie cuadrica (si se desea rellena o formada por lineas).*/
gluQuadricDrawStyle(quad, GLU_FILL);
glScaled(0.3, 0.3, 0.2);
//glDisable(GL_LIGHTING);
//glColor3f(0.4, 0.211, 0.050);
gluCylinder(quad, 10, 10, 40, 100.0, 100.0);
glPushMatrix();
//glColor3f(0.0, 0.0, 1.0);
//glRotatef(a,0.0,0.0,1.0);
GLfloat mat_p_ambient2[] = {0,0.1,1,1};
GLfloat mat_p_diffuse2[] = {0,0.1,1,1};
GLfloat mat_pspecular2[] = {0,0,0.7,1};
GLfloat mat_pshininess2[] = {18.2};
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_pspecular2);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_pshininess2);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_p_ambient2);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_p_diffuse2);
glShadeModel(GL_SMOOTH);
glTranslatef(18, 0,20);
glScalef(15.0, 1.5, 35.0);
glutSolidCube(1);
glPopMatrix();
glPushMatrix();
//glColor3f(0.0, 0.0, 1.0);
//glRotatef(b,0.0,0.0,1.0);
glTranslatef(-18, 0, 20);
glScalef(15.0, 1.5, 35.0);
glutSolidCube(1);
glPopMatrix();
//glEnable(GL_LIGHTING);
glPopMatrix();
}
dibujabase(){
glPushMatrix();
//lColor3f(0.63, 0.6, 0.6);
// glColor3f(1, 1, 1);
glScalef(1.5, 0.5, 1.5);
glTranslatef(0.0, 2.0, -1.0);
glutSolidCube(5);
glPopMatrix();
}
void dibujaObjeto(void)
{
glPushMatrix();
glTranslatef(0, 4, 0);
glRotatef(rotar, 0, 1,0);
glTranslatef(0.0, salto, 0.0);
GLfloat mat_p_ambient[] = {0.4725,0.4245,0.8645,1};
GLfloat mat_p_diffuse[] = {0.34615,0.5143,0.8903,1};
GLfloat mat_pspecular[] = {1.797357,1.723991,1.708006,1};
GLfloat mat_pshininess[] = {18.2};
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_pspecular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_pshininess);
glMaterialfv(GL_FRONT, GL_AMBIENT, mat_p_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_p_diffuse);
glShadeModel(GL_SMOOTH);
glutSolidSphere(tamanio, 68, 68);
glPopMatrix();
}
static GLfloat floorVertices[4][3] = {
{ -30.0, 0.0, 30.0 },
{ 30.0, 0.0, 30.0 },
{ 30.0, 0.0, -30.0 },
{ -30.0, 0.0, -30.0 },
};
static GLfloat floorVertices2[4][3] = {
{ -30.0, 30.0, 30 },
{ 30.0, 30.0, 30 },
{ 30.0, -30.0, 30 },
{ -30.0, -30.0, 30 },
};
static GLfloat floorVertices3[4][3] = {
{ -30.0, 30.0, -30 },
{ 30.0, 30.0, -30 },
{ 30.0, -30.0, -30 },
{ -30.0, -30.0, -30 },
};
static GLfloat floorVertices4[4][3] = {
{ 30.0, 30.0, 30 },
{ 30.0, 30.0, -30 },
{ 30.0, -30.0, -30 },
{ 30.0, -30.0, 30 },
};
static GLfloat floorVertices5[4][3] = {
{ -50.0, 50.0, 50 },
{ -50.0, 50.0, -50 },
{ -50.0, -50.0, -50 },
{ -50.0, -50.0, 50 },
};
void drawFloor(void)
{
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3fv(floorVertices[0]);
glTexCoord2f(0.0, 20.0);///dice cuantas veces se repite la textura el 20.0
glVertex3fv(floorVertices[1]);
glTexCoord2f(20.0, 20.0);
glVertex3fv(floorVertices[2]);
glTexCoord2f(20.0, 0.0);
glVertex3fv(floorVertices[3]);
glEnd();
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
}
void drawWall(void)
{
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3fv(floorVertices2[0]);
glTexCoord2f(0.0, 20.0);///dice cuantas veces se repite la textura el 20.0
glVertex3fv(floorVertices2[1]);
glTexCoord2f(20.0, 20.0);
glVertex3fv(floorVertices2[2]);
glTexCoord2f(20.0, 0.0);
glVertex3fv(floorVertices2[3]);
glEnd();
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3fv(floorVertices3[0]);
glTexCoord2f(0.0, 20.0);///dice cuantas veces se repite la textura el 20.0
glVertex3fv(floorVertices3[1]);
glTexCoord2f(20.0, 20.0);
glVertex3fv(floorVertices3[2]);
glTexCoord2f(20.0, 0.0);
glVertex3fv(floorVertices3[3]);
glEnd();
glDisable(GL_TEXTURE_2D);
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex3fv(floorVertices4[0]);
glTexCoord2f(0.0, 20.0);///dice cuantas veces se repite la textura el 20.0
glVertex3fv(floorVertices4[1]);
glTexCoord2f(20.0, 20.0);
glVertex3fv(floorVertices4[2]);
glTexCoord2f(20.0, 0.0);
glVertex3fv(floorVertices4[3]);
glEnd();
glDisable(GL_TEXTURE_2D);
}
void dibujarMuro()
{
glDisable(GL_LIGHTING);
glColor3f(1, 1, 1);
glutSolidCube(0.1);
glEnable(GL_LIGHTING);
}
void drawPared(){
/*Se dibujan las paredes.*/
/*Pared izquierda.*/
glPushMatrix();
glTranslatef(10, 12, 25);
glScalef(150.1, 202.0, 25);
glRotatef(70.0, 0.0, 1.0, 0.0);
dibujarMuro();
glPopMatrix();
/*Pared derecha.*/
glPushMatrix();
glTranslatef(10, 12, -25);
glScalef(150.1, 202.0, 25);
glRotatef(-70.0, 0.0, 1.0, 0.0);
dibujarMuro();
glPopMatrix();
}
void dibujapilares(){
glPushMatrix();
glTranslatef(30, 12.0, 10.0);
glScalef(42.0, 103.0, 42.0);
dibujarCastillo(0,0,0.0215,0.1745,0.55,0.7568,0.61424,0.55,0.633,0.727811,0.55,76.8);
glPopMatrix();
/*Primer muro trasero.*/
glPushMatrix();
glTranslatef(30, 12.0, -10.0);
glScalef(42.0, 103.0, 42.0);
dibujarCastillo(0,0,0.0215,0.1745,0.55,0.7568,0.61424,0.55,0.633,0.727811,0.55,76.8);
glPopMatrix();
/*Tercer muro trasero.*/
glPushMatrix();
glTranslatef(30, 12, -28);
glScalef(42.0, 103.0, 42.0);
dibujarCastillo(0,0,0.0215,0.1745,0.55,0.7568,0.61424,0.55,0.633,0.727811,0.55,76.8);
glPopMatrix();
/*Cuarto muro trasero.*/
glPushMatrix();
glTranslatef(30, 12, 28);
glScalef(42.0, 103.0, 42.0);
dibujarCastillo(0,0,0.0215,0.1745,0.55,0.7568,0.61424,0.55,0.633,0.727811,0.55,76.8);
glPopMatrix();
/*Muro izquierdo medio.*/
glPushMatrix();
glTranslatef(0, 12, 25);
glScalef(42.0, 103.0, 42.0);
dibujarCastillo(0,0,0.0215,0.1745,0.55,0.7568,0.61424,0.55,0.633,0.727811,0.55,76.8);
glPopMatrix();
/*Muro derecho medio.*/
glPushMatrix();
glTranslatef(0, 12, -25);
glScalef(42.0, 103.0, 42.0);
dibujarCastillo(0,0,0.0215,0.1745,0.55,0.7568,0.61424,0.55,0.633,0.727811,0.55,76.8);
glPopMatrix();
/*Muro izquierdo frontal.*/
glPushMatrix();
glTranslatef(-30, 15, 18);
glScalef(42.0, 103.0, 42.0);
dibujarCastillo(0,0,0.0215,0.1745,0.55,0.7568,0.61424,0.55,0.633,0.727811,0.55,76.8);
glPopMatrix();
/*Muro derecho frontal.*/
glPushMatrix();
glTranslatef(-30, 15, -18);
glScalef(42.0, 103.0, 42.0);
dibujarCastillo(0,0,0.0215,0.1745,0.55,0.7568,0.61424,0.55,0.633,0.727811,0.55,76.8);
glPopMatrix();
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
posicionAve[0] = 20*cos(lightAngle);
posicionAve[1] = lightHeight;///rota en y
posicionAve[2] = 20*sin(lightAngle);
posicionLuz[0] = 0;
posicionLuz[1] = 20;///rota en y
posicionLuz[2] = -1;
posicionLuz[3] = 0.7;///luz posicional (0) o direccional(1) ilumina a todo
shadowMatrix(sombraPiso, planoPiso, posicionLuz);
glPushMatrix();
glRotatef(angle2, 1.0, 0.0, 0.0);/* mover mouse */
glRotatef(angle, 0.0, 1.0, 0.0);
glLightfv(GL_LIGHT0, GL_POSITION, posicionLuz); /*light position. */
///cambia la posicion de la luz mientras va girando
glLightfv(GL_LIGHT0, GL_POSITION, posicionLuz);//Reacomodar la luz
///se reacomoda
glEnable(GL_BLEND);///transparencia
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glColor4f(1.0, 1.0, 1.0, 0.5);///a la mitad la transparencia
drawFloor();
drawPared();
dibujapilares();
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);///deshabilitamos profundidad
glDisable(GL_LIGHTING);///deshabilitamos luz
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPushMatrix();
glColor4f(0.0, 0.0, 0.0, 0.5);///le ponemos transparencia para que se vea la textura
glMultMatrixf((GLfloat *) sombraPiso);
///es una matriz de sombra al piso
//dibujaObjeto();///Sombra
dibujarAve();
dibujabase();
glPopMatrix();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
///----------------------------------------------------------------
dibujarAve();
//dibujaObjeto(); ///dibujo objeto solito
dibujabase();
///----------------------------------------------------------------
glDisable(GL_LIGHTING);///Simulamos la luz en la esfera
glColor3f(1.0, 1.0, 0.5);
glPushMatrix();
glTranslatef(posicionLuz[0], posicionLuz[1], posicionLuz[2]);
glutSolidSphere(0.8, 20, 20); //simulo la pos. de la luz con una esfera
glColor3f(1, 0.9, 0.4);
glutSolidSphere(3, 30, 30);
glPopMatrix();
glPushMatrix();
/*Se declara un objeto que almacena una superficie cuadrica.*/
GLUquadricObj *quad;
/*Se hace la instancia del objeto.*/
quad = gluNewQuadric();
/*Se define el estilo de la superficie cuadrica (si se desea rellena o formada por lineas).*/
gluQuadricDrawStyle(quad, GLU_FILL);
glTranslated(0.0, 20, -1.0);
glRotatef(90, 1.0, 0.0, 0.0);
glScaled(0.25, 0.25, 2);
glDisable(GL_LIGHTING);
glColor3f(0.4, 0.211, 0.050);
gluCylinder(quad, 4, 4, 10.0, 30.0, 60.0);
glEnable(GL_LIGHTING);
glPopMatrix();
/*Atributos de la base del poste.*/
glEnable(GL_LIGHTING);
glPopMatrix();
glutSwapBuffers();
}
void mouse(int button, int state, int x, int y)
{
if (button == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
moving = 1;
startx = x;
starty = y;
}
if (state == GLUT_UP) {
moving = 0;
}
}
}
void mover(int x, int y)
{
if (moving) {
angle = angle + (x - startx);
angle2 = angle2 + (y - starty);
startx = x;
starty = y;
glutPostRedisplay();
}
}
void idle(void)///REposo
{
static float time = 0.0;
time = glutGet(GLUT_ELAPSED_TIME) / 500.0;///inicializamos e incrementamos medio segundo
//salto =20.0 * fabs(sin(time)*0.7);
lightAngle -= 0.01;
rotar=rotar+0.1;
a=a+1;
glutPostRedisplay();
}
static void
key(unsigned char c, int x, int y)
{
if (c == 27) {
exit(0);
}
glutPostRedisplay();
}
void init(void){
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_PROJECTION);
gluPerspective(40.0,1.0,20.0,500.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0.0, 8.0, 70.0, /* vista en (0,8,60) */
0.0, 10.0, 0.0, /* centro en (0,8,0) */
0.0, 1.0, 0.); /* altura en Y */
glLightfv(GL_LIGHT0, GL_DIFFUSE, colorLuz);
glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glClearColor(0, 0, 0, 1);
texturaPiso();
defPlano(planoPiso, floorVertices[1], floorVertices[2], floorVertices[3]);//Plano para sombra}
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL | GLUT_MULTISAMPLE);
glutInitWindowSize(1024, 800);
glutCreateWindow("LUZ,SOMBRA,REFLEXION Y TEXTURA");
glutDisplayFunc(display);
glutMouseFunc(mouse);
glutMotionFunc(mover);
glutIdleFunc(idle);
glutKeyboardFunc(key);
init();
glutMainLoop();
return 0;
}