Скачиваний:
34
Добавлен:
15.09.2014
Размер:
8.59 Кб
Скачать
#include <windows.h>
#include <gl\gl.h>
#include <gl\wglext.h>
#include <gl\glu.h>
#include <fstream>
#include <cmath>
#include <cstdlib>
#include <string>

using namespace std;

#define STEP 0.5f

#pragma pack(1)
struct TgaHeader
    {
    GLbyte	identsize;              
    GLbyte	colorMapType;           // 0 - обычный цвет, 1 - индексированный
    GLbyte	imageType;              // 0 = нет, 1 = индексированный, 2 = rgb, 3 = черно белый, +8=сжатие алгоритмом rle
    unsigned short	colorMapStart;
    unsigned short	colorMapLength;
    unsigned char 	colorMapBits;
    unsigned short	xstart;
    unsigned short	ystart;
    unsigned short	width;
    unsigned short	height;
    GLbyte	bits;
    GLbyte	descriptor;
    };

GLuint ReadTGA(const wstring& filename)		//Возвращает индекс текстурного объекта
{
	GLuint index = 0;
	TgaHeader head;
	char* data;
	unsigned image_size;
	GLint iComponents;
	GLenum eFormat;
	ifstream file(filename.c_str(),ios::binary);

	if( !file )
		return 0;
	file.seekg(0);
	file.read((char*)(&head),sizeof(head));
	
    if(head.bits != 8 && head.bits != 24 && head.bits != 32)
        return 0;
	image_size = head.width * head.height * (head.bits / 8);
	data = new char[image_size];
	file.seekg(sizeof(head));
	file.read(data,head.width * head.height * (head.bits / 8) );
	
	glGenTextures(1,&index);
	glBindTexture(GL_TEXTURE_2D,index);
	switch( head.bits )
	{
	case 24 :
		eFormat = GL_BGR_EXT;
		iComponents = GL_RGB8;
		break;
	case 32 :
		eFormat = GL_BGRA_EXT;
		iComponents = GL_RGBA8;
		break;
	case 8 :
		eFormat = GL_LUMINANCE;
		iComponents = GL_LUMINANCE8;
		break;
	}
	
	gluBuild2DMipmaps(GL_TEXTURE_2D,iComponents,head.width,head.height,eFormat,GL_UNSIGNED_BYTE,data);

	delete [] data;

	return index;
}

float vertex[][3] = {	0.0f, 0.0f, 0.0f,
						0.0f, 0.0f, 1.0f,
						0.0f, 1.0f, 0.0f,
						0.0f, 1.0f, 1.0f,
						1.0f, 0.0f, 0.0f,
						1.0f, 0.0f, 1.0f,
						1.0f, 1.0f, 0.0f,
						1.0f, 1.0f, 1.0f };
float normals[][3] = {	-1.0f, 0.0f, 0.0f,
						1.0f, 0.0f, 0.0f,
						0.0f, -1.0f, 0.0f,
						0.0f, 1.0f, 0.0f,
						0.0f, 0.0f, -1.0f,
						0.0f, 0.0f, 1.0f };
float tex_coord[][2] = {0.0f, 0.0f,
						0.0f, 1.0f,
						1.0f, 1.0f,
						1.0f, 0.0f };
void RenderCube()
{
	glBegin(GL_QUADS);				//Рисуем квадратами
		glNormal3fv(normals[0]);
		glTexCoord2fv(tex_coord[0]);
		glVertex3fv(vertex[0]);		
		glTexCoord2fv(tex_coord[1]);
		glVertex3fv(vertex[1]);
		glTexCoord2fv(tex_coord[2]);
		glVertex3fv(vertex[3]);
		glTexCoord2fv(tex_coord[3]);
		glVertex3fv(vertex[2]);

		glNormal3fv(normals[1]);
		glTexCoord2fv(tex_coord[0]);
		glVertex3fv(vertex[4]);
		glTexCoord2fv(tex_coord[1]);
		glVertex3fv(vertex[6]);
		glTexCoord2fv(tex_coord[2]);
		glVertex3fv(vertex[7]);
		glTexCoord2fv(tex_coord[3]);
		glVertex3fv(vertex[5]);

		glNormal3fv(normals[2]);
		glTexCoord2fv(tex_coord[0]);
		glVertex3fv(vertex[0]);
		glTexCoord2fv(tex_coord[1]);
		glVertex3fv(vertex[1]);
		glTexCoord2fv(tex_coord[2]);
		glVertex3fv(vertex[5]);
		glTexCoord2fv(tex_coord[3]);
		glVertex3fv(vertex[4]);

		glNormal3fv(normals[3]);
		glTexCoord2fv(tex_coord[0]);
		glVertex3fv(vertex[2]);
		glTexCoord2fv(tex_coord[1]);
		glVertex3fv(vertex[3]);
		glTexCoord2fv(tex_coord[2]);
		glVertex3fv(vertex[7]);
		glTexCoord2fv(tex_coord[3]);
		glVertex3fv(vertex[6]);

		glNormal3fv(normals[4]);
		glTexCoord2fv(tex_coord[0]);
		glVertex3fv(vertex[0]);
		glTexCoord2fv(tex_coord[1]);
		glVertex3fv(vertex[2]);
		glTexCoord2fv(tex_coord[2]);
		glVertex3fv(vertex[6]);
		glTexCoord2fv(tex_coord[3]);
		glVertex3fv(vertex[4]);
		
		glNormal3fv(normals[5]);
		glTexCoord2fv(tex_coord[0]);
		glVertex3fv(vertex[1]);
		glTexCoord2fv(tex_coord[1]);
		glVertex3fv(vertex[5]);
		glTexCoord2fv(tex_coord[2]);
		glVertex3fv(vertex[7]);
		glTexCoord2fv(tex_coord[3]);
		glVertex3fv(vertex[3]);
	glEnd();				//Конец рисования примитивов
}

void RenderScene(float ang_x,float ang_y,GLuint tex_index)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );	
	glMatrixMode(GL_MODELVIEW);								//Устанавливает режим матрицы модели-вида
	glPushMatrix();
	glTranslatef(0.0f,0.0f,-3.0f);			//Перенос куба в направлении 3.0 единиц по оси -z
	glRotatef(ang_x,1.0f,0.0f,0.0f);		//Поворот отновительно оси x на угол ang_x
	glRotatef(ang_y,0.0f,1.0f,0.0f);		//повотор относительно у
	RenderCube();
	glPopMatrix();
}
void ChangeSize(int h,int w)
{
	GLfloat fAspect;
    if(h == 0)
        h = 1;

    glViewport(0, 0, w, h);					//Изменить размер области вывода OpenGL
        
    fAspect = (GLfloat)w / (GLfloat)h;		//	соотношение ширины к высоте

    glMatrixMode(GL_PROJECTION);			//	Выбираем матрицу проекции
    glLoadIdentity();						//	Загрузить единичную матрицу
	
    gluPerspective(60.0f, fAspect, 0.001f, 50.0f);	//Созданем персективную проекцию
        
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity(); 
}

LRESULT CALLBACK WndProc(HWND hWnd,	UINT message, WPARAM wParam, LPARAM lParam)
{
	static HGLRC hRC;
    static HDC hDC;
	static float angle_x,angle_y;
	static GLuint tex_index;
	switch( message )
	{
	case WM_CREATE :			//Создание окна
		{
			hDC = GetDC(hWnd);						//Получить контекст рисования окна
			PIXELFORMATDESCRIPTOR pfd = { 
		    sizeof(PIXELFORMATDESCRIPTOR),
			1,
			PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,	//Рисовать в окно, поддержка OpenGL, двойной буффер
			PFD_TYPE_RGBA,		//формат красный-зел-синий-прозрачность
			32,					//32 битный буффер цвета
			0,0,0,0,0,0,0,
			0,0,0,0,
			16,					//16 бит буффер глубины
			8,
			0,0,0,0,0,0 };

			int nRegularFormat = ChoosePixelFormat(hDC, &pfd); //Вохвращеает ближайший похожий формат , на описанный структурой
			SetPixelFormat(hDC,nRegularFormat,&pfd);		//Устанавливаем формат
			hRC = wglCreateContext(hDC);					//Создание контекста OpenGL
			wglMakeCurrent(hDC,hRC);						//Делает текущим созданыый контекст OpenGL
			glEnable(GL_TEXTURE_2D);						//Устанасливаем двухмерное текстурирование
			glEnable(GL_DEPTH_TEST);
			tex_index = ReadTGA(L"Stone.tga");
			if( !tex_index )
			{
				MessageBox(hWnd,L"Невозможно создать текстуру.",L"Error.",MB_OK);
			}
		}
		break;
	case WM_PAINT :
		RenderScene(angle_x,angle_y,tex_index);
		SwapBuffers(hDC);					//Поменять буфферы местами
		return 0;
	case WM_KEYDOWN :			//При нажиме клавиши
		{
			switch ( LOWORD(wParam) )
			{
			case VK_UP :
				angle_x -= STEP;
				break;
			case VK_DOWN :
				angle_x += STEP;
				break;
			case VK_LEFT:
				angle_y -= STEP;
				break;
			case VK_RIGHT:
				angle_y += STEP;
				break;
			}
		}
		return 0;
	case WM_DESTROY :			//При закрытии окна
		wglMakeCurrent(hDC,NULL);	//Делаем текущим контекстом OpenGl - 0	
		wglDeleteContext(hRC);		//Удаляем контекст OpenGL
		ReleaseDC(hWnd,hDC);		//Удаляем контекст окна
		PostQuitMessage(0);			//Посылаем сообщение о окончании 
		return 0;
	case WM_SIZE :
		ChangeSize(HIWORD(lParam),LOWORD(lParam));	//Вызввается при изменении размера окна
		break;
	}
	return ::DefWindowProc(hWnd, message, wParam, lParam);		//стандартная процедура обработки сообщений
}

int APIENTRY WinMain(	HINSTANCE 	hInstance,
						HINSTANCE 	hPrevInstance,
						LPSTR 		lpCmdLine,
						int			nCmdShow)
{
	WNDCLASS wc;
	HWND hWnd;
	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;	//Окно перерисовывается при изменениии разамера по вертикали и горизонтали
	
	wc.lpfnWndProc = (WNDPROC)WndProc;		//Оконная процедура
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;			//Идентификатор приложения
	wc.hIcon = NULL;					//стандартная иконка
	wc.hCursor = LoadCursor(NULL, IDC_ARROW); //Курсор стандартный
	wc.hbrBackground = NULL;					
	wc.lpszMenuName = NULL;
	wc.lpszClassName = L"OpenGL Window";		//Насзвание классса окна

	if( RegisterClass(&wc) == NULL )
	{
		MessageBox(0,L"Ошибка!",L"Класс не зарегистрирован!",MB_OK);
		return -1;
	}

	hWnd = CreateWindow(L"OpenGL Window",L"O",WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
		0,0,640,480,NULL,NULL,hInstance,NULL);
	if( !hWnd )
	{
		MessageBox(0,L"Ошибка!",L"Окно не создано!",MB_OK);
		return -2;
	}
	MSG msg;
	ShowWindow(hWnd,nCmdShow);
	UpdateWindow(hWnd);
	while( GetMessage(&msg,NULL,0,0) )
	{
		TranslateMessage(&msg);		//Преобразовать сообщение в понятную окну форму
		DispatchMessage(&msg);		//Отправить сообщение на обработку в оконную процедуру
	}

	return 0;
}