
Формирование проекций
Теперь перейдем непосредственно к формированию проекций. Нам нужно построить две ортографические проекции: вид спереди и вид сверху. При задании полей вывода проекций необходимо оставить место в окне для визуальных объектов, с помощью которых мы будем управлять параметрами сцены. Для размещения этих объектов используем в качестве контейнера визуальный объект класса TPanel. Панель будет расположена внизу окна, и мы должны это учесть при определении размеров полей вывода и их положения в окне.
Создание вида спереди не требует введения дополнительных видовых преобразований. Координатная система для сцены определена, и можно просто вызвать процедуру формирования сцены. Дополнительная процедура DrawLight показывает положение источника. Остановимся на ее реализации подробнее. Источник представляет сфера, материал которой испускает собственный свет за счет эммисии, это делает ее похожей на реальный источник света. Как вы знаете из лекционного материала, такие свойства источника света как позиция и направление подвергаются трансформациям, накопленным в матрице видового преобразования на момент их установления. Поэтому установить точную позицию источника света в мировой системе координат иногда довольно затруднительно. Однако, позиция источника и другие свойства хранятся конвейером, и получить их значения можно с помощью процедуры glGetLightfv, указав источник и имя свойства.
procedure DrawLight(light: GLenum);
var pos, para: array[0..3] of glFloat;
dir: array[0..2] of glFloat;
begin
glPushMatrix;
glLoadIdentity;
glPushAttrib(GL_COLOR_MATERIAL);
para[0]:=1; para[1]:=1; para[2]:=0; para[3]:=0;
glMaterialfv(GL_FRONT, GL_EMISSION, @para);
glGetLightfv(GL_LIGHT0, GL_POSITION, @pos);
glTranslatef(pos[0],pos[1],pos[2]);
gluSphere(q, 0.25, 50, 32);
glPopAttrib;
glPopMatrix;
end;
Стандарт на OpenGL оговаривает, что позиция источника хранится в видовых координатах, но во многих реализациях (и в той, которой мы пользуемся) позиция хранится в мировых координатах. Рассмотренный подход можно использовать только при работе с позиционным источником. Для направленного источника получить позицию таким способом, нельзя.
Вторую проекцию мы будем использовать как схему, показывающую положение основных объектов влияющих на расчет освещения. Поэтому выключим освещение и зададим одинаковый цвет для всех объектов. Для формирования вида сверху повернем координатную систему сцены вокруг оси X. Можно использовать поворот на угол, немного меньший 90 градусов, для того чтобы плоский прямоугольник был лучше виден. Далее необходимо учесть смещение сцены относительно точки наблюдения, о котором говорилось выше. Для показа положения источника можно использовать процедуру аналогичную DrawLight, но учитывающую видовое преобразование (поворот вокруг оси X). Отличие будет состоять только в преобразовании переноса - glTranslatef(pos[0],-pos[2],pos[1]).
Управление параметрами освещения
Для завершения тестовой программы осталось только создать визуальные объекты для управления параметрами освещения. Мы использовали два типа переменных: логические, исходя из состояния которых включаем тот или иной режим, и численные, определяющие конкретные значения параметров. Соответственно для изменения их значений можно использовать объекты классов TCheckBox и TScrollBar. При задании числовых значений положение движка объекта дает лишь приблизительное представление о заданном значении. Поэтому необходимо отображать на экране точные значения установленных величин. Это можно сделать различными способами, например, с помощью объектов класса TLabel. Объекты ScrollBar изменяют величины в указанном диапазоне с шагом 1. Такой шаг может оказаться слишком большим при изменении величин с плавающей точкой, например, координат источника. Выход очевиден – масштабировать значения. Так если мы хотим изменять значения от 0.0 до 10.0 с шагом 0.1, то должны установить диапазон изменения величин визуального объекта 0-100 и при занесении значений в переменные учесть масштабирующий коэффициент – 10. В результате обработчик события onChange объекта ScrollBar, изменяющего Z координату позиции источника будет выглядеть следующим образом:
procedure TForm1.ScrollBarZChange(Sender: TObject);
begin
Zpos:= ScrollBarZ.Position /10;
LabelZ.caption:='Z = '+ floattostrF(Zpos,ffFixed,4,2);
draw;
end;
Обратите внимание на то, что допустимые значения для одних параметров освещения задаются непрерывным диапазоном, а для других требуются дискретные значения (возможно одновременно с непрерывным диапазоном). Не забудьте задать начальные значения всем определенным нами глобальным переменным.
Угол светового конуса Cval:= 180;
Сдвиги источника Zpos:= 0; Xpos:= 0;
Распределение потока внутри светового конуса ExpVal:= 0;
Коэффициент рассеивания зеркально отраженного света Sval:= 128;
Режим учета положения наблюдателя выключен LV:= GL_FALSE;
Сдвиг сцены относительно наблюдателя VPpos:= 0;
Зеркальная составляющая выключена Spec:= false;
Диффузная составляющая выключена Dif:= false;
Направление на центр Dir:= false;
Источник позиционный LDirect:= false;