OpenGL в Delphi

       

Обмен данными с DLL


Напомню, что головной модуль не использует библиотеку классов Delphi, однако проектировать без визуальных средств диалоговые окна - дело слишком тяжелое. Поэтому будем использовать для их реализации все мощные и удобные средства, предоставляемые Delphi специально для этих целей. Диалоговые окна размещены в динамических библиотеках, но должны иметь общие с головной программой данные. Решить проблему обмена данными с различными модулями можно различными путями, в частности, в этом примере используются указатели на данные. Например, диалоговое окно "Параметры системы" имеет флажок "Площадка", с помощью которого пользователь может задавать режим отображения этого объекта. После задания режима при воспроизведении кадра необходимо соответствующим образом отобразить текущие значения установки. Значение установки хранит в головном модуле булевская переменная-флажок figSquare; если она равна true, то при перерисовке кадра вызывается дисплейный список площадки:

If figSquare then glCallList (4); // рисуем площадку

Откройте модуль Unit1.pas в подкаталоге Ех0З и посмотрите forward-описание процедуры ParamForm, размещаемой в динамической библиотеке ParForm.dll, которая связана с отображением и функционированием диалогового окна "Параметры системы". Первые четыре аргумента этой процедуры - указатели на переменные булевского типа; каждая из них задает определенный флаг, управляющий режимом отображения осей, площадки, источника света или указателя курсора. При вызове этой процедуры из головного модуля в качестве фактических аргументов процедуры передаются ссылки на соответствующие переменные:

ParamForm (@flgOc, @flgSquare, SflgLight, @flgCursor, ...

Вы можете увидеть это в модуле ParForm.pas головного проекта ARM.dpr. Теперь при нажатии кнопки "Применить" окна "Параметры системы", как и при закрытии этого окна, переменной по заданному адресу устанавливается соответствующее значение:

If Forml.CheckBoxSquare.Checked
then wrkPFlagSquare^ := True
else wrkPFlagSquare^ := False;

При очередном перерисовывании по тику таймера главного окна системы это значение задаст, отображать ли площадку.
Таким образом, передавая в библиотеки ссылки, т. е. адреса данных, переменных и массивов головного модуля, я делаю эти данные доступными для использования, чтения и модификации за его пределами.
Использование ссылок является простым и удобным средством обмена данными между модулями программных систем. Я не претендую на роль первооткрывателя этого механизма, но уверен, что многим начинающим будет очень полезно освоить его, чтобы понять, почему многие команды OpenGL требуют в качестве аргумента именно адрес данных, а не сами данные.

Замечание
Напоминаю если команда OpenGL имеет несколько форматов, то использование формата, основанного на ссылочной адресации данных, является более предпочтительным в целях экономии памяти и повышения скорости работы

Для изменения оптических свойств материала и свойств источника света, таких как его положение и направление, необходим вызов соответствующих команд OpenGL. Простая передача данных о заданных значениях параметров решит проблему только, если при каждой перерисовке экрана будет происходить обращение к процедуре инициализации источника света Понятно, что это слишком накладно и не может считаться удовлетворительным
Одно из возможных решений состоит в том, что все процедуры, связанные с источником света, размещаются в отдельной библиотеке, к которой по мере необходимости обращаются головной модуль программы и сервисный модуль параметров системы. Менее элегантным решением является дублирование кода, когда одни и те же команды OpenGL вызываются из разных модулей системы.
Окно параметров системы снабжено также кнопкой "Отменить" на случай, если пользователь захотел отказаться от внесенных изменений, но не нажал еще кнопку "Применить". В этом случае, а также при появлении окна параметров необходимо иметь возможность получения данных о текущих значениях установок. Для этого библиотеку InitRC пришлось дополнить процедурой, возвращающей адреса переменных, являющихся, по сути, локальными данными модуля:

procedure GetData (var PMaterials : PMateria1;
var PLPosition : PArray4D;
var PFAmbient : PArray4D;
var PLDirection : PArraySD); export; stdcall;
begin
PMaterials := @Materials;
PLPosition := @LPosition;
PFAmbient := OFAmbient;
PLDirection := SLDirection;
end;

В подкаталоге Ех04 я поместил исходные файлы пользовательской библиотеки InitRC. Обратите внимание, что "головная часть" проекта динамической библиотеки соответствует этапу ее инициализации. В данном примере на этом этапе я задаю оптические свойства материала конструкции и инициализирую переменные:

begin // инициализация библиотеки
Materials := 1;
Material [1] := @AmbBronza;
Material [2] := @DifBronza;
Material [3] := SSpecBronza;
// цвет материала и диффузное отражение материала - значения из массива
glMaterialfv(GL_FRONT, GL_AMBIENT, Material [1]);
glMaterialfv(GL_FRONT, GL_DIFFUSE, Material [2]);
glMaterialfv(GL_FRONT, GL_SPECULAR, Material [3] ) ;
glMaterialf (GL_FRONT, GL_SHININESS, 51.2);
end.



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