OpenGL в Delphi

       

Классический пример на построение поверхности Безье




Массив опорных точек содержит координаты шестнадцати вершин. Работа программы начинается с установки параметров вычислителя:

glMap2f (GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, @ctrlpoints);
glEnable (GL_MAP2_VERTEX_3);
glMapGrid2f (20, 0. 0, 1. 0, 20, 0. 0, 1. 0);

У команды glMap2f аргументов больше, чем у glMaplf, но теперь нам легко понять их смысл. Первый аргумент - константа, определяющая тип рассчитываемых величин, в данном случае это координаты точек поверхности. Последний аргумент - указатель на массив контрольных точек поверхности.
Второй и третий параметры задают преобразования по координате u поверхности. Четвертый аргумент, как и в предыдущем случае, задает, сколько вещественных чисел содержится в порции данных - здесь мы сообщаем, что каждая точка задана тремя координатами. Пятый аргумент - количество точек в строке структуры, хранящей данные.
Следующие четыре аргумента имеют смысл, аналогичный предыдущим четырем, но задают параметры для второй координаты поверхности, координаты v. Значение восьмого аргумента стало равно двенадцати путем перемножения количества чисел, задающих координаты одной вершины (3), на количество точек в строке массива (4).
После задания параметров вычислителя он включается вызовом команды glEnable, после чего вызывается одна из пары команд, позволяющих построить поверхность - команда giMapGnd2f, рассчитывающая двумерную сетку. Первый и четвертый аргументы этой команды определяют количество разбиений по каждой из двух координат поверхности, остальные параметры имеют отношение к отображению интервалов.
Собственно изображение поверхности, двумерной сетки, осуществляется вызовом второй команды из тандема:

glEvalMesh2 (GL_FILL, 0, 20, О, 20);

Первый аргумент команды задает режим воспроизведения, следующие две пары чисел задают количество подинтервалов разбиения по каждой координате поверхности. В примере мы берем по 20 разбиений, столько же, сколько задано в команде giMapGnd2f, чтобы не выходить за пределы интервалов, но это не обязательно, можно брать и больше.
Если смысл параметров, связанных с отображением интервалов, вам кажется не совсем ясным, рекомендую вернуться к примеру по кривой Безье и еще раз его разобрать.
Замечу, что режим воспроизведения можно варьировать также с помощью Команды glPolygonMode.
Обратите внимание, что в рассматриваемом примере используется режим автоматического расчета нормалей к поверхности:

glEnable (GL_AUTO_NORMAL);

Без этого режима поверхность выглядит невыразительно, но его использование допускается только в случае поверхностей, рассчитываемых вычислителем.
В проекте введены два режима: один управляет тем, как строится поверхность - сплошной или линиями. Второй режим задает, надо ли выводить опорные точки. Нажимая на клавиши ввода и пробела, можно менять текущие значения этих режимов.
При нажатой кнопке мыши при движении курсора поверхность вращается по двум осям, что позволяет хорошо рассмотреть ее с разных позиций Для осуществления этого режима введен флаг, булевская переменная Down, которая принимает истинное значение при удерживаемой кнопке мыши, и две вспомогательные переменные, связанные с экранными координатами указателя.
В момент нажатия кнопки запоминаются координаты курсора; при движении курсора сцена поворачивается по двум осям на угол, величина которого зависит от разницы текущей и предыдущей координат курсора:

procedure TfrmGL.FormMouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
If Down then begin // кнопка мыши нажата
glRotatef (X - wrkX, 0.0, 1.0, 0.0);// поворот по горизонтали экрана
glRotatef (Y - wrkY, 1.0, 0.0, 0.0);// поворот по вертикали экрана
InvalidateRect(Handle, nil, False); // перерисовать экран
wrkX := X; // запоминаем координаты курсора
wrkY := Y;
end;
end;

Но при изменении размеров окна система координат возвращается в первоначальное положение.
Точно так же, как и в случае с кривой Безье, для воспроизведения поверхности можно воспользоваться командой glEvalCoord2f. Отрезки строятся по вершинам, предоставленным вычислителем:

9lBegm (GL_LINE_STRIP) ;
For i := 0 to 30 do For ] := 0 to 30 do
glEvalCoord2f (i / 30, j / 30);
glEnd;

Мы уже изучили множество параметров команды glEnable, задающей режимы воспроизведения и, в частности, позволяющей использовать вычислители. Я должен обязательно привести пример на команду, позволяющую определить, включен сейчас какой-либо режим или вычислитель - команду glIsEnabled. Ее аргумент - константа, символ определяемого режима, а результат работы, согласно документации, имеет тип GLboolean. Мы знаем о небольшой проблеме Delphi, связанной с этим типом, так что для вас не должно стать откровением то, что обрабатывать возвращаемое значение мы будем как величину булевского типа.
Приведу здесь простой пример, в котором до и после включения режима окрашивания поверхностей выводится сообщение о том, доступен ли этот режим:

If glIsEnabled (GL_COLOR_MATERIAL) = TRUE
then ShowMessage ('COLOR_MATERIAL is enabled')
else ShowMessage ('COLOR_MATERIAL is disabled');

Соответствующий проект располагается в подкаталоге Ex47.
В этом разделе мы рассмотрели, как в OpenGL строятся кривые и поверхности Безье, позже рассмотрим еще несколько примеров на эту тему.



Содержание раздела