Подготовка окна
//====== Добываем дежурный контекст m_hdc =::GetDC(GetSafeHwnd()); //====== Просим выбрать ближайший совместимый формат int iD = ChoosePixelForraat(m_hdc, spfd); if (!iD) { MessageBox('ChoosePixelFormat::Error"); return -1; } //====== Пытаемся установить этот формат if (ISetPixelFormat (m_hdc, iD, Spfd)) { MessageBox("SetPixelFormat::Error"); return -1; } //====== Пытаемся создать контекст передачи OpenGL if (!(m_hRC = wglCreateContext (m_hdc))) { MessageBox("wglCreateContext::Error"); return -1; } //====== Пытаемся выбрать его в качестве текущего if (IwglMakeCurrent (m_hdc, m_hRC)) { MessageBox("wglMakeCurrent::Error"); return -1; //====== Теперь можно посылать команды OpenGL glEnable(GL_LIGHTING); // Будет освещение //====== Будет только один источник света glEnable(GL_LIGHTO); //====== Необходимо учитывать глубину (ось Z) glEnable(GL_DEPTH_TEST); //====== Необходимо учитывать цвет материала поверхности glEnable(GL_COLOR_MATERIAL); //====== Устанавливаем цвет фона. SetBkColor (); //====== Создаем изображение и запоминаем в списке DrawScene (); return 0; }
Контекст передачи (rendering context) создается функцией wglCreateContext с учетом выбранного формата пикселов. Так осуществляется связь OpenGL с Windows. Создание контекста требует, чтобы обычный контекст существовал и был явно указан в параметре wglCreateContext. HGLRC использует тот же формат пикселов, что и НОС. Мы должны объявить контекст передачи в качестве текущего (current) и лишь после этого можем делать вызовы команд OpenGL, которые производят включение некоторых тумблеров в машине состояний OpenGL. Вызов функции DrawScene, создающей и запоминающей изображение, завершает обработку сообщения.
Таким образом, сцена рассчитывается до того, как приходит сообщение о перерисовке WM_PAINT. Удалять контекст передачи надо после отсоединения его от потока. Это делается в момент, когда закрывается окно представления. Введите в тело заготовки OnDestroy следующие коды:
void COGView::OnDestroy(void) { //====== Останавливаем таймер анимации KillTimer(1); //====== Отсоединяем контекст от потока wglMakeCurrent(0, 0); //====== Удаляем контекст if (m_hRC) { wglDeleteContext(m_hRC); m_hRC = 0; } CView::OnDestroy(); }
Так же как и в консольном проекте OpenGL, обработчик сообщения WM_SIZE должен заниматься установкой прямоугольника просмотра (giviewport) и мы, так же как и раньше, зададим его равным всей клиентской области окна. – Напомним, что конвейер OpenGL использует эту установку для того, чтобы поместить изображение в центр окна и растянуть или сжать его пропорционально размерам окна. Кроме того, в обработке onSize с помощью матрицы проецирования (GL_PROJECTION) задается тип проекции трехмерного изображения на плоское окно. Мы выбираем центральный или перспективный тип проецирования и задаем при этом угол зрения равным m_AngleView. В конструкторе ему было присвоено значение в 45 градусов:
void COGView::OnSize(UINT nType, int ex, int cy) { //====== Вызов родительской версии CView::OnSize(nType, ex, cy); //====== Вычисление диспропорций окна double dAspect = cx<=cy? double(cy)/ex: double(ex)/cy; glMatrixMode (GL_PROJECTION); glLoadldentity(); //====== Установка режима перспективной проекции gluPerspective (m_AngleView, dAspect, 0.01, 10000.); //====== Установка прямоугольника просмотра glViewport(0, 0, сх, су); }