glBegin (GL_QUADS);
//==== Здесь располагаются команды, задающие четырехугольники
glEnd();
Четырехугольник задается координатами своих вершин. При задании координат какой-либо вершины (например командой glVertex3f (x, y, z);) можно сразу же определить ее цвет (например командой glColor3f (red, green, blue);). Если цвета вершин будут разными, а режим заполнения равен константе GL_FILL, то цвета внутренних точек четырехугольника примут промежуточное значение. Конвейер OpenGL производит аппроксимацию цвета так, что при перемещении от одной вершины к другой цвет изменяется плавно.
Режим растеризации или заполнения промежуточных точек графического примитива задается командой glPolygonMode. OpenGL различает фронтальные (front-facing polygons), обратные (back-facing polygons) и двухсторонние многоугольники. Режим заполнения их отличается, поэтому первый параметр функции glPolygonMode должен определить тип полигона (GL_FRONT, GL_BACK или GL_FRONT_AND_BACK).
Второй параметр собственно и определяет режим заполнения. Он может принимать значение GL_POINT, GL_LINE или GL_FILL. Первый выбор даст лишь обозначение примитива в виде его вершин, второй — даст некий скелет (вершины будут соединены линиями), а третий заполнит все промежуточные точки примитива. По умолчанию принят режим GL_FILL и мы получаем сплошной лоскут. Если в качестве первого параметра задать GL_FRONT_AND_BACK, то изменения второго параметра будут касаться обеих поверхностей одеяла. Другие сочетания дают на первый взгляд странные эффекты: так, если задать сочетание (GL_FRONT, GL_LINE), то лицевая сторона одеяла будет обозначена каркасом (frame view), а изнаночная по умолчанию будет сплошной (GL_FILL). Поверхность при этом выглядит как полупрозрачное одеяло.
Мы решили оставить неизменным значение GL_FRONT_AND_BACK для первого параметра и дать пользователю возможность изменять режим заполнения (второй параметр glPolygonMode) по его желанию. Впоследствии мы внесем эту настройку в диалог свойств COM-объекта, а результат выбора пользователя будем хранить в переменной m_FillMode. С учетом сказанного введите коды реализации функции DrawScene.
void COpenGL::DrawScene()
{
glNewList(1, GL_COMPILE);
glPolygonMode(GL_FRONT_AND_BACK, m_FillMode);
UINT nx = m_xSize-1, nz = m_zSize-1;
if (m_bQuad)
glBegin (GL_QUADS);
for (UINT z=0, i=0; z<nz; z++, i++)
{
if (!m_bQuad)
glBegin (GL_QUAD_STRIP);
for (UINT x=0; x<nx; x++, i++)
{
int
j = i + m_xSize,
k = j+1,
n = i+1;
float
xi = m_cPoints[i].x, 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,
ax = 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;
glNormal3f (vx,vy,vz);
if (m_bQuad)
{
glColor3f (0.2f, 0.8f, 1.f); glVertex3f (xi, yi, zi);
glColor3f (0.6f, 0.7f, 1.f); glVertex3f (xj, yj, zj);
glColor3f (0.7f, 0.9f, 1.f); glVertex3f (xk, yk, zk);
glColor3f (0.7f, 0.8f, 1.f); glVertex3f (xn, yn, zn);
}
else
{
glColor3f (0.9f, 0.9f, 1.0f); glVertex3f (xi, yi, zi);
glColor3f (0.5f, 0.8f, 1.0f); glVertex3f (xj, yj, zj);
if (x == nx - 1)
{
glColor3f (0.9f, 0.9f, 1.0f);
glVertex3f (xn, yn, zn);
glColor3f (0.5f, 0.8f, 1.0f);
glVertex3f (xk, yk, zk);
}
}
}
if (!m_bQuad)
glEnd();
}
if (m_bQuad)
glEnd();
glEndList();
}
Для осмысления алгоритма надо учитывать, что:
¨ Количество узлов сетки вдоль того или иного направления (X или Z) на единицу больше количества промежутков (ячеек).
¨ Реалистичность изображения во многом достигается благодаря аккуратному вычислению нормалей. При расчете освещения OpenGL учитывает направление нормали к поверхности.
¨ Нормаль является характеристикой вершины (узла сетки).
Эти действия абсолютно аналогичны тем, которые вы делали, когда готовили поверхность для изображения в окне приложения на основе MFC.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.