Управление цветом фона. Подготовка сцены OpenGL.
Мы решили оставить неизменным значение GL_FRONT_AND_BACK для первого параметра и дать пользователю возможность изменять режим заполнения (второй параметр glPolygonMode) по его желанию. Впоследствии внесем эту настройку в диалог свойств СОМ-объекта, а результат выбора пользователя будем хранить в переменной m_FillMode. С учетом сказанного введите коды реализации функции DrawScenel:
//====== Подготовка изображения void COpenGL::DrawScene() { //====== Создание списка рисующих команд glNewListd, GL_COMPILE); //====== Установка режима заполнения //====== внутренних точек полигонов glPolygonMode(GL_FRONT_AND_BACK, m_FillMode); //====== Размеры изображаемого объекта UINTnx = m_xSize-l, nz = m_zSize-l; //====== Выбор способа создания полигонов if (m_bQuad) glBegin (GL QUADS); //=== Цикл прохода по слоям изображения (ось Z) for (UINT z=0, i=0; z<nz; z++, i++) //=== Связанные полигоны начинаются //=== на каждой полосе вновь if (!m_bQuad) glBegin(GL_QUAD_STRIP); //=== Цикл прохода вдоль оси X for (UINT x=0; x<nx; х++, i++) { // i, j, k, n – 4 индекса вершин примитива при // обходе в направлении против часовой стрелки int j = i + m_xSize, // Индекс узла с большим Z k = j+1, // Индекс узла по диагонали n = i+1; // Индекс узла справа // Выбор координат 4-х вершин из контейнера float xi = m_cPoints [i]. х, yi = m_cPoints [i].y, zi = m_cPoints [i] .z, xj = m_cPoints [ j ].x, yj = m_cPoints [ j ].y, zj = m_cPoints [ j ].z, xk = m_cPoints [k].x, yk = m_cPoints [k] .y, zk = m_cPoints [k] .z, xn = m_cPoints [n].x, yn = m_cPoints [n].y, zn = m_cPoints [n] .z, //=== Координаты векторов боковых сторон ах = xi-xn, ay = yi-yn, by = yj-yi, bz = zj-zi, //=== Вычисление вектора нормали vx = ay*bz, vy = – bz*ax, vz = ax*by, //=== Модуль нормали v = float (sqrt (vx*vx + vy*vy + vz*vz)); //====== Нормировка вектора нормали vx /= v; vy /= v; vz /= v; //====== Задание вектора нормали glNormalSf (vx,vy f vz); // Ветвь создания несвязанных четырехугольников if (m_bQuad) { //====== Обход вершин осуществляется //=== в направлении против часовой стрелки glColorSf (0.2f, 0.8f, l.f); glVertex3f (xi, yi, zi); glColor3f <0.6f, 0.7f, l.f); glVertexSf (xj, уj, zj); glColorSf (0.7f, 0.9f, l.f); glVertexSf (xk, yk, zk); glColorSf (0.7f, 0.8f, l.f); glVertexSf (xn, yn, zn); } else // Ветвь создания цепочки четырехугольников { glColor3f (0.9f, 0..9f, l.Of); glVertexSf (xi, yi, zi); glColorSf (0.5f, 0.8f, l.0f); glVertexSf (xj, уj, zj); } } //====== Закрываем блок команд GL_QUAD_STRIP if (!m_bQuad) glEnd(); } //====== Закрываем блок команд GL_QUADS if (m_bQuad) glEnd(); //====== Закрываем список команд OpenGL glEndList (); }
Для осмысления алгоритма надо учитывать, что количество узлов сетки вдоль того или иного направления (X или Z) на единицу больше количества промежутков (ячеек). Кроме того, надо иметь в виду, что при расчете освещения OpenGL учитывает направление нормали (перпендикуляра) к поверхности. Реалистичность изображения во многом достигается благодаря аккуратному вычислению нормалей. Нормаль является характеристикой вершины (узла сетки).