Каркас Windows-приложения. Особенности нового каркаса. Перемещение в пространстве (с текстурированными стенами)

Страницы работы

Содержание работы

Каркас Windows-приложения

В этом разделе мы разработаем новый каркас приложения, который использует функции API (из Windows SDK) для создания окна с выбранным нами пиксельным форматом и специальным контекстом отображения OpenGL (переменной типа HGLRC — Rendering Context). Новый подход позволит динамически менять режим демонстрации изображения (display mode): оконный — полноэкранный. Полноэкранный режим усиливает визуальный эффект трехмерного пространства на плоском экране, а SDK-каркас помогает управлять всеми событиями Windows.

Подготовку контекста передачи OpenGL надо рассматривать как некий обязательный ритуал, в котором порядок действий определен. В этой процедуре выделяют следующие шаги:

q  Игнорирование сообщения WM_ERASEBACKGROUND, которое создается перед каждой перерисовкой и обычно служит для инициации процесса закраски окна (стирание фона окна).

q  Установка pixel-формата с помощью структуры PIXELFORMATDESCRIPTOR.

q  Создание контекста устройства Windows окна (HDC) и специального контекста OpenGL (HGLRC).

q  Специфическая обработка сообщения WM_SIZE.

q  Постоянная перерисовка (см. ниже функцию Draw).

q  Освобождение обоих контекстов при закрытии окна.

Окнам, которые в своей клиентской области используют контекст передачи OpenGL, не следует позволять стирать свой фон, так как данная операция искажает и тормозит работу конвейера. Если бы мы работали в каркасе MFC, где родитеский класс CWnd реагирует на WM_ERASEBKGND и самостоятельно стирает фон, то нам бы следовало ввести в дочерний (оконный) класс реакцию на это событие и вставить в нее код вида: return TRUE;, что означает, что сообщение уже обработано. В нашем случае, так как мы используем каркас API, нет необходимости это делать, и мы просто игнорируем сообщение о необходимости стирания фона (WM_ERASEBKGND).

Если бы в окне были стандартные элементы управления (кнопки, списки и т.д.), то для вырезания их из области действия пиксельного формата OpenGL, при создании окна следовало бы установить биты стиля WS_CLIPCHILDREN и WS_CLIPSIBLINGS.

Создайте проект типа Win32 Application с именем Win и подключите к нему новый файл с именем NeHe.h. Этот файл декларирует тип структур AppInfo, который помогает двум главным модулям нового каркаса приложения обмениваться данными. Первый модуль (NeHe.cpp) является общей основой каркаса. Он содержит функцию WinMain, которая создает окно и выполняет цикл обработки сообщений, и оконную процедуру WndProc, которая обрабатывает, посылаемые ему сообщения. Другие функции каркаса управляют атрибутами окна.

Второй модуль (его вы будете периодически менять) содержит исследуемый код, то есть функции, оперирующие командами OpenGL. Сообщение WM_TOGGLEFULLSCREEN является пользовательским, его нет в системе, оно создано нами и служит для того, чтобы правильно обыграть последовательность событий, происходящих во время переключения режимов воспроизведения. Введите в файл заголовков NeHe.h следующий код.

#pragma once

#pragma comment(lib, "opengl32.lib")

#pragma comment(lib, "glu32.lib")

#pragma comment(lib, "glaux.lib")

#ifndef CDS_FULLSCREEN

#define CDS_FULLSCREEN 4

#endif           

const UINT WM_TOGGLEFULLSCREEN = WM_USER+1; // Our message for toggling full screen mode

struct AppInfo

{

const char* cls; // Application class name

HINSTANCE hInst; // Application instance

bool bQuit;   // Stop the full-screen toggling loop and quit?

bool bFull;   // Desired screen mode (not actual)

bool bVisible;   // Is window visible ?

bool keys [256]; // Array of key flags

char* title;     // Window title

int width;    // Current window width

int height;   // Current window height

int resWidth; // Screent resolution width

int resHeight;   // Screent resolution height

int bpp;    // Screen resolution (bits per pixel)

HWND hWnd;    // Window handle

HDC hDC;    // Windows device context

HGLRC hRC;    // OpenGL rendering context

DWORD ticks;  // Timer ticks

AppInfo();

};

extern AppInfo gInfo;

//===== These are functions you must provide:

bool Init ();  // Performs all your Initialization

void Update (DWORD ms);  // Perform motion updates

//===== ms - is the number of milliseconds passed since the last call

void Draw ();  // Perform all your scene drawing

void Deinitialize (); // Performs all your deinitialization

Добавьте к проекту новый файл NeHe.cpp и введите в него следующий код.

#include <windows.h>

#include <gl/gl.h>

#include <gl/glu.h>

#include "NeHe.h"

AppInfo::AppInfo()

{

bQuit = false;     bFull = true;

width = 700;     height= 500;

resWidth = 640;    resHeight = 480; bpp  = 24;

char* name = "OpenGL Tutorial";

title = name;    cls = name;

hInst = 0;

}

AppInfo gInfo;

void Resize (int w, int h)

{

if (!gInfo.bFull)

{

gInfo.width = w;

gInfo.height = h;

}

glViewport (0, 0, w, h);

glMatrixMode (GL_PROJECTION);

glLoadIdentity ();

gluPerspective (45, float(w) / h, 0.1f, 1000);   

glMatrixMode (GL_MODELVIEW);

glLoadIdentity ();

}

bool ToFullScreen ()

{

DEVMODE dm;

ZeroMemory (&dm, sizeof (dm));

dm.dmSize   = sizeof (dm);

Похожие материалы

Информация о работе