Created
January 9, 2015 00:00
-
-
Save arsinclair/fdab3338e47ea43068e7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <stdio.h> | |
#include <math.h> | |
#include <gl\gl.h> | |
#include <gl\glu.h> | |
#include <gl\glaux.h> | |
HDC hDC=NULL; // дескриптор контекста устройства | |
HGLRC hRC=NULL; // дескриптор контекста рендеринга | |
HWND hWnd=NULL; // дескриптор окна | |
HINSTANCE hInstance; // Сохраняет экземпляр приложения, для проверки единственности | |
bool keys[256]; | |
bool active=TRUE; | |
bool fullscreen=TRUE; | |
float points[45][45][3]; // Массив точек волны | |
int wiggle_count = 0; // Счетчик скорости развевания флага | |
GLfloat xrot; // X вращение | |
GLfloat yrot; // Y вращение | |
GLfloat zrot; // Z вращение | |
GLfloat hold; | |
GLuint texture[1]; // Хранилище для нашей текстуры | |
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Декларация WndProc | |
AUX_RGBImageRec *LoadBMP(char *Filename) // функция загрузки нашей bmp | |
{ | |
FILE *File=NULL; | |
if (!Filename) // убедится что задана ссылка на файл | |
{ | |
return NULL; // Если нет, то NULL | |
} | |
File=fopen(Filename,"r"); // Проверка, существует ли он? | |
if (File) | |
{ | |
fclose(File); | |
return auxDIBImageLoad(Filename); // Загрузить bmp и вернуть указатель на него | |
} | |
return NULL; | |
} | |
int amerika = 0; | |
int LoadGLTextures() // Конвертация bmp в текстуру | |
{ | |
int Status=FALSE; | |
AUX_RGBImageRec *TextureImage[1]; | |
memset(TextureImage,0,sizeof(void *)*1); // Обнулить указатель | |
// Загрузить bmp, проверка на ошибки - > если не существует, то выход | |
if (amerika == 0) | |
{ | |
if (TextureImage[0] = LoadBMP("Data/2.bmp")) | |
{ | |
Status = TRUE; | |
glGenTextures(1, &texture[0]); | |
glBindTexture(GL_TEXTURE_2D, texture[0]); | |
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
} | |
} | |
else | |
{ | |
if (TextureImage[0] = LoadBMP("Data/1.bmp")) | |
{ | |
Status = TRUE; | |
glGenTextures(1, &texture[0]); | |
glBindTexture(GL_TEXTURE_2D, texture[0]); | |
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
} | |
} | |
// Освобождение памяти | |
if (TextureImage[0]) | |
{ | |
if (TextureImage[0]->data) | |
{ | |
free(TextureImage[0]->data); | |
} | |
free(TextureImage[0]); | |
} | |
return Status; | |
} | |
//------------------------------ | |
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Инициализация окна (размеры и позиция окна, размерность управляющей матрицы) | |
{ | |
if (height==0) // на ноль не делим (к телу функции) | |
{ | |
height=1; | |
} | |
glViewport(0,0,width,height); // Сброс вида | |
glMatrixMode(GL_PROJECTION); // Выбрать и сбросить матрицу вида | |
glLoadIdentity(); | |
// рассчитываем перспективу окна и перспективную дистанцию | |
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); | |
glMatrixMode(GL_MODELVIEW); | |
glLoadIdentity(); | |
} | |
int InitGL(GLvoid) // инициализация опенджееэль | |
{ | |
if (!LoadGLTextures()) // начать загрузку текстуры | |
{ | |
return FALSE; // если ошибка, возвращаем false | |
} | |
glEnable(GL_TEXTURE_2D); // включить наложение двухмерных текстур | |
glShadeModel(GL_SMOOTH); // сглаживание | |
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // фон | |
glClearDepth(1.0f); // глубина буфера | |
glEnable(GL_DEPTH_TEST); | |
glDepthFunc(GL_LEQUAL); | |
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // уровень отрисовки - Nicest | |
glPolygonMode( GL_BACK, GL_FILL ); | |
glPolygonMode( GL_FRONT, GL_LINE ); // из чего сделана сетка сзади - линии | |
for(int x=0; x<45; x++) | |
{ | |
for(int y=0; y<45; y++) | |
{ | |
points[x][y][0]=float((x/5.0f)-4.5f); | |
points[x][y][1]=float((y/5.0f)-4.5f); | |
points[x][y][2]=float(sin((((x/5.0f)*40.0f)/360.0f)*3.141592654*2.0f)); | |
} | |
} | |
return TRUE; | |
} | |
int DrawGLScene(GLvoid) // отрисовка сцены (втч и перерисовка) | |
{ | |
int x, y; | |
float float_x, float_y, float_xb, float_yb; | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // очистить экран и буфер | |
glLoadIdentity(); // сбросить вид | |
glTranslatef(0.0f,0.0f,-12.0f); //отдаление | |
glRotatef(xrot,1.0f,0.0f,0.0f); //вращение по иксу | |
glRotatef(yrot,0.0f,1.0f,0.0f); //вращение по игреку | |
glRotatef(zrot,0.0f,0.0f,1.0f); //вращение по зэду | |
glBindTexture(GL_TEXTURE_2D, texture[0]); //нанести текстуру на отрисовываемую ниже модель | |
glBegin(GL_QUADS); //отрисовка четырехугольника | |
for( x = 0; x < 44; x++ ) | |
{ | |
for( y = 0; y < 44; y++ ) | |
{ | |
float_x = float(x)/44.0f; | |
float_y = float(y)/44.0f; | |
float_xb = float(x+1)/44.0f; | |
float_yb = float(y+1)/44.0f; | |
glTexCoord2f( float_x, float_y); | |
glVertex3f( points[x][y][0], points[x][y][1], points[x][y][2] ); | |
glTexCoord2f( float_x, float_yb ); | |
glVertex3f( points[x][y+1][0], points[x][y+1][1], points[x][y+1][2] ); | |
glTexCoord2f( float_xb, float_yb ); | |
glVertex3f( points[x+1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2] ); | |
glTexCoord2f( float_xb, float_y ); | |
glVertex3f( points[x+1][y][0], points[x+1][y][1], points[x+1][y][2] ); | |
} | |
} | |
glEnd(); | |
// сглаживание волны по каждому второму кадру | |
if( wiggle_count == 2 ) | |
{ | |
for( y = 0; y < 45; y++ ) | |
{ | |
hold=points[0][y][2]; | |
for( x = 0; x < 44; x++) | |
{ | |
points[x][y][2] = points[x+1][y][2]; | |
} | |
points[44][y][2]=hold; | |
} | |
wiggle_count = 0; | |
} | |
wiggle_count++; | |
//инкременты вращения | |
xrot+=0.3f; // по х | |
yrot+=0.2f; // по у | |
zrot+=0.4f; // по з | |
return TRUE; | |
} | |
GLvoid KillGLWindow(GLvoid) // правильный выход из фулскрина (без этой функции искажается рабочий стол) | |
{ | |
if (fullscreen) | |
{ | |
ChangeDisplaySettings(NULL,0); // если мы в фулскрин - > свитч на десктоп | |
ShowCursor(TRUE); // показать скрытый указатель | |
} | |
if (hRC) // активен ли контекст рендеринга? | |
{ | |
if (!wglMakeCurrent(NULL,NULL)) //попытка освободить его | |
{ | |
MessageBox(NULL,"ошибка освобождения контекстов","Ошибка",MB_OK | MB_ICONINFORMATION); | |
} | |
if (!wglDeleteContext(hRC)) // попытка удалить его | |
{ | |
MessageBox(NULL,"ошибка при попытке удаления контекста","Ошибка",MB_OK | MB_ICONINFORMATION); | |
} | |
hRC=NULL; // обнуляем дескриптор рендеринга | |
} | |
//------------------------------ то же самое для контекста устройства: DC = Device Context | |
if (hDC && !ReleaseDC(hWnd,hDC)) | |
{ | |
MessageBox(NULL,"Ошибка освобождения контекста устройства","Ошибка",MB_OK | MB_ICONINFORMATION); | |
hDC=NULL; | |
} | |
if (hWnd && !DestroyWindow(hWnd)) | |
{ | |
MessageBox(NULL,"Невозможно уничтожить контекст устройства","Ошибка",MB_OK | MB_ICONINFORMATION); | |
hWnd=NULL; | |
} | |
if (!UnregisterClass("OpenGL",hInstance)) // тут освобождение всего класса GL | |
{ | |
MessageBox(NULL,"Невозможно разрегистрировать класс","Ошибка",MB_OK | MB_ICONINFORMATION); | |
hInstance=NULL; | |
} | |
} | |
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) | |
{ | |
// создание окна, задание его характеристик, позиции | |
GLuint PixelFormat; | |
WNDCLASS wc; | |
DWORD dwExStyle; | |
DWORD dwStyle; | |
RECT WindowRect; | |
WindowRect.left=(long)0; | |
WindowRect.right=(long)width; | |
WindowRect.top=(long)0; | |
WindowRect.bottom=(long)height; | |
fullscreen=fullscreenflag; // установить флаг fullscreen | |
hInstance = GetModuleHandle(NULL); | |
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; | |
wc.lpfnWndProc = (WNDPROC) WndProc; | |
wc.cbClsExtra = 0; | |
wc.cbWndExtra = 0; | |
wc.hInstance = hInstance; | |
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); | |
wc.hCursor = LoadCursor(NULL, IDC_ARROW); | |
wc.hbrBackground = NULL; | |
wc.lpszMenuName = NULL; | |
wc.lpszClassName = "OpenGL"; | |
if (!RegisterClass(&wc)) // создаем класс окна | |
{ | |
MessageBox(NULL,"Невозможно создать класс для окна","Ошибка",MB_OK|MB_ICONEXCLAMATION); | |
return FALSE; | |
} | |
if (fullscreen) | |
{ | |
DEVMODE dmScreenSettings; // настройки полноэкранного режима для устройства | |
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); | |
dmScreenSettings.dmSize=sizeof(dmScreenSettings); | |
dmScreenSettings.dmPelsWidth = width; | |
dmScreenSettings.dmPelsHeight = height; | |
dmScreenSettings.dmBitsPerPel = bits; | |
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT; | |
// попытка вклюичть полноэкранный. здесь избавляемся от меню пуск | |
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL) | |
{ | |
// если ошибка, то исп. либо оконный режим, либо выход | |
if (MessageBox(NULL,"Полноэкранный режим не поддерживается\nвашей видеокартой. Запустить в оконном?","FLAG_Opengl",MB_YESNO|MB_ICONEXCLAMATION)==IDYES) | |
{ | |
fullscreen=FALSE; | |
} | |
else | |
{ | |
MessageBox(NULL,"Закрыть программу?","Ошибка",MB_OK|MB_ICONSTOP); | |
return FALSE; | |
} | |
} | |
} | |
if (fullscreen) | |
{ | |
dwExStyle=WS_EX_APPWINDOW; // расширить границы окна | |
dwStyle=WS_POPUP; | |
ShowCursor(FALSE); // скрыть курсор | |
} | |
else | |
{ | |
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // как будет происходить перекрытие открытых окон | |
dwStyle=WS_OVERLAPPEDWINDOW; | |
} | |
AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // установить размер полноэкрана | |
// ну и создать окно | |
if (!(hWnd=CreateWindowEx( dwExStyle, // стиль окна | |
"OpenGL", // имя класса | |
title, // название окноа | |
dwStyle | // стиль окна | |
WS_CLIPSIBLINGS | | |
WS_CLIPCHILDREN, | |
0, 0, // позиция окна | |
WindowRect.right-WindowRect.left, // определить ширину окна | |
WindowRect.bottom-WindowRect.top, // -=- высоту | |
NULL, // окно является наследствием? | |
NULL, // исп. меню? | |
hInstance, | |
NULL))) | |
{ | |
KillGLWindow(); | |
MessageBox(NULL,"Ошипка создания окна.","Ошибка",MB_OK|MB_ICONEXCLAMATION); | |
return FALSE; | |
} | |
static PIXELFORMATDESCRIPTOR pfd= | |
{ | |
sizeof(PIXELFORMATDESCRIPTOR), | |
1, | |
PFD_DRAW_TO_WINDOW | | |
PFD_SUPPORT_OPENGL | | |
PFD_DOUBLEBUFFER, | |
PFD_TYPE_RGBA, | |
bits, | |
0, 0, 0, 0, 0, 0, | |
0, | |
0, | |
0, | |
0, 0, 0, 0, | |
16, | |
0, | |
0, | |
PFD_MAIN_PLANE, | |
0, | |
0, 0, 0 | |
}; | |
if (!(hDC=GetDC(hWnd))) // есть ли контекст устройства уже забинден? | |
{ | |
KillGLWindow(); | |
MessageBox(NULL,"Не получается присоеденится к контексту устройства. /nМожет быть он уже используется другим приложением...?.","Ошибка",MB_OK|MB_ICONEXCLAMATION); | |
return FALSE; | |
} | |
if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) | |
{ | |
KillGLWindow(); | |
MessageBox(NULL,"Невозможно найти подходящий к картинке метод обработки пикселов.","Ошибка",MB_OK|MB_ICONEXCLAMATION); | |
return FALSE; | |
} | |
// то же самое по сути, только тут уже попытка забиндиться на уже выбранный | |
if(!SetPixelFormat(hDC,PixelFormat,&pfd)) | |
{ | |
KillGLWindow(); | |
MessageBox(NULL,"Невозможно использовать текущий метод обработки пикселов.","Ошибка",MB_OK|MB_ICONEXCLAMATION); | |
return FALSE; | |
} | |
// то же самое для выбор контекста рендеринга | |
if (!(hRC=wglCreateContext(hDC))) | |
{ | |
KillGLWindow(); | |
MessageBox(NULL,"Невозножно создать подходящий контекст рендеринга.","Ошибка",MB_OK|MB_ICONEXCLAMATION); | |
return FALSE; | |
} | |
// то же самое, попытка активировать КР | |
if(!wglMakeCurrent(hDC,hRC)) | |
{ | |
KillGLWindow(); | |
MessageBox(NULL,"Невозножно активировать контекст рендеринга","Ошибка",MB_OK|MB_ICONEXCLAMATION); | |
return FALSE; | |
} | |
ShowWindow(hWnd,SW_SHOW); // Показать окно | |
SetForegroundWindow(hWnd); // Поставить приоритет процесса выше | |
SetFocus(hWnd); // клавиатура фокус навести на окно | |
ReSizeGLScene(width, height); // пересчитать проекцию сцены под конкретные размеры окна | |
if (!InitGL()) // Инициализировать окно попытка | |
{ | |
KillGLWindow(); | |
MessageBox(NULL,"Инициализация провалена. Что будем делать?","Ошикба",MB_OK|MB_ICONEXCLAMATION); | |
return FALSE; | |
} | |
return TRUE; | |
} | |
// установка дескриптора для новосозданного окна, задание параметров для передачи в функцию | |
LRESULT CALLBACK WndProc( HWND hWnd, | |
UINT uMsg, | |
WPARAM wParam, | |
LPARAM lParam) | |
//------------------ ненужная но прикольная функция скринсейвера виндовс, а так же отключение режима энергосбережения монитора | |
{ | |
switch (uMsg) | |
{ | |
case WM_ACTIVATE: | |
{ | |
if (!HIWORD(wParam)) | |
{ | |
active=TRUE; | |
} | |
else | |
{ | |
active=FALSE; | |
} | |
return 0; | |
} | |
case WM_SYSCOMMAND: | |
{ | |
switch (wParam) | |
{ | |
case SC_SCREENSAVE: | |
case SC_MONITORPOWER: | |
return 0; | |
} | |
break; | |
} | |
case WM_CLOSE: | |
{ | |
PostQuitMessage(0); | |
return 0; | |
} | |
case WM_KEYDOWN: | |
{ | |
keys[wParam] = TRUE; | |
return 0; | |
} | |
case WM_KEYUP: | |
{ | |
keys[wParam] = FALSE; | |
return 0; | |
} | |
case WM_SIZE: //ресайз сцены | |
{ | |
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); | |
return 0; | |
} | |
} | |
//возвращение ошибочных параметров | |
return DefWindowProc(hWnd,uMsg,wParam,lParam); | |
} | |
int WINAPI WinMain( HINSTANCE hInstance, | |
HINSTANCE hPrevInstance, | |
LPSTR lpCmdLine, | |
int nCmdShow) | |
{ | |
MSG msg; | |
BOOL done=FALSE; | |
// выбор режима оконного или фулскрин | |
if (MessageBox(NULL,"Запустимся в полноэкранном?", "Полноэкранный режим?",MB_YESNO|MB_ICONQUESTION)==IDNO) | |
{ | |
fullscreen=FALSE; // оконный тогда | |
} | |
if (MessageBox(NULL, "Америка или Беларусь? Америка: нет, Беларусь: да.", "Страна", MB_YESNO | MB_ICONQUESTION) == IDNO) | |
{ | |
amerika = 1; | |
} | |
// создать окно | |
if (!CreateGLWindow("Развевающийся флаг",640,480,16,fullscreen)) | |
{ | |
return 0; | |
} | |
while(!done) | |
{ | |
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) | |
{ | |
if (msg.message==WM_QUIT) | |
{ | |
done=TRUE; | |
} | |
else | |
{ | |
TranslateMessage(&msg); | |
DispatchMessage(&msg); | |
} | |
} | |
else | |
{ | |
// Отрисовываем сцену. Наблюдаем за нажатием ESC из DrawGLScene() | |
if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) | |
{ | |
done=TRUE; | |
} | |
else | |
{ | |
SwapBuffers(hDC); | |
} | |
if (keys[VK_F1]) // F1 также ждем | |
{ | |
keys[VK_F1]=FALSE; | |
KillGLWindow(); | |
fullscreen=!fullscreen; | |
// пересоздать окно | |
if (!CreateGLWindow("Развевающийся флаг",640,480,16,fullscreen)) | |
{ | |
return 0; | |
} | |
} | |
} | |
} | |
//конечное выключение | |
KillGLWindow(); | |
return (msg.wParam); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment