/* * tex_boneco.c * Este programa demonstra o uso do mapeamento "esférico" * para criar efeitos de reflexões. * tex_boneco * Pode-se chavear entre as duas imagens pela tecla 't'. * * author: Ting (17/10/06) */ #include #include #include #include #include #include "readBMP.h" static GLfloat vdata[8][3] = { {-1.0, -1.0, -1.0}, {1.0, -1.0, -1.0}, {1.0, 1.0, -1.0}, {-1.0, 1.0, -1.0}, {-1.0, -1.0, 1.0}, {1.0, -1.0, 1.0}, {1.0, 1.0, 1.0}, {-1.0, 1.0, 1.0} }; static GLfloat ndata[6][3] = { {0.0, 0.0, -1.0},{0.0, 1.0, 0.0},{-1.0, 0.0, 0.0}, {1.0, 0.0, 0.0},{0.0, 0.0, 1.0},{0.0, -1.0, 0.0} }; static GLuint vindices[6][4] = { {0,3,2,1}, {2,3,7,6}, {0,4,7,3}, {1,2,6,5}, {4,5,6,7}, {0,1,5,4} }; static GLfloat ambient[] = {0.0, 0.0, 0.0, 1.0}; static GLfloat diffuse[] = {1.0, 1.0, 1.0, 1.0}; static GLfloat specular[] = {1.0, 1.0, 1.0, 1.0}; static GLfloat position[] = {0.0, 0.0, 4.0, 1.0}; static GLfloat fog_color[] = {0.0, 0.0, 0.0, 1.0}; static GLfloat mat_ambient[] = {0.0, 0.0, 0.0, 1.0}; static GLfloat mat_shininess[] = {90.0}; static GLfloat mat_specular[] = {1.0, 1.0, 1.0, 1.0}; static GLfloat mat_diffuse[] = {0.8, 0.8, 0.8, 1.0}; static GLfloat lmodel_ambient[] = {0.2, 0.2, 0.2, 1.0}; GLfloat spin_x=0.0, spin_y=0.0, spin_z=0.0; GLfloat ant=0.0, bra=0.0, cab=0.0; GLuint braco, busto, cabeca, perna; GLuint indice=0; BMPImage *image1, *image2; // data structure for image static GLuint texName[2]; /* Simple BMP reading code, should be adaptable to many systems. Originally from Windows, ported to Linux, now works on my Mac OS system. NOTE!! only reads 24-bit RGB, single plane, uncompressed, unencoded BMP, not all BMPs. BMPs saved by xv should be fine. */ // // This code was created by Jeff Molofee '99 // (www.demonews.com/hosted/nehe) // Ported to Linux/GLUT by Richard Campbell '99 // Code and comments for adaptation to big endian/little endian systems // Nina Amenta '04 // /* Reads a long 32 bit integer; comment out one or the other shifting line below, whichever makes your system work right. */ unsigned int endianReadInt(FILE* file) { unsigned char b[4]; unsigned int i; if ( fread( b, 1, 4, file) < 4 ) return 0; /* LITTLE VS BIG ENDIAN LINES - comment out one or the other */ i = (b[3]<<24) | (b[2]<<16) | (b[1]<<8) | b[0]; // big endian //i = (b[0]<<24) | (b[1]<<16) | (b[2]<<8) | b[3]; // little endian return i; } /* Reads a 16 bit integer; comment out one or the other shifting line below, whichever makes your system work right. */ unsigned short int endianReadShort(FILE* file) { unsigned char b[2]; unsigned short s; if ( fread( b, 1, 2, file) < 2 ) return 0; /* LITTLE VS BIG ENDIAN LINES - comment out one or the other */ s = (b[1]<<8) | b[0]; // big endian //s = (b[0]<<8) | b[1]; // little endian return s; } // quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only. // See http://www.dcs.ed.ac.uk/~mxr/gfx/2d/BMP.txt for more info. int BMPImageLoad(char *filename, BMPImage *image) { FILE *file; unsigned long size; // size of the image in bytes. unsigned long i; // standard counter. unsigned short int planes; // number of planes in image (must be 1) unsigned short int bpp; // number of bits per pixel (must be 24) char temp; // temporary color storage for bgr-rgb conversion. // make sure the file is there. if ((file = fopen(filename, "rb"))==NULL) { printf("File Not Found : %s\n",filename); return 0; } // seek through the bmp header, up to the width/height: fseek(file, 18, SEEK_CUR); // read the width if (!(image->sizeX = endianReadInt(file))) { printf("Error reading width from %s.\n", filename); return 0; } printf("Width of %s: %lu\n", filename, image->sizeX); // read the height if (!(image->sizeY = endianReadInt(file))) { printf("Error reading height from %s.\n", filename); return 0; } printf("Height of %s: %lu\n", filename, image->sizeY); // calculate the size (assuming 24 bits or 3 bytes per pixel). size = image->sizeX * image->sizeY * 3; // read the planes if (!(planes=endianReadShort(file))) { printf("Error reading planes from %s.\n", filename); return 0; } if (planes != 1) { printf("Planes from %s is not 1: %u\n", filename, planes); return 0; } // read the bits per pixel if (!(bpp = endianReadShort(file))) { printf("Error reading bpp from %s.\n", filename); return 0; } if (bpp != 24) { printf("Bpp from %s is not 24: %u\n", filename, bpp); return 0; } // seek past the rest of the bitmap header. fseek(file, 24, SEEK_CUR); // read the data. image->data = (char *) malloc(size); if (image->data == NULL) { printf("Error allocating memory for color-corrected image data"); return 0; } if ((i = fread(image->data, size, 1, file)) != 1) { printf("Error reading image data from %s.\n", filename); return 0; } for (i=0;i rgb) temp = image->data[i]; image->data[i] = image->data[i+2]; image->data[i+2] = temp; } // we're done. return 1; } /* Desenhar um cubo */ static void cube() { int i, j; /* desenhar o cubo */ for (i=0; i<6; i++) { glNormal3fv(ndata[i]); glBegin(GL_POLYGON); glVertex3fv(&vdata[vindices[i][0]][0]); glVertex3fv(&vdata[vindices[i][1]][0]); glVertex3fv(&vdata[vindices[i][2]][0]); glVertex3fv(&vdata[vindices[i][3]][0]); glEnd(); } } static void boneco() { /* criar braco */ /* gerar um indice de uma lista */ braco = glGenLists(1); /* inicializar o conteudo da lista "braco". Ha dois modos: GL_COMPLIE: somente armazena; GL_COMPILE_AND_EXECUTE: armazena e executa */ glNewList(braco, GL_COMPILE); glScalef(0.09, 0.28, 0.09); cube(); /* finalizar a lista inicializada */ glEndList(); /* criar busto */ busto = glGenLists(1); glNewList(busto, GL_COMPILE); glScalef(0.35, 0.525, 0.2); cube(); glEndList(); /* criar cabeca */ cabeca = glGenLists(1); glNewList(cabeca, GL_COMPILE); glScalef(0.2, 0.2, 0.2); cube(); glEndList(); /* criar perna */ perna = glGenLists(1); glNewList(perna, GL_COMPILE); glScalef(0.09, 0.57, 0.09); cube(); glEndList(); } void init(void) { glClearColor(0.0, 0.0, 0.0, 0.0); /* definir a fonte de luz */ glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, specular); glLightfv(GL_LIGHT0, GL_POSITION, position); /* definir o material da superficie do boneco */ glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, mat_shininess); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); /* definir a luz do ambiente */ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); /* definir o modo de iluminação dos dois lados */ glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); /* definir o modo de tonalizacao */ glShadeModel(GL_SMOOTH); /* setar a convencao de orientacao. Ha duas alternativas: GL_CCW (anti-horario) e GL_CW (horario) */ glFrontFace(GL_CCW); /* definir as faces a serem discardadas. Ha tres alternativas: GL_FRONT, GL_BACK e GL_FRONT_AND_BACK */ glCullFace(GL_BACK); /* definir o modo como os pixels são armazenados na memória do processador */ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); /* gerar nomes para 2 texturas */ glGenTextures (2, texName); /* definir a textura 1 */ glBindTexture (GL_TEXTURE_2D, texName[0]); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image1->sizeX, image1->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image1->data); free(image1->data); free(image1); /* definir a textura 2 */ glBindTexture (GL_TEXTURE_2D, texName[1]); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, image2->sizeX, image2->sizeY, GL_RGB, GL_UNSIGNED_BYTE, image2->data); free(image2->data); free(image2); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); /* definir a função de z-teste */ glDepthFunc(GL_LESS); /* habilitar as funcionalidades ... */ glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); /* desenhar o boneco */ boneco(); } void display(void) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); /* habilitar a textura */ glEnable(GL_TEXTURE_2D); /* setar a cor de desenho em branco (1,1,1) */ glColor3f (1.0, 1.0, 1.0); /* carregar a matriz de identidade na pilha de matriz de transformacao */ glLoadIdentity(); /* concatenar a matriz de translacao com a do topo da pilha */ glTranslatef(0.0,0.0,-3.8); /* concatenar a matriz de rotacao com a do topo da pilha */ glRotatef(spin_x,1.0,0.0,0.0); /* concatenar a matriz de rotacao com a do topo da pilha */ glRotatef(spin_y,0.0,1.0,0.0); /* concatenar a matriz de rotacao com a do topo da pilha */ glRotatef(spin_z,0.0,0.0,1.0); /* concatenar a matriz de mudanca de escala com a do topo da pilha */ /* aumentar a escala para ficar compatível com o tamanho de texels */ glScalef(6.,6.,6.); /* draw object */ /* ativar a textura */ glBindTexture (GL_TEXTURE_2D, texName[indice]); /* desenhar a figura */ /* desenhar o busto */ glPushMatrix(); glCallList(busto); glPopMatrix(); /* desenhar as pernas */ glPushMatrix(); glTranslatef(0.2, -1.12, 0.0); glCallList(perna); glPopMatrix(); glPushMatrix(); glTranslatef(-0.2, -1.12, 0.0); glCallList(perna); glPopMatrix(); /* desenhar a cabeca */ glPushMatrix(); glTranslatef(0.0, 0.73, 0.0); // rotacionar a cabeca no sentido anti-horario em torno de y */ glRotatef(cab, 0.0, 1.0, 0.0); glCallList(cabeca); glPopMatrix(); /* desenhar os bracos */ glPushMatrix(); glTranslatef(-0.45, 0.26, 0.0); glPushMatrix(); glCallList(braco); glPopMatrix(); glPushMatrix(); glTranslatef(0.0, -0.59, 0.0); glCallList(braco); glPopMatrix(); glPopMatrix(); glPushMatrix(); glTranslatef(0.45, 0.26, 0.0); /* rotationar o braco no sentido anti-horario em trono do x */ glTranslatef(.0, .28, .0); glRotatef(bra, 1.0, 0.0, 0.0); glTranslatef(.0, -.28, .0); glPushMatrix(); glCallList(braco); glPopMatrix(); glPushMatrix(); glTranslatef(0., -0.59, 0.0); /* rotationar o anti-braco no sentido anti-horario em trono do x */ glTranslatef(.0, .28, .0); glRotatef(ant, 1.0, 0.0, 0.0); glTranslatef(.0, -0.28, .0); glCallList(braco); glPopMatrix(); glPopMatrix(); /* forcar a execucao dos comandos enviados a OpenGL */ glFlush (); } void reshape(int width, int height) { glViewport( 0, 0, width, height ); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho (-12.0, 12.0, -12.0, 12.0, 0.0, 12.0); glMatrixMode(GL_MODELVIEW); } /* ARGSUSED1 */ void keyboard(unsigned char key, int x, int y) { switch (key) { case 'a': /* increment -10.0 no ângulo de rotação em torno do eixo x */ ant -= 10.0; if (ant < -160.0) ant = 0.0; break; case 'b': /* increment -10.0 no ângulo de rotação em torno do eixo x */ bra -= 10.0; if (bra < -160.0) bra = 0.0; break; case 'c': /* increment -10.0 no ângulo de rotação em torno do eixo x */ cab += 10.0; break; case 'x': /* increment +10.0 no ângulo de rotação em torno do eixo x */ spin_x += 10.0; break; case 'y': /* incrementa +10.0 no ângulo de rotação em torno do eixo y */ spin_y += 10.0; break; case 'z': /* increment +10.0 no ângulo de rotação em torno do eixo z */ spin_z += 10.0; break; case 't': /* toggle textura */ if (indice == 1) indice = 0; else indice = 1; break; case 'r': /* reset */ spin_x = spin_y = spin_z = 0.0; break; case 27: exit(0); return; } /* forçar um evento para ativar o redesenho */ glutPostRedisplay(); } int main(int argc, char **argv) { GLenum type; /* alocar espaço para imagem1 */ image1 = (BMPImage *) malloc(sizeof(BMPImage)); if (image1 == NULL) { printf("Error allocating space for image"); exit(0); } if (!BMPImageLoad(argv[1], image1)) { exit(1); } /* alocar espaço para imagem2 */ image2 = (BMPImage *) malloc(sizeof(BMPImage)); if (image2 == NULL) { printf("Error allocating space for image"); exit(0); } if (!BMPImageLoad(argv[2], image2)) { exit(1); } glutInit(&argc, argv); glutInitWindowPosition(100, 100); glutInitWindowSize(500, 500); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_SINGLE); glutCreateWindow("Boneco Espelho"); init(); glutReshapeFunc(reshape); glutKeyboardFunc(keyboard); glutDisplayFunc(display); glutMainLoop(); return 0; }