Skip to content

Instantly share code, notes, and snippets.

@arsinclair
Created January 9, 2015 00:00
Show Gist options
  • Save arsinclair/fdab3338e47ea43068e7 to your computer and use it in GitHub Desktop.
Save arsinclair/fdab3338e47ea43068e7 to your computer and use it in GitHub Desktop.
#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