Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Myho

[Código] Carregador de BMP e Camera 3D

Recommended Posts

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

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

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

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.