Міністерство освіти і науки України
Національний університет «Львівська політехніка»
Кафедра САПР
Звіт до лаболаторної роботи №4
На тему
ДВОМІРНІ ПОБУДОВИ З ВИКОРИСТАННЯМ OpenGL
ЗАСОБАМИ BORLAND DELPHI
З курсу: Геометричне моделювання у конструюванні
інженерних об'єктів і систем
1. МЕТА РОБОТИ
Мета роботи – ознайомлення та практичне освоєння технології й основ роботи з графічними можливостями бібліотеки OpenGL на площині в операційному середовищі Wіndows. Вивчити способи підключення бібліотеки OpenGL при розробці програмних проектів засобами візуального середовища програмування Borland Delphi. Ознайомитися та засвоїти основні графічні функцій та процедури, набути практичних навиків програмування графіки для Wіndows-програм на основі OpenGL.
2. ТЕОРЕТИЧНІ ВІДОМОСТІ
2.1. ОСНОВНІ ПОНЯТТЯ
OpenGL – це стандартна бібліотека для усіх 32-розрядних операційних систем, у тому числі і для операційної системи Windows. OpenGL – не окрема програма, а частина операційної системи. Це означає, що відкомпільована програма, яка використовує OpenGL, не потребує ніяких додаткових програм чи модулів, крім стандартних, що містяться на будь-якому комп’ютері з встановленою операційною системою Windows 95 версії OSR2 та вище. У склад стандартної поставки Delphi (починаючи з третьої версії) входить заготовочний файл, який дозволяє будувати програми з використанням OpenGL, а також довідковий файл по командах цієї бібліотеки. OpenGL є на даний момент одним з найпопулярніших програмних інтерфейсів (API) для розробки прикладних програм в області двовимірної й тривимірної графіки. Стандарт OpenGL був розроблений і затверджений в 1992 році провідними фірмами в галузі розробки програмного забезпечення, а його основою стала бібліотека IRIS GL, розроблена Silicon Graphics. На даний час реалізація OpenGL включає в себе декілька бібліотек (опис базових функцій OpenGL, GLU, GLUT, GLAUX та інші). Характерними особливостями OpenGL, які забезпечили поширення і розвиток цього графічного стандарту, є:
• Стабільність. Доповнення і зміни в стандарті реалізовуються таким чином, щоб зберегти
сумісність з розробленим раніше програмним забезпеченням.
• Надійність і переносимість. Програми, що використовують OpenGL, гарантують
однаковий візуальний результат незалежно від типу операційної системи, що
використовується для організації відображення інформації. Крім того, ці програми можуть
виконуватися як на персональних комп’ютерах, так і на робочих станціях і
суперкомп’ютерах.
• Легкість застосування.
Стандарт OpenGL має продуману структуру та інтуїтивно зрозумілий інтерфейс, що дозволяє з меншими витратами створювати ефективні програми, що містять менше рядків коду, ніж з використанням інших графічних бібліотек. Необхідні функції для забезпечення сумісності з різним обладнанням реалізовані на рівні бібліотеки u1110 і значно спрощують розробку прикладних програм.
2.1.1 Основні можливості OpenGL :
• Набір базових примітивів: точки, лінії, багатокутники тощо.
• Видові та координатні перетворення.
• Вилучення невидимих ліній і поверхонь (z-буфер).
• Використання сплайнів для побудови ліній та поверхонь.
• Накладення текстури та застосування освітлення.
• Додаткові спеціальні ефекти: туман, зміна прозорості, поєднання кольорів (blending), усунення ступінчатості (anti-aliasing).
Існує реалізація OpenGL для різних платформ, для чого було зручно розділити базові функції графічної системи та функції для відображення графічної інформації і взаємодії з користувачем. Були створені бібліотеки для відображення інформації за допомогою віконної підсистеми для операційних систем Windows і Unix (WGL і GLX відповідно), а також бібліотеки GLAUX та GLUT, які використовуються для створення так званих консольних програм. Бібліотека GLAUX поступається за популярністю написаній дещо пізніше бібліотеці GLUT, хоч вони надають приблизно однакові можливості. До складу бібліотеки GLU увійшла реалізація більш складних функцій, таких як набір популярних геометричних примітивів (куб, куля, циліндр, диск), функції побудови сплайнів, реалізація додаткових операцій над матрицями тощо. Усі вони реалізовані через базові функції OpenGL.
2.1.2. Архітектура і особливості синтаксису
З точки зору архітектури, графічна система OpenGL є конвейєром, що складається з декількох етапів обробки даних:
• Апроксимація кривих і поверхонь.
• Обробка вершин і збирання примітивів.
• Растеризация і обробка фрагментів.
• Операції над пікселями.
• Підготовка текстури.
• Передача даних в буфер кадру.
Узагалі, OpenGL можна порівняти з кінцевим автоматом, стан якого визначається безліччю значень спеціальних змінних (їхні імена звичайно починаються з символів GL_) і значеннями поточної нормали, кольору та координат текстури. Уся ця інформація буде використана при надходженні в систему координат вершини для побудови фігури, в яку вона входить. Зміна станів відбувається за допомогою команд, які оформляються як виклики функцій.
Для забезпечення інтуїтивно зрозумілих назв в OpenGL повне ім’я команди має вигляд:
type glCommand_name[1 2 3 4][b s i f d ub us ui][v](type1 arg1,-, typeN argN)
Таким чином, ім’я складається з декількох частин:
gl це ім’я бібліотеки, в якій описана ця функція: для базових функцій OpenGL, функцій з бібліотек GLU, GLUT, GLAUX це gl, glu, glut, aux відповідно.
Command_name ім’я команди
[1 2 3 4] кількість аргументів команди
[b s i f d ub us ui ] тип аргументу:
b – GLbyte байт
s – GLshort коротке ціле
і – GLіnt ціле
f – GLfloat дробове
d – GLdouble дробове з подвійною точністю
ub – GLubyte беззнаковий байт
us – GLushort беззнакове коротке ціле
uі – GLuіnt беззнакове ціле
[v] наявність цього символа показує, що як параметри функції використовується покажчик на масив значень. Символи в квадратних дужках в деяких назвах не використовуються.
Наприклад, команда glVertex2i() описана як базова в бібліотеці OpenGL, і використовує як параметри два цілих числа, а команда glColor3fv() використовує як параметр покажчик на масив з трьох дійсних чисел.
2.2 ПРОСТІ ГРАФІЧНІ ПРИМІТИВИ
Крапки, лінії, трикутники,чотирикутники, багатокутники – прості об’єкти, з яких складаються будь-як складні фігури. OpenGL безпосередньо не підтримує функцій для створення таких складних об’єктів як сфера, конус і тор, тобто таких функцій немає в opengl32.dll. Ці функції є в бібліотеці утиліт glu32.dll, і влаштовані вони в такий спосіб. Для того щоб намалювати сферу, функція gluSphere використовує функції з бібліотеки glu32.dll, а ті у свою чергу, використовують базову бібліотеку opengl32.dll і з ліній багатокутників будують сферу.
Примітиви створюються в такий спосіб:
glBegіn(GLenum mode); // указуємо, що будемо малювати
glVertex[2 3 4][s і f d](...); // перша вершина
... // тут інші вершини
glVertex[2 3 4][s і f d](...); // остання вершина
glEnd(); // закінчили малювати примітив
Спочатку вказується, що буде малюватися – glBegіn із відповідним параметром.
Можливі значення mode перераховані нижче в таблиці 1. Далі вказуються вершини, що визначають об’єкти зазначеного типу. Можна задавати вершину одним з цих способів:
glVertex2d(x,y); // дві змінних типу double
glVertex3d(x,y,z); // три змінних типу double
glVertex2dv(array); // масив із двох змінних типу double
glVertex3d(array); // масив із трьох змінних типу double
Виклик glEnd вказує, що закінчили малювати об’єкти типу, зазначеного в glBegіn.
Режими малювання простих примітивів:
GL_POINTS - кожний виклик glVertex задає окрему крапку
GL_LINES - кожна пара вершин задає відрізок
GL_LINE_STRIP - рисується ламана
GL_LINE_LOOP - рисується ламана, причому її остання точка з’єднюється з першою
GL_TRIANGLES - кожні три виклики glVertex задають трикутник
GL_TRIANGLE_STRIP - рисуються трикутники з спільною стороною
GL_TRIANGLE_FAN - теж саме, але по іншому правилу з’єднюються вершини
GL_QUADS - кожні четири виклики glVertex задают чотирьохкутник
GL_QUAD_STRIP - чотирьохкутники із спільною стороною
GL_POLYGON - багатокутник
Тип GL_LINES задає формування відрізка за двома вершинами, які розглядаються як його початкова та кінцева точки. Побудовані таким чином відрізки не стикуються один з одним у крайніх точках (рис. 7, а). Якщо необхідно сформувати ламану лінію (polyline) – послідовність зі стикованих відрізків, – то використовується тип GL_LINE_STRIP. Найчастіше ламані лінії використовуються для апроксимації кривих. Якщо необхідно отримати замкнутий контур, то можна чи вказати як кінцеву та початкову в списку одну й ту ж вершину, чи використати спеціальний тип, який визначає саме замкнуту лінію, – GL_LINE_LOOP. Замкнута лінія не має внутрішньої області на відміну від багатокутника. Багатокутники (polygon) відіграють особливу роль у комп’ютерній графіці, оскільки у растрових системах зображення таких примітивів формується дуже швидко. За допомогою багатокутників апроксимують криволінійні поверхні. Продуктивність графічних систем прийнято зараз оцінювати у кількості багатокутників, які виводяться на екран протягом одної секунди. Можна виводити лише контур, заливати внутрішню область одним кольором чи заповнювати певним малюнком, причому в залитому багатокутнику границі можуть і не відображатися.
Ребра об’єктів багатокутників (тип GL_POLYGON) співпадають з відрізками замкнутої ламаної, яка побудована на тому самому наборі вершин. Внутрішня область об’єкта заповнюється згідно із заданими атрибутів зафарбування. В OpenGL можна використовувати функцію glPolygonMode( ) для відображення ребер та відміняти використовуваний по замовчуванню режи зафарбування. Формування трикутників (тип GL_TRIANGLES) та чотирьохкутників (тип GL_QUADS) задається відповідно трьома та чотирма вершинами. Ці об’єкти тонуються швидше, ніж такіж за формою об’єкти типу GL_POLYGON.
Смуги (GL_TRIANGLE_STRIP, GL_QUAD_STRIP, GL_TRIANGLE_FAN) є групою трикутників чи чотирьохкутників, у яких окремі фігури сумісно використовують декілька вершин. У трикутній смузі – об’єкт типу GL_TRIANGLE_STRIP – кожна наступна вершина у списку комбінується з двома попередніми та визначає таким чином наступну трикутну комірку смуги. У смузі, що складається з чотирьохкутних комірок – об’єкті типу GL_QUAD_STRIP, - кожна пара вершин у списку комбінуються з попередньою парою та задає наступну комірку. Об’єкт типу GL_TRIANGLE_FAN – роза – будується на основі одної фіксованої вершини (центра), яка йде першою у списку вершин. Наступні дві вершини у списку визначають перший трикутний „пелюсток”, а потім кожна наступна вершина разом з попередньою у списку та центральною точкою задають наступний „пелюсток”.
Індивідуальне завдання
Варіант 29:
Написати програму із застосуванням 2D графічних функцій бібліотеки OpenGL, яка дозволяє візуалізувати у незалежних вікнах програми заповнення випадковими колами, із різними кольорами, контурами, розбиванням трикутниками, чотирикутниками, центральною вершиною.
Результати роботи:
Текст програми:
program projectLaba4;
uses
Forms,
laba4 in 'laba4.pas' {Form1},
laba4U2 in 'laba4U2.pas' {Form2},
laba4_2 in 'laba4_2.pas' {Form3};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TForm2, Form2);
Application.Run;
end.
unit laba4U2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm2 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender:TObject);
procedure Button2Click(Sender:TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
uses laba4, laba4_2;
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
var
Form1: TForm1;
begin
Form1 := TForm1.Create(nil);
Form1.Top := random(round(ClientWidth/2));
Form1.Left := random(round(ClientHeight/2));
Form1.Show;
end;
procedure TForm2.Button2Click(Sender:TObject);
var
Form3: TForm3;
begin
Form3 := TForm3.Create(nil);
Form3.Top := random(round(ClientWidth/2));
Form3.Left := random(round(ClientHeight/2));
Form3.Show;
end;
end.
unit laba4_2;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OpenGL;
type
TForm3 = class(TForm)
procedure FormCreate(Sender:TObject);
procedure FormPaint(Sender:TObject);
procedure FormDestroy(Sender:TObject);
procedure FormClose(Sender:TObject; var Action: TCloseAction);
private
hrc: HGLRC;
R, G, B : Single;
end;
var
Form3: TForm3;
implementation
{$R *.dfm}
procedure TForm3.FormPaint(Sender:TObject);
var
circle_count, many_kytnysk,count_sectors,j, i: integer;
center_x, center_y, radius : single;
begin
wglMakeCurrent(Canvas.Handle, hrc);
glViewPort(0, 0, ClientWidth, ClientHeight);
glClearColor(R, G, B, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
circle_count := round(random(10));
radius := random;
for i := 1 to circle_count do
begin
center_x := random;
center_y := random;
count_sectors := random(10)+ 6;
glColor3f(random, random, random);
glBegin(GL_QUAD_STRIP);
glVertex2f(center_x, center_y);
glVertex2f(center_x, center_y - radius);
//glVertex2f(center_x + radius * cos(2*pi/count_sectors), center_y + radius * sin(2*pi/count_sectors));
for j := 2 to count_sectors + 2 do
begin
glVertex2f(center_x, center_y);
glVertex2f(center_x + radius * cos(2*pi/count_sectors * j), center_y + radius * sin(2*pi/count_sectors * j));
end;
glEnd;
end;
wglMakeCurrent(0, 0);
end;
procedure setDCPixelFormat(hdc: HDC);
var
pfd: TPixelFormatDescriptor;
nPixelFormat: Integer;
begin
FillChar(pfd, SizeOf(pfd), 0);
nPixelFormat := ChoosePixelFormat(hdc, @pfd);
SetPixelFormat(hdc, nPixelFormat, @pfd);
end;
procedure TForm3.FormCreate(Sender:TObject);
begin
SetDCPixelFormat(Canvas.Handle);
hrc := wglCreateContext(Canvas.Handle);
R := random;
G := random;
B := random;
end;
procedure TForm3.FormDestroy(Sender:TObject);
begin
wglDeleteContext(hrc);
end;
procedure TForm3.FormClose(Sender:TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
end.
unit laba4;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OpenGL;
type
TForm1 = class(TForm)
procedure FormCreate(Sender:TObject);
procedure FormPaint(Sender:TObject);
procedure FormDestroy(Sender:TObject);
procedure FormClose(Sender:TObject; var Action: TCloseAction);
private
hrc: HGLRC;
R, G, B : Single;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormPaint(Sender:TObject);
var
circle_count, many_kytnysk,count_sectors,j, i: integer;
center_x, center_y, radius : single;
begin
wglMakeCurrent(Canvas.Handle, hrc);
glViewPort(0, 0, ClientWidth, ClientHeight);
glClearColor(R, G, B, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
circle_count := round(random(10));
radius := random;
for i := 1 to circle_count do
begin
center_x := random;
center_y := random;
count_sectors := random(10)+ 6;
glColor3f(random, random, random);
glBegin(GL_TRIANGLE_STRIP);
glVertex2f(center_x, center_y);
glVertex2f(center_x, center_y - radius);
glVertex2f(center_x + radius * cos(2*pi/count_sectors), center_y + radius * sin(2*pi/count_sectors));
for j := 2 to count_sectors + 1 do
begin
glVertex2f(center_x, center_y);
glVertex2f(center_x + radius * cos(2*pi/count_sectors * j), center_y + radius * sin(2*pi/count_sectors * j));
end;
glEnd;
end;
wglMakeCurrent(0, 0);
end;
procedure setDCPixelFormat(hdc: HDC);
var
pfd: TPixelFormatDescriptor;
nPixelFormat: Integer;
begin
FillChar(pfd, SizeOf(pfd), 0);
nPixelFormat := ChoosePixelFormat(hdc, @pfd);
SetPixelFormat(hdc, nPixelFormat, @pfd);
end;
procedure TForm1.FormCreate(Sender:TObject);
begin
SetDCPixelFormat(Canvas.Handle);
hrc := wglCreateContext(Canvas.Handle);
R := random;
G := random;
B := random;
end;
procedure TForm1.FormDestroy(Sender:TObject);
begin
wglDeleteContext(hrc);
end;
procedure TForm1.FormClose(Sender:TObject; var Action: TCloseAction);
begin
Action := caFree;
end;
end.
Висновок: в процесі виконання даної лабораторної роботи я освоїв основи роботи з графічними можливостями бібліотеки OpenGL, реалізував програму для побудови кіл, за допомогою таких графічних примітивів як: трикутник, чотирикутник.