Для создания
проекта используется Lazarus 1.0.8 и Fedora 19
Linux.
Компонент
TOpenGLControl, по — умолчанию, не
установлен в среде Lazarus, поэтому нам с
вами предстоит установить данный
компонент. Выберите пункт меню Package >
Install / Uninstall Packages, откроется окно
установки новых пакетов в среду Lazarus
(Смотрите рисунок 1).
Рисунок
1. Установка нового пакета
В окне
установки новых пакетов, в списке
неустановленных пакетов, необходимо
найти пакет с именем lazopenglcontext 0.0.1,
выбрать его и нажать кнопку Install
selection. После этого необходимо нажать
кнопку Save and Rebuild IDE, для пересборки
Lazarus уже с компонентом TOpenGLControl. В
окне подтверждения установки нового
пакета, нажмите кнопку Continue.
Теперь,
если посмотреть на ленту компонентов,
то вы увидите новую секцию OpenGL c
TOpenGLControl компонентом на ней.
Теперь
создадим новый проект. Для это выберите
пункт меню File > New, в окне создания
нового проекта выберите раздел Project
>Application и нажмите кнопку Ok. Сохраните
проект в каталог /home/[имя
пользователя]/Projects/lazarus/ogl_p2 и присвойте
имя проекту ogl_p2.lpi, а модулю формы
ogl_p2_unit1.pas, для этого выберите пункт
меню File > Save As.
В инспекторе
объектов нам необходимо присвоить имя
форме, в поле Name напишем имя формы
ogl_form1. Дальше нам необходимо вытащить
на форму компонент TOpenGLControl.
Имя компонента будет OpenGLControl1. Теперь
нам необходимо для нашей формы написать
код обработчика события OnCreate, для этого
в (Object Inspector) инспекторе объекта выберите
нашу форму с именем ogl_form1 и перейдите с
вкладки (Properties) Свойства на вкладку
(Events) Событий, найдите в списке событий,
событие OnCreate и выберите кнопку с тремя
точками напротив. Ваш обработчик должен
выглядеть как показано ниже:
procedure
Togl_form1.FormCreate(Sender: TObject);
begin
Application.OnIdle := @IdleFunc;
end;
Давайте
рассмотрим код обработчика события
OnCreate формы с именем ogl_form1.Первой строчкой
мы определим процедуру, которая вызывается
когда в приложение ничего не происходит,
данная функция называется IdleFunc:
Application.OnIdle
:= @IdleFunc;
В модуле
формы ogl_p2_unit1.pas в секцию uses нам необходимо
добавить OpenGL модуль с именем gl.
В глобальной
секции переменных var в модуле формы
ogl_p2_unit1.pas, после строчки:
var
ogl_form1:
Togl_form1;
нам необходимо определить три переменные,
две из которых нужно принять как должное,
для того чтобы при изменение размеров
окна OpenGL — анимация не изменяла скорость:
timer:
single;
LastMsecs: integer;
и третья
переменная, задает угол на который
поворачивается объект каждый раз:
rrx:
single;
Создадим
обработчик формы для события изменения
размеров формы. Для этого нам необходимо
в (Object Inspector) инспекторе объектов перейти
на вкладку событий формы и нажать на
кнопку с тремя точками напротив события
OnResize и в обработчике события написать
следующий код:
procedure
Togl_form1.FormResize(Sender: TObject);
begin
OpenGLControl1.SetBounds(0, 0, Width, Height);
end;
Строчкой
OpenGLControl1.SetBounds(0, 0, Width, Height); мы
устанавливаем границы компонента
OpenGLControl1 при
изменение размеров формы, т.е. компонент
OpenGLControl1 будет
растянут на всю форму.
Теперь взглянем на код процедуры, которая
выполняется каждый раз когда в программе
ничего не происходит:
procedure
Togl_form1.IdleFunc(Sender: TObject; var Done: Boolean);
begin
OpenGLControl1.Invalidate;
end;
Если
приложение ничего не делает, то область
вывода OpenGL графики компонента
OpenGLControl1 объявляется
не действительной, тем самым заставляет
перерисовать область вывода графики
компонента OpenGLControl1,
т.е. вызывается
процедура — обработчик события OnPaint
компонента
OpenGLControl1.
В
классе формы нам понадобится объявить
процедуру IdleFunc.
Рассмотрим
обработчик события OnPaint
компонента
OpenGLControl1. Для
начала нужно создать данную процедуру
— обработчик. В инспекторе объектов
выберите компонент OpenGLControl1
и перейдите на
вкладку событий. Найдите событие OnPaint
и нажмите на кнопку с тремя кнопками
напротив.
procedure
Togl_form1.OpenGLControl1Paint(Sender: TObject);
var
CurTime:
TDateTime;
MSecs:
integer;
begin
CurTime:=Now;
MSecs:=round(CurTime*86400*1000) mod 1000;
if MSecs<0
then MSecs:=1000+MSecs;
timer:=msecs-LastMsecs;
if timer<0
then timer:=1000+timer;
LastMsecs:=MSecs;
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
glFrustum
(-1, 1, -1, 1, 4.5, 10);
glTranslatef(0.0, 0.0, -5.0);
rrx:=rrx-0.6*(timer/10);
glRotatef(rrx,0.0,1.0,0.0);
glBegin(GL_QUADS);
glColor3f(
1.0, 1.0, 0.0);
glVertex3f(-0.5, 0.5, 0.0);
glVertex3f(
0.5, 0.5, 0.0);
glVertex3f(
0.5,-0.5, 0.0);
glVertex3f(-0.5,-0.5, 0.0);
glEnd();
OpenGLControl1.SwapBuffers;
end;
1) Объявляем локальные переменные,
которые будут использоваться в процедуре,
секция var:
var
CurTime:
TDateTime;
MSecs:
integer;
2) Расчет времени используемое для
вращение OpenGL объекта:
CurTime:=Now;
MSecs:=round(CurTime*86400*1000) mod 1000;
if MSecs<0
then MSecs:=1000+MSecs;
timer:=msecs-LastMsecs;
if timer<0
then timer:=1000+timer;
LastMsecs:=MSecs;
3) Инициализация сцены и настройка обзора
сцены:
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
glFrustum
(-1, 1, -1, 1, 4.5, 10);
glTranslatef(0.0, 0.0, -5.0);
4)
Вращаем объект
на значение rrx
с учетом времени.
rrx:=rrx-0.6*(timer/10);
glRotatef(rrx,0.0,1.0,0.0);
5) Формируем квадрат желтого цвета:
glBegin(GL_QUADS);
glColor3f(
1.0, 1.0, 0.0);
glVertex3f(-0.5, 0.5, 0.0);
glVertex3f(
0.5, 0.5, 0.0);
glVertex3f(
0.5,-0.5, 0.0);
glVertex3f(-0.5,-0.5, 0.0);
glEnd();
6) Отображаем содержимое буфера на экран:
OpenGLControl1.SwapBuffers;
И последнее, что нам осталось сделать,
это написать обработчик события OnResize
для компонента OpenGLControl1, в котором
мы будем подгонять размер OpenGL сцены под
размер компонента OpenGLControl1. Опять
выбираем, в инспекторе объектов, компонент
OpenGLControl1, переходим на вкладку события
и находим событие OnResize. Нажимаем кнопку
с тремя точками напротив этого события.
Код обработчика показан ниже:
procedure
Togl_form1.OpenGLControl1Resize(Sender: TObject);
begin
glViewport
(0, 0, OpenGLControl1.Width, OpenGLControl1.Height);
end;
Теперь взглянем на снимок нашего
приложения в действие (Смотрите рисунок
2).
Рисунок 2. Результат работы программы
Код программы:
unit ogl_p2_unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, OpenGLContext, Forms, Controls,
Graphics, Dialogs, gl; type { Togl_form1 } Togl_form1 = class(TForm) OpenGLControl1: TOpenGLControl; procedure FormCreate(Sender: TObject); procedure FormResize(Sender: TObject); procedure OpenGLControl1Paint(Sender: TObject); procedure OpenGLControl1Resize(Sender: TObject); procedure IdleFunc(Sender: TObject; var Done: Boolean); private { private declarations } public { public declarations } end; var ogl_form1: Togl_form1; timer: single; LastMsecs: integer; rrx: single; implementation {$R *.lfm} { Togl_form1 } procedure Togl_form1.OpenGLControl1Paint(Sender: TObject); var CurTime: TDateTime; MSecs: integer; begin CurTime:=Now; MSecs:=round(CurTime*86400*1000) mod 1000; if MSecs<0 then MSecs:=1000+MSecs; timer:=msecs-LastMsecs; if timer<0 then timer:=1000+timer; LastMsecs:=MSecs; glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); glLoadIdentity (); glFrustum (-1, 1, -1, 1, 4.5, 10); glTranslatef(0.0, 0.0, -5.0); rrx:=rrx-0.6*(timer/10); glRotatef(rrx,0.0,1.0,0.0); glBegin(GL_QUADS); glColor3f( 1.0, 1.0, 0.0); glVertex3f(-0.5, 0.5, 0.0); glVertex3f( 0.5, 0.5, 0.0); glVertex3f( 0.5,-0.5, 0.0); glVertex3f(-0.5,-0.5, 0.0); glEnd(); OpenGLControl1.SwapBuffers; end; procedure Togl_form1.OpenGLControl1Resize(Sender: TObject); begin glViewport (0, 0, OpenGLControl1.Width, OpenGLControl1.Height); end; procedure Togl_form1.FormCreate(Sender: TObject); begin Application.OnIdle := @IdleFunc; end; procedure Togl_form1.FormResize(Sender: TObject); begin OpenGLControl1.SetBounds(0, 0, Width, Height); end; procedure Togl_form1.IdleFunc(Sender: TObject; var Done: Boolean); begin OpenGLControl1.Invalidate; end; end.
syntax highlighted by Code2HTML, v. 0.9.1