Myho 2 Denunciar post Postado Dezembro 12, 2008 Ola pessoal. Antes de tudo desculpem se isso foge muito do conteudo desse forum, mas espero que possa ser interessante para aqueles que buscam uma introducao a OpenGL + GLUT + C++. Primeiro Post - BMP Loader Segundo Post - Camera 3d Terceiro Post - Programa teste Compilado no Windows Vista com Visual Studio 2005 A Primeira classe serve para carregar imagens em .BMP Do jeito que foi projetada, ela pode guardar apenas uma imagem por vez. Então se quiser trabalhar com varias imagens pode-se usar o valor retornado por LoadBitmap para ir armazenando as imagens em outras variaveis. No meu caso eu precisava apenas das texturas, e fiz dois metodos, voce pode criar uma textura a partir da ultima imagem carregada, ou carregar a imagem ja como textura. Quando se carrega como textura a imagem é deletada, ficando apenas a textura. CBMPLoader.h #include <windows.h> #include <GL/glut.h> #include <iostream> #include <fstream> using namespace std; #define BITMAP_ID 0x4D42 // Identificacao do BMP ( Magic Number ) #define MAX_TEXTURES 10 // Definindo a quantidade maxima de texturas que posso usar ( se quiser usar mais texturas q isso, é soh alterar ) class CBMPLoader { public: CBMPLoader(); ~CBMPLoader(); unsigned char* LoadBitmap(char *filename); // Carrega um arquivo bmp apartir do seu caminho e retorna o vetor contendo os pixels da imagem void CreateTexture(int id); // Cria uma textura com a imagem atual void LoadTextureFromBitmap(char *filename,int id); // Engloba os dois metodos acima, uma facilitacao apenas void FreeImage(); // libera a imagem private: unsigned int uiID; // ID da textura int iImageWidth; // Largura int iImageHeight; // Altura unsigned char *image; // Ponteiro para a imagem unsigned int textureVec[MAX_TEXTURES]; // Vetor que armazena as Id das texturas }; CBMPLoader.cpp #include"CBMPLoader.h" CBMPLoader::CBMPLoader() { // Inicializa as variaveis image = 0; iImageWidth = 0; iImageHeight = 0; glGenTextures(MAX_TEXTURES,textureVec); } CBMPLoader::~CBMPLoader() { FreeImage(); } unsigned char* CBMPLoader::LoadBitmap(char *filename) { ifstream file; // Variaveis da windows.h para guardar o cabecalho e informacoes do BMP BITMAPINFOHEADER bitmapInfoHeader; BITMAPFILEHEADER header; //Variavel auxiliar para converter o BGR do BMP pra o RGB do OpenGl ( mais a frente sera feita a conversao ) unsigned char ucConverte = 0; file.open(filename,ios::binary); file.read(reinterpret_cast<char*>(&header),sizeof(BITMAPFILEHEADER)); if(header.bfType != BITMAP_ID) { file.close(); return NULL; } file.read(reinterpret_cast<char*>(&bitmapInfoHeader), sizeof(BITMAPINFOHEADER)); iImageWidth = bitmapInfoHeader.biWidth; iImageHeight = bitmapInfoHeader.biHeight; if(bitmapInfoHeader.biSizeImage == 0) bitmapInfoHeader.biSizeImage = bitmapInfoHeader.biWidth * bitmapInfoHeader.biHeight * 3; file.seekg(header.bfOffBits); image = new unsigned char[bitmapInfoHeader.biSizeImage]; if(!image) { delete[] image; file.close(); return NULL; } file.read(reinterpret_cast<char*>(image),bitmapInfoHeader.biSizeImage); // conversao de bgr para rgb for(int iIndex = 0; iIndex < (int)bitmapInfoHeader.biSizeImage; iIndex+=3) { ucConverte = image[iIndex]; image[iIndex] = image[iIndex+2]; image[iIndex+2] = ucConverte; } file.close(); return image; } void CBMPLoader::CreateTexture(int id) { textureVec[id] = id; glBindTexture(GL_TEXTURE_2D, textureVec[id]); gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, iImageWidth, iImageHeight, GL_RGB, GL_UNSIGNED_BYTE, image); } void CBMPLoader::LoadTextureFromBitmap(char *filename,int id) { LoadBitmap(filename); CreateTexture(id); FreeImage(); } void CBMPLoader::FreeImage() { if(image){ delete[] image; image = 0; } } Compartilhar este post Link para o post Compartilhar em outros sites
Myho 2 Denunciar post Postado Dezembro 12, 2008 A segunda classe simula uma camera em primeira pessoa. Setas direcionais para cima e para baixo movimentam a camera para frente e para tras Setas direcionais esquerda e direita rotacionam a camera HOME e END deslizam a camera para esquerda ou direita PgUp PgDown olham para cima e para baixo Camera.h #include <windows.h> #include <GL/glut.h> #include <cmath> #include <iostream> using namespace std; // Meio portugues meio ingles.. whatever =P // Definindo apenas as velocidades de cada movimento da camera #define FRENTE 0.1f // andar para frente #define TRAS -0.1f // andar para tras #define DIREITA -0.1f // rotacionar para direita #define ESQUERDA 0.1f // rotacionar para esquerda #define UP 0.01f // olhar para cima #define DOWN -0.01f // olhar para baixo #define STRAFE_LEFT -0.1f // desliza para esquerda #define STRAFE_RIGHT 0.1f // desliza para direita class CCamera { public: CCamera(void); ~CCamera(void); void MoveCamera(float MoveSpeed); // Movimenta a camera para frente e para tras void RotateCamera(float f_Direction); // Rotaciona a camera e a visao void SetCamera( float f_xPos, float f_yPos, float f_zPos, // Inicializa a camera ( apenas chama o GluLookAt ) float f_xEye, float f_yEye, float f_zEye, bool b_UpX, bool b_UpY, bool b_Upz); void PositionCamera(float f_xPos, float f_yPos, float f_zPos); // Posiciona a camera no mundo void PointCamera(float f_xEye, float f_yEye, float f_zEye); // Seta para onde a camera aponta void SetCameraUp(bool b_UpX, bool b_UpY, bool b_UpZ); // Define qual o vetor aponta para cima ( Y geralmente) void LookUpDown(float f_Look); // Olha para cima e para baixo *** NAO ROTACIONA, APENAS OLHA *** void Strafe(float f_Direction); // Faz movimento perpendicular ( esquerda ou direita ) à direcao que a camera aponta void UpDate(); // Sempre deve ser feita esta atualizacao quando alguma alteracao e feita na camera private: float PosX, PosY, PosZ; // variaveis que guardam a posicao da camera no mundo float EyeX, EyeY, EyeZ; // variaveis que guardam a direcao para onde a camera aponta bool CamUpX, CamUpY,CamUpZ; // variaveis que guardam o vetor que aponta para cima }; Camera.cpp #include "Camera.h" CCamera::CCamera(void) { } CCamera::~CCamera(void) { } void CCamera::MoveCamera(float f_Direction) { // Pega o vetor para onde a camera esta olhando float vecX = EyeX - PosX; float vecY = EyeY - PosY; float vecZ = EyeZ - PosZ; // Calcula o modulo do vetor float normal = 1 /(float)sqrt(vecX * vecX + vecY * vecY + vecZ * vecZ); // Normaliza as direcoes, para ter o tamanho do vetor em cada eixo vecX *= normal; vecY *= normal; vecZ *= normal; // Multiplico o valor passado como direcao pelo tamanho do vetor no eixo X e no Z PosX += vecX * f_Direction; PosZ += vecZ * f_Direction; //Aqui faco o mesmo mas como a direcao para onde a camera esta olhando EyeX += vecX * f_Direction; EyeZ += vecZ * f_Direction; } void CCamera::RotateCamera(float RotateAngle) { // Calculo antecipadamente o Cosseno e o Seno do angulo float CossAng = (float)cos(RotateAngle); float SinAng = (float)sin(RotateAngle); // Velocidade e em torno de qual angulo deve rotar float xSpeed = 0; float ySpeed = 0.5; float zSpeed = 0; // Pego o vetor para onde a camera esta olhando atualmente float vecX = EyeX - PosX; float vecY = EyeY - PosY; float vecZ = EyeZ - PosZ; // Calculo o modulo do vetor float normal = 1 / (float)sqrt(vecX * vecX + vecY * vecY + vecZ * vecZ); // Normaliza as direcoes, para ter o tamanho do vetor em cada eixo vecX *= normal; vecY *= normal; vecZ *= normal; // CALCULA O NOVO X float NewVecX = (CossAng + (1 - CossAng) * xSpeed) * vecX; NewVecX += ((1 - CossAng) * xSpeed * ySpeed - zSpeed * SinAng)* vecY; NewVecX += ((1 - CossAng) * xSpeed * zSpeed + ySpeed * SinAng) * vecZ; // CALCULA O NOVO Y float NewVecY = ((1 - CossAng) * xSpeed * ySpeed + zSpeed * SinAng) * vecX; NewVecY += (CossAng + (1 - CossAng) * ySpeed) * vecY; NewVecY += ((1 - CossAng) * ySpeed * zSpeed - xSpeed * SinAng) * vecZ; // CALCULA O NOVO Z float NewVecZ = ((1 - CossAng) * xSpeed * zSpeed - ySpeed * SinAng) * vecX; NewVecZ += ((1 - CossAng) * ySpeed * zSpeed + xSpeed * SinAng) * vecY; NewVecZ += (CossAng + (1 - CossAng) * zSpeed) * vecZ; //Adiciono a nova vista a antiga, corrigindo assim a visao da camera. EyeX = PosX + NewVecX; EyeY = PosY + NewVecY; EyeZ = PosZ + NewVecZ; } void CCamera::SetCamera( float f_xPos, float f_yPos, float f_zPos, float f_xEye, float f_yEye, float f_zEye, bool b_UpX, bool b_UpY, bool b_UpZ) { //Posicao da Camera PosX = f_xPos; PosY = f_yPos; PosZ = f_zPos; //Direcao para onde a camera aponta EyeX = f_xEye; EyeY = f_yEye; EyeZ = f_zEye; // Vetor UP ( qual vetor aponta para cima ) CamUpX = b_UpX; CamUpY = b_UpY; CamUpZ = b_UpZ; RotateCamera(0); MoveCamera(0); } void CCamera::PositionCamera(float f_xPos, float f_yPos, float f_zPos) { PosX = f_xPos; PosY = f_yPos; PosZ = f_zPos; } void CCamera::PointCamera(float f_xEye, float f_yEye, float f_zEye) { EyeX = f_xEye; EyeY = f_yEye; EyeZ = f_zEye; } void CCamera::SetCameraUp(bool b_UpX, bool b_UpY, bool b_UpZ) { CamUpX = b_UpX; CamUpY = b_UpY; CamUpZ = b_UpZ; } void CCamera::UpDate() { gluLookAt(PosX, PosY, PosZ, EyeX, EyeY, EyeZ, CamUpX, CamUpY, CamUpZ); } void CCamera::LookUpDown(float f_Look) { // Uma boa ideia eh colocar um limite para esse " olhar para cima ou para baixo " EyeY += f_Look; } void CCamera::Strafe(float f_Direction) { // FAZ OS MESMOS PASSOA DA FUNCAO DE MOVER A CAMERA float vecX = EyeX - PosX; float vecY = EyeY - PosY; float vecZ = EyeZ - PosZ; float normal = 1 /(float)sqrt(vecX * vecX + vecY * vecY + vecZ * vecZ); vecX *= normal; vecY *= normal; vecZ *= normal; // AQUI ESTA A DIFERENCA, FAZENDO O PRODUTO VETORIAL, PARA OBTER UM VETOR ORTOGONAL // ENTRE O VETOR QUE INDICA OQUE ESTAMOS VENDO E O VETOR CIMA (UP). float ortoVecX = (vecY * CamUpZ) - (vecZ * CamUpY); float ortoVecY = (vecZ * CamUpX) - (vecX * CamUpZ); float ortoVecZ = (vecX * CamUpY) - (vecY * CamUpX); // posiciona a camera PosX += ortoVecX * f_Direction; PosZ += ortoVecZ * f_Direction; // ajusta a visao EyeX += ortoVecX * f_Direction; EyeZ += ortoVecZ * f_Direction; } Compartilhar este post Link para o post Compartilhar em outros sites
Myho 2 Denunciar post Postado Dezembro 12, 2008 E agora um programa de teste para as duas classes. As imagens que utilizo no programa estao disponiveis no link abaixo. http://rapidshare.com/files/172562621/Imagens.rar Para quem quiser, segue o link com todos arquivos do fonte, imagens e um executavel do projeto. http://rapidshare.com/files/172563250/Camera.rar main #include "CBMPLoader.h" #include "Camera.h" CCamera camera; CBMPLoader loader; void GetImput(); void SkyBox(); void LoadTextures(); void Desenha(); // Apersar da GLUT proporcionar a criacao dessa CallBack de teclado, o input nao fica natural. // Por isso existe a funcao GetInput(), da qual utilizo as funcoes do windows.h void Teclado (unsigned char key, int x, int y) { if (key == 27) exit(0); } void Inicializa(void) { glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glClearColor(0,0,0,1); glMatrixMode(GL_PROJECTION); gluPerspective(45,800/600,0.1,500); glMatrixMode(GL_MODELVIEW); camera.SetCamera(0.0f,1.8f,0.0f, 0.0f,1.9f,-50.0f, 0,true,0); LoadTextures(); } int main(void) { glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(800,600); glutCreateWindow("CAMERA 3D"); glutDisplayFunc(Desenha); glutKeyboardFunc (Teclado); Inicializa(); glutMainLoop(); return 0; } void GetImput() { if(GetKeyState(VK_UP) & 0x80) { camera.MoveCamera(FRENTE); } if(GetKeyState(VK_DOWN) & 0x80) { camera.MoveCamera(TRAS); } if(GetKeyState(VK_LEFT) & 0x80) camera.RotateCamera(ESQUERDA); if(GetKeyState(VK_RIGHT) & 0x80) camera.RotateCamera(DIREITA); if(GetKeyState(VK_PRIOR) & 0x80) camera.LookUpDown(UP); if(GetKeyState(VK_NEXT) & 0x80) camera.LookUpDown(DOWN); if(GetKeyState(VK_HOME) & 0x80) camera.Strafe(STRAFE_LEFT); if(GetKeyState(VK_END) & 0x80) camera.Strafe(STRAFE_RIGHT); } void SkyBox() { //chao glBindTexture(GL_TEXTURE_2D,6); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f);glVertex3f(-100,0,-100); //v0 glTexCoord2f(50.0f,0.0f);glVertex3f( 100,0,-100); // v1 glTexCoord2f(50.0f,50.0f);glVertex3f( 100,0, 100); //v2 glTexCoord2f(0.0f,50.0f);glVertex3f(-100,0, 100); // v3 glEnd(); // ceu glBindTexture(GL_TEXTURE_2D,5); glBegin(GL_QUADS); glTexCoord2f(1.0f,0.0f);glVertex3f(-100,70,-100); //v0 glTexCoord2f(0.0f,0.0f);glVertex3f( 100,70,-100); // v1 glTexCoord2f(0.0f,1.0f);glVertex3f( 100,70, 100); //v2 glTexCoord2f(1.0f,1.0f);glVertex3f(-100,70, 100); // v3 glEnd(); // parede lateral +X glBindTexture(GL_TEXTURE_2D,3); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f);glVertex3f(100,-70,100); //v0 glTexCoord2f(0.0f,1.0f);glVertex3f(100,70,100); // v1 glTexCoord2f(1.0f,1.0f);glVertex3f(100,70,-100); //v2 glTexCoord2f(1.0f,0.0f);glVertex3f(100,-70, -100); // v3 glEnd(); // -x glBindTexture(GL_TEXTURE_2D,4); glBegin(GL_QUADS); glTexCoord2f(1.0f,0.0f);glVertex3f(-100,-70,100); //v0 glTexCoord2f(1.0f,1.0f);glVertex3f(-100,70,100); // v1 glTexCoord2f(0.0f,1.0f);glVertex3f(-100,70,-100); //v2 glTexCoord2f(0.0f,0.0f);glVertex3f(-100,-70, -100); // v3 glEnd(); // -z glBindTexture(GL_TEXTURE_2D,2); glBegin(GL_QUADS); glTexCoord2f(1.0f,0.0f);glVertex3f(-100,-70, -100); //v0 glTexCoord2f(0.0f,0.0f);glVertex3f( 100,-70, -100); // v1 glTexCoord2f(0.0f,1.0f);glVertex3f( 100,70, -100); //v2 glTexCoord2f(1.0f,1.0f);glVertex3f(-100,70, -100); // v3 glEnd(); //+z glBindTexture(GL_TEXTURE_2D,1); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f);glVertex3f(-100,-70, 100); //v0 glTexCoord2f(1.0f,0.0f);glVertex3f( 100,-70, 100); // v1 glTexCoord2f(1.0f,1.0f);glVertex3f( 100,70, 100); //v2 glTexCoord2f(0.0f,1.0f);glVertex3f(-100,70, 100); // v3 glEnd(); } void LoadTextures() { loader.LoadTextureFromBitmap("dsback.bmp",1); loader.LoadTextureFromBitmap("dsfront.bmp",2); loader.LoadTextureFromBitmap("dsleft.bmp",3); loader.LoadTextureFromBitmap("dsright.bmp",4); loader.LoadTextureFromBitmap("dstop.bmp",5); loader.LoadTextureFromBitmap("grass.bmp",6); } void Desenha(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); GetImput(); // leitura de input camera.UpDate(); // atualiza a camera SkyBox(); // desenha o ceu glutSwapBuffers(); glutPostRedisplay(); } Compartilhar este post Link para o post Compartilhar em outros sites