jueves, 1 de diciembre de 2016


Sombras














#include <GL/glut.h>

GLfloat angle = 0,angle2 = 0;
int moving, startx, starty;

static GLfloat posicionLuz[] = {12, 20, 12, 0.5};//x,y,z,luz posicional/direccional
static GLfloat planoPiso[4]; //plano donde se proyeta la sombra
static GLfloat matSombra[4][4];

static GLfloat planoPared[0]; //plano donde se proyeta la sombra
static GLfloat matSombraPared[4][4];

enum {X, Y, Z, W};
enum {A, B, C, D};

/* Matriz de proyeccion de la sombra */
void matrizDsombra(GLfloat matrizSombra[4][4],GLfloat plano[4], GLfloat posLuz[4]) //aqui se utiliza la posicion de la luz y el plano para generar la matriz de sombra
{   GLfloat punto;

    // Producto punto entre vector light position y la normal del plano
    punto = plano[X] * posLuz[X] + plano[Y] * posLuz[Y] +
        plano[Z] * posLuz[Z] + plano[W] * posLuz[W];

    matrizSombra[0][0] = punto - posLuz[X] * plano[X];
    matrizSombra[1][0] = 0.f - posLuz[X] * plano[Y];
    matrizSombra[2][0] = 0.f - posLuz[X] * plano[Z];
    matrizSombra[3][0] = 0.f - posLuz[X] * plano[W];

    matrizSombra[X][1] = 0.f - posLuz[Y] * plano[X];
    matrizSombra[1][1] = punto - posLuz[Y] * plano[Y];
    matrizSombra[2][1] = 0.f - posLuz[Y] * plano[Z];
    matrizSombra[3][1] = 0.f - posLuz[Y] * plano[W];

    matrizSombra[X][2] = 0.f - posLuz[Z] * plano[X];
    matrizSombra[1][2] = 0.f - posLuz[Z] * plano[Y];
    matrizSombra[2][2] = punto - posLuz[Z] * plano[Z];
    matrizSombra[3][2] = 0.f - posLuz[Z] * plano[W];

    matrizSombra[X][3] = 0.f - posLuz[W] * plano[X];
    matrizSombra[1][3] = 0.f - posLuz[W] * plano[Y];
    matrizSombra[2][3] = 0.f - posLuz[W] * plano[Z];
    matrizSombra[3][3] = punto - posLuz[W] * plano[W];

}

void matrizDsombraPared(GLfloat matrizSombra[4][4],GLfloat plano[4], GLfloat posLuz[4]) //aqui se utiliza la posicion de la luz y el plano para generar la matriz de sombra
{   GLfloat punto;

    // Producto punto entre vector light position y la normal del plano
    punto = plano[X] * posLuz[X] + plano[Y] * posLuz[Y] +
        plano[Z] * posLuz[Z] + plano[W] * posLuz[W];

    matrizSombra[0][0] = punto - posLuz[X] * plano[X];
    matrizSombra[1][0] = 0.f - posLuz[X] * plano[Y];
    matrizSombra[2][0] = 0.f - posLuz[X] * plano[Z];
    matrizSombra[3][0] = 0.f - posLuz[X] * plano[W];

    matrizSombra[X][1] = 0.f - posLuz[Y] * plano[X];
    matrizSombra[1][1] = punto - posLuz[Y] * plano[Y];
    matrizSombra[2][1] = 0.f - posLuz[Y] * plano[Z];
    matrizSombra[3][1] = 0.f - posLuz[Y] * plano[W];

    matrizSombra[X][2] = 0.f - posLuz[Z] * plano[X];
    matrizSombra[1][2] = 0.f - posLuz[Z] * plano[Y];
    matrizSombra[2][2] = punto - posLuz[Z] * plano[Z];
    matrizSombra[3][2] = 0.f - posLuz[Z] * plano[W];

    matrizSombra[X][3] = 0.f - posLuz[W] * plano[X];
    matrizSombra[1][3] = 0.f - posLuz[W] * plano[Y];
    matrizSombra[2][3] = 0.f - posLuz[W] * plano[Z];
    matrizSombra[3][3] = punto - posLuz[W] * plano[W];

}


/* Ecuación del plano dados 3 puntos. */
void ecPlano(GLfloat plano[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  (para calcular la ecuación del plano*/
    plano[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
    plano[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
    plano[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];

    plano[D] = -(plano[A] * v0[X] + plano[B] * v0[Y] + plano[C] * v0[Z]);
}

void ecPlanoPared(GLfloat plano[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  (para calcular la ecuación del plano*/
    plano[A] = vec0[Y] * vec1[Z] - vec0[Z] * vec1[Y];
    plano[B] = -(vec0[X] * vec1[Z] - vec0[Z] * vec1[X]);
    plano[C] = vec0[X] * vec1[Y] - vec0[Y] * vec1[X];

    plano[D] = -(plano[A] * v0[X] + plano[B] * v0[Y] + plano[C] * v0[Z]);
}

void objeto(void)
{
    glPushMatrix();
        glTranslatef(0, 4, -4);
        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); //propiedades de material
        glMaterialfv(GL_FRONT, GL_SHININESS, mat_pshininess);
        glMaterialfv(GL_FRONT, GL_AMBIENT, mat_p_ambient);
        glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_p_diffuse);
        glutSolidSphere(4, 68, 68);
        //glutWireSphere(4, 68, 68);
        //glutSolidCube(5.5);
        //glutWireCube(5.5);
        //glutWireTeapot(5);
        //glutSolidTorus(0.3, 3, 64, 64);
    glPopMatrix();
}

static GLfloat verticesPiso[4][3] = {
    { -10.0, 0.0,  10.0 },
    {  10.0, 0.0,  10.0 },
    {  10.0, 0.0, -10.0 },
    { -10.0, 0.0, -10.0 },
};

static GLfloat verticesPared1[4][3] = {
    { 10.0, 0.0,  -10.0 },
    {  -10.0, 0.0,  -10.0 },
    {  -10.0, 10.0, -10.0 },
    { 10.0, 10.0, -10.0 },
};

void dibujaPiso(void)
{
    glDisable(GL_LIGHTING);
    glBegin(GL_QUADS);
    glVertex3fv(verticesPiso[0]);
    glVertex3fv(verticesPiso[1]);
    glVertex3fv(verticesPiso[2]);
    glVertex3fv(verticesPiso[3]);
    glEnd();
    glEnable(GL_LIGHTING);
}

void dibujaPared1(void)
{
    glDisable(GL_LIGHTING);
    glBegin(GL_QUADS);
    glVertex3fv(verticesPared1[0]);
    glVertex3fv(verticesPared1[1]);
    glVertex3fv(verticesPared1[2]);
    glVertex3fv(verticesPared1[3]);
    glEnd();
    glEnable(GL_LIGHTING);
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    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);
        ///////////////////////////////////////////////
        glColor4f(0.1, 0.55, 0.55, 0.5);
        dibujaPiso();
        dibujaPared1();
        ///////////////////////////////////////////////
        glDisable(GL_LIGHTING);
        glDisable(GL_DEPTH_TEST);
        glEnable(GL_BLEND); //habilita la transparencia
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        glPushMatrix();
            glColor4f(0.0, 0.0, 0.0, 0.1);//color atenuacion de la sombra
            glMultMatrixf((GLfloat *) matSombraPared); //para proyectar la sombra en la pared
                objeto();//Sombra
        glPopMatrix();

        glPushMatrix();
            glColor4f(0.0, 0.0, 0.0, 0.1);//color atenuacion de la sombra
            glMultMatrixf((GLfloat *) matSombra); //para proyectar la sombra en el piso
                objeto();//Sombra
        glPopMatrix();


        glDisable(GL_BLEND);
        glEnable(GL_LIGHTING);
        glEnable(GL_DEPTH_TEST);
        ////////////////////////////////////////////////

        objeto();     //dibujo objeto original
        ////////////////////////////////////////////////
        glDisable(GL_LIGHTING); //desabilitar la luz porque si no se ve del color del material
        glTranslatef(posicionLuz[0], posicionLuz[1], posicionLuz[2]);
        glColor3f(1.0, 1.0, 0.0);
        glutSolidSphere(0.5, 10, 10);
        ////////////////////////////////////////////////

    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 init(void){
    glMatrixMode(GL_PROJECTION);
    gluPerspective(25.0,2.0,20.0,150.0);
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(0.0, 8.0, 60.0,  /* vista en (0,8,60) */
              0.0, 8.0, 0.0,      /* centro en (0,8,0) */
              0.0, 1.0, 0.0);      /* altura en Y */
    glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 2.5);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);

    glClearColor(0.93, 0.93, 0.93, 1);
    ecPlano(planoPiso, verticesPiso[1], verticesPiso[2], verticesPiso[3]);//Plano para sombra se ponen los planos que sean necesarios
    ecPlanoPared(planoPared, verticesPared1[0], verticesPared1[1], verticesPared1[2]);
    matrizDsombra(matSombra, planoPiso, posicionLuz);    //matriz de la sombra recalcular?
    matrizDsombraPared(matSombraPared, planoPared, posicionLuz);
}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL | GLUT_MULTISAMPLE);
    glutInitWindowSize(800, 400);
    glutCreateWindow("Sombra Plana");
    glutDisplayFunc(display);
    glutMouseFunc(mouse);
    glutMotionFunc(mover);
    init();
    glutMainLoop();
    return 0;
}