MFC и OpenGL
- Название:MFC и OpenGL
- Автор:
- Жанр:
- Издательство:Информационный сервер для программистов - исходники со всего света.
- Год:неизвестен
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
MFC и OpenGL краткое содержание
MFC и OpenGL - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
MFC и OpenGL
"Подать сюда MFС!!! – кричил он, топая всеми 4-мя лапами."
Сижу тут как-то, программку сочиняю, тут смотрю, царь зверей пожаловал. Вопрос задать пришел. Спрашивает как же OpenGLв MFCто вставить? Сначала думал отмажусь, потом смотрю, настойчивый такой царь попался. Письма шлет, желает знать как же все-таки её туда вставить-то. Вот и решил я примерчик на MFCсостроить дабы цари меньше утруждали себя, а больше на солнышке бы нежились, чтоб у царей спокойно и хорошо все было, тогда и нам, простым зверушкам жить хорошо будет. И так поехали.
Для начала сделаем приложение MFCкак диалог. Я назвал его BitScroll. Как это делать? Смотрите шаги по MFC.
Теперь, при помощи визарда добавим функцию
BOOL CBitScrollDlg::PreCreateWindow(CREATESTRUCT& cs) {
cs.style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
return CDialog::PreCreateWindow(cs);
}
Помните, мы устанавливали слиль окна в функции CreateWindow? Так вот это действие по смыслу тоже самое. Напомню как это выглядело в Win32API:
hWnd = CreateWindow("Skeleton", "Skeleton", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 50, 50, 700, 400, NULL, NULL, hInst, NULL);
Теперь обратимся к функции OnInitDialog(). В ней сначала вызывается функция базового класса, т.е. CDialog, а потом устанавливаются иконки для диалога. Давайте вставим наш код между иконками и CDialog::OnInitDialog().
SetWindowPos(&wndTop, 0, 0, WIDTH, HEIGHT, SWP_NOMOVE);
pDC = GetDC();
CenterWindow();
Init(); SetTimer(1,SPEED, NULL);
Теперь посмотрим, что мы сделали. Сначала сделаем окно нужного нам размера (макросы WIDTHи HEIGHTобъявлены так #define WIDTH 640и #define HEIGHT 480в заголовочном файле).
Затем получим контекст для рисования. Установимся в центр вселенной и… вот, тут самое интересное, тут мы вызываем нашу собственную функцию, которая будет инициализировать OpenGL(напоминаю, что тоже самое делала функция Initialв программе на Win32API).
А потом включаем таймер, чтобы обеспечить анимацию. Обратимся теперь к Init(). Выглядит она итак:
void CBitScrollDlg::Init() {
CRect rect;
HGLRC hrc;
if (!bSetupPixelFormat()) return;
hrc = wglCreateContext(pDC->GetSafeHdc());
ASSERT(hrc != NULL);
wglMakeCurrent(pDC->GetSafeHdc(), hrc);
GetClientRect(&rect);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glDepthFunc(GL_LESS);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)rect.right / (GLfloat)rect.bottom, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
}
Что мы тут делаем? Прежде всего вызываем ф-ию SetupPixelFormat(), это опять наша функция и мы посмотрим ее чуть позже.
Далее, как и раньше, получаем контекст рендеринга (маленькая деталь, ранее pDC(а точнее эта переменная называлась hDC) была объявлена как static HDC hDC, сейчас контекст рисования является пременной типа CDC, а ф-ция wglCreateContextи другие функции OpenGLтребуют в качестве аргумента переменную типа HDC. Поэтому мы получаем этот hardware contextс помощью pDC->GetSafeHdc()).
Затем делаем этот контекст текущим и настраиваем область отображения, так как это делалось в Initial()( Win32API)
Функция bSetupPixelFormat()содержит следующее:
BOOL CBitScrollDlg::bSetupPixelFormat() {
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
1, // version number
PFD_DRAW_TO_WINDOW | // support window
PFD_SUPPORT_OPENGL | // support OpenGL
PFD_DOUBLEBUFFER, // double buffered
PFD_TYPE_RGBA, // RGBA type
24, // 24-bit color depth
0, 0, 0, 0, 0, 0, // color bits ignored
0, // no alpha buffer
0, // shift bit ignored
0, // no accumulation buffer
0, 0, 0, 0, // accum bits ignored
32, // 32-bit z-buffer
0, // no stencil buffer
0, // no auxiliary buffer
PFD_MAIN_PLANE, // main layer
0, // reserved
0, 0, 0 // layer masks ignored
};
int pixelformat;
if ((pixelformat = ChoosePixelFormat(pDC->GetSafeHdc(), &pfd)) == 0) {
MessageBox("ChoosePixelFormat failed");
return FALSE;
}
if (SetPixelFormat(pDC->GetSafeHdc(), pixelformat, &pfd) == FALSE) {
MessageBox("SetPixelFormat failed");
return FALSE;
}
return TRUE;
}
Как не трудно заметить, она почти полностью взята из Win32APIприложения за исключением того, что hDCзаменена на pDC->GetSafeHdc().
Теперь добавим в нашу программку обработчик от таймера (мы его недавно сделали в ф-ции Init())
void CBitScrollDlg::OnTimer(UINT nIDEvent) {
DrawScene();
CDialog::OnTimer(nIDEvent);
}
Все тривиально. По смыслу ясно, что каждый раз, когда срабатывает обработчик таймера (а делает он это часто) рисуется сцена. Таким образом получается анимация. Посмотрим на эту функцию:
void CBitScrollDlg::DrawScene() {
static GLfloat angle = 0;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, –2.0f);
glRotatef(angle, 1.0f, 0.5f, 0.3f);
glBegin(GL_QUADS);
glColor3f(1.0f, 0.0f, 1.0f);
glVertex3f(-0.5f, 0.5f, 0.0f);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.5f, 0.5f, 0.0f);
glColor3f(0.0f, 1.0f, 1.0f);
glVertex3f(0.5f, –0.5f, 0.0f);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(-0.5f, –0.5f, 0.0f);
glEnd();
glFinish();
SwapBuffers(wglGetCurrentDC());
angle += 0.5f;
}
По моему проще уже некуда. Я надеюсь, что все ясно.
Ну вот казалось бы и все. Единственное, что остается сделать – убраться за собой. Т.е. надо при выходе удалить контекст рендеринга и убить таймер.
Эти вещи надо сделать в 2-х обработчиках OnCloseи OnDestroy. Посмотрим на них:
void CBitScrollDlg::OnClose() {
// TODO: Add your message handler code here and/or call default
HGLRC hrc;
KillTimer(1);
hrc = ::wglGetCurrentContext();
::wglMakeCurrent(NULL, NULL);
if (hrc) ::wglDeleteContext(hrc);
CDialog::OnClose();
}
и
void CBitScrollDlg::OnDestroy() {
CDialog::OnDestroy();
// TODO: Add your message handler code here
HGLRC hrc;
KillTimer(1);
hrc = ::wglGetCurrentContext();
::wglMakeCurrent(NULL, NULL);
if (hrc) ::wglDeleteContext(hrc);
}
Она практически одинаковые. Работают так же как и case WM_CLOSEв Win32API. Т.е. убиваем таймер, получаем контекст рендеринга, если он есть – удаляем его.
Ну вот и все. Еще добавлю, что в проекте есть функция OnSizeдля обработки изменений размеров окна. В данном случае она не нужна, но если вставлять OpenGLв SDIили MDI, то она вам понадобится.
Интервал:
Закладка: