Рисование точек, линий и многоугольников

Задание графических примитивов

Все геометрические примитивы в OpenGL задаются в терминах вершин. Каждая вершина задаётся набором чисел, определяющих её координаты в пространстве.

OpenGL работает с однородными координатами (x, y, z, w). Если координата z не задана, то она считается равной нулю. Если координата w не задана, то она считается равной единице.

Под линией в OpenGL подразумевается отрезок, заданный своими начальной и конечной вершинами.

Под гранью (многоугольником) в OpenGL подразумевается замкнутый выпуклый многоугольник с несамопересекающейся границей.

Все геометрические объекты в OpenGL задаются посредством вершин, а сами вершины задаются процедурой

glVertex{2 3 4}{s i f d}[v](TYPE x, …),

где реальное количество параметров определяется первым суффиксом (2, 3 или 4), а суффикс v означает, что в качестве единственного аргумента выступает массив, содержащий необходимое количество координат. Например:

glVertex2s(1, 2);

glVertex3f(2.3, 1.5, 0.2);

GLdouble vect[] = {1.0, 2.0, 3.0, 4.0};

glVertex4dv(vect);

Для задания геометрических примитивов необходимо как-то выделить набор вершин, определяющих этот объект. Для этого служат процедуры glBegin() и glEnd(). Процедура glBegin(GLenum mode) обозначает начало списка вершин, описывающих геометрический примитив. Тип примитива задаётся параметром mode, который принимает одно из следующих значений:

GL_POINTS – набор отдельных точек;

GL_LINES – пары вершин, задающих отдельные точки;

GL_LINE_STRIP – незамкнутая ломаная;

GL_LINE_LOOP – замкнутая ломаная;

GL_POLYGON – простой выпуклый многоугольник;

GL_TRIANGLES – тройки вершин, интерпретируемые как вершины отдельных треугольников;

GL_TRIANGLE_STRIP – связанная полоса треугольников;

GL_TRIANGLE_FAN – веер треугольников;

GL_QUADS – четвёрки вершин, задающие выпуклые четырёхугольники;

GL_QUAD_STRIP – полоса четырёхугольников.

Процедура glEnd() отмечает конец списка вершин.

Между командами glBegin() и glEnd() могут находится команды задания различных атрибутов вершин:glVertex(), glColor(), glNormal(), glCallList(), glCallLists(), glTexCoord(), glEdgeFlag(),glMaterial(). Между командами glBegin() и glEnd() все остальные команды OpenGL недопустимы и приводят к возникновению ошибок.

Рассмотрим в качестве примера задание окружности:

glBegin(GL_LINE_LOOP);

for (int i = 0; I < N; i++)

{

float angle = 2 * M_PI * i / N;

glVertex2f(cos(angle), sin(angle));

}

glEnd();

Хотя многие команды могут находиться между glBegin() и glEnd(), вершины генерируются при вызовеglVertex(). В момент вызова glVertex() OpenGL присваивает создаваемой вершине текущий цвет, координаты текстуры, вектор нормали и т. д. Изначально вектор нормали полагается равным (0, 0, 1), цвет полагается равным (1, 1, 1, 1), координаты текстуры полагаются равными нулю.

Для задания размеров точки служит процедура glPointSize(GLfloat size), которая устанавливает размер точки в пикселях, по умолчанию он равен единице.

Для задания ширины линии в пикселях служит процедура gflineWidth(GLfloatwidth). Шаблон, которым будет рисоваться линия, можно задать при помощи процедуры glLineStipple(Glint factor, GLushortpattern). Шаблон задается переменной pattern и растягивается в factor раз. Использование шаблонов линии необходимо разрешить при помощи команды glEnable(GL_UNE_STIPPLE). Запретить использование шаблонов линий можно командой glDisable(GL_LINE_ST1PPLE).

Многоугольники рисуются как заполненные области пикселей внутри границы, хотя их можно рисовать либо только как граничную линию, либо просто как набор граничных вершин.

Многоугольник имеет две стороны (лицевую и нелицевую) и может быть отрисован по-разному, в зависимости от того, какая сторона обращена к наблюдателю. По умолчанию обе стороны рисуются одинаково. Для задания того, как именно следует рисовать переднюю и заднюю стороны многоугольника, служит процедура glPolygonMode(GLenumface, GLenum mode). Параметр face может принимать значения GL_FRONT_AND_BACK (обе стороны), GL_FRONT(лицевая сторона) или GL_BACK (нелицевая сторона). Параметр mode может принимать значения GL_POINT, GL_LINEили GL_FILL, обозначая, что многоугольник должен рисоваться как набор граничных точек, граничная ломаная линия или заполненная область, например:

glPolygonMode(GL_FRONT, GL_FILL);

glPolygonMode(GL_BACK, GLJJNE).

По умолчанию вершины многоугольника, которые появляются на экране в направлении против часовой стрелки, называются лицевыми. Это можно изменить при помощи процедуры glFrontFace(GLenum mode). По умолчанию параметр mode равняется GL_CCW, что соответствует направлению обхода против часовой стрелки. Если задать этот параметр равным GL_CW, то лицевыми будут считаться многоугольники с направлением обхода вершин по часовой стрелке.

При помощи процедуры glCullFace(GLenum mode) вывод лицевых или нелицевых граней многоугольников можно запретить. Параметр mode принимает одно из значений GL_FRONT (оставить только лицевые грани), GL_BACK(оставить нелицевые) или GL_FRONT_AND_BACK (оставить все грани). Для отсечения граней необходимо разрешить отсечение при помощи команды glEnable(GL_CULL_FACE).

Шаблон для заполнения грани можно задать при помощи процедуры gIPolygonStipple(const GLubyte * mask), где mask задает массив битов размером 32 на 32.

Для разрешения использования шаблонов при выводе многоугольников служит командаglEnable(GL_POLYGON_STIPPLE).

Свой вектор нормали для каждой вершины можно задать при помощи одной из следующих процедур:

glNormal3{b s i d f}(TYPE nx, TYPE ny, TYPE nz);

glNormal3{b s I d f}v(const TYPE * v).

В версиях с суффиксами b, s или i значения аргументов масштабируются в отрезок [-1, 1].

В качестве примера приведём процедуру, строящую прямоугольный параллелепипед с рёбрами, параллельными координатным осям, по диапазонам изменения х, у и z.

#include <windows.h>

#include <gl\gl.h>

drawBox(GLfloat x1, GLfloat x2, GLfloat y1, GLfloat y2, GLfloat z1, GLfloat

z2)

{

glBegin (GL_POLYGON);

glNormal3f (0.0, 0.0, 1.0);

glVertex3f (x1, y1, z2);

glVertex3f (x2, y1, z2);

glVertex3f (x2, y2, z2);

glVertex3f (x1, y2, z2);

glEnd ();

glBegin (GL_POLYGON);

glNormal3f (0.0, 0.0, -1.0);

glVertex3f (x2, y1, z1);

glVertex3f (x1, y1, z1);

glVertex3f (x1, y2, z1);

glVertex3f (x2, y2, z1);

glEnd ();

glBegin (GL_POLYGON);

glNormal3f (-1.0, 0.0, 0.0);

glVertex3f (x1, y1, z1);

glVertex3f (x1, y1, z2);

glVertex3f (x1, y2, z2);

glVertex3f (x1, y2, z1);

glEnd ();

glBegin (GL_POLYGON);

glNormal3f (1.0, 0.0, 0.0);

glVertex3f (x2, y1, z2);

glVertex3f (x2, y1, z1);

glVertex3f (x2, y2, z1);

glVertex3f (x2, y2, z2);

glEnd ();

glBegin (GL_POLYGON);

glNormal3f (0.0, 1.0, 0.0);

glVertex3f (x1, y2, z2);

glVertex3f (x2, y2, z2);

glVertex3f (x2, y2, z1);

glVertex3f (x1, y2, z1);

glEnd ();

glBegin (GL_POLYGON);

glNormal3f (0.0, -1.0, 0.0);

glVertex3f (x2, y1, z2);

glVertex3f (x1, y1, z2);

glVertex3f (x1, y1, z1);

glVertex3f (x2, y1, z1);

glEnd ();

}


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: