Реферат по предмету "Программирование"


OpenGL и Delphi на практике

OpenGL и Delphi на практике
Издательский Дом "КОМИЗДАТ"

Любая
теория хороша, если она может быть реализована на Delphi :-). Поэтому предлагаю
не откладывая в долгий ящик написать первую программу на OpenGL - а потом,
окрылившись успехом, вернуться к теории и как следует проштудировать все книги
и сайты по сабжу, чтобы уж стать настоящими монстрами трехмерного
моделирования.

Для
начала придется проделать подготовительную работу:

настроить
формат пикселей с учетом отображаемой информации;

создать
контекст OpenGL и подготовить сам движок OpenGL к работе.

Формат
пикселей удобно вынести в отдельную процедуру, которую мы оформим следующим
образом:

procedure SetDCPixelFormat (dc:
HDC);

var pfd: TPixelFormatDescriptor;

nPixelFormat: Integer;

begin

FillChar (pfd, SizeOf (pfd),0);

with pfd do

begin

nSize:= sizeof (pfd);

nVersion:= 1;

dwFlags:= PFD_DRAW_TO_WINDOW or

PFD_SUPPORT_OPENGL or

PFD_DOUBLEBUFFER;

iPixelType:= PFD_TYPE_RGBA;

cColorBits:= 16;

cDepthBits:= 64;

iLayerType:= PFD_MAIN_PLANE;

end;

nPixelFormat:=ChoosePixelFormat
(DC,@pfd);

SetPixelFormat (DC,
nPixelFormat,@pfd);

end;

Здесь
при заполнении структуры TPixelFormatDescriptor мы задаем параметры будущего
графического отображения, в том числе количество цветовых бит, а также тип
пикселей (iPixelType). Мы также задаем флаги, которые, как видно из названия,
указывают, что наша программа будет поддерживать OpenGL, а также что мы будем
рисовать в окне и использовать двойную буферизацию (параметр, необходимый для
воспроизведения движущихся объектов).

Далее
посредством вызова ChoosePixelFormat система выбирает подходящий формат пикселя
- и мы присваиваем его (через SetPixelFormat) нашему окну.

Теперь
нужно инициализировать контекст самого OpenGL посредством функций, содержащихся
в модуле Windows, и произвести дополнительную настройку движка:

procedure TForm1.FormCreate (Sender:
TObject);

begin

H:=Handle;

DC:=GetDC (H);

SetDCPixelFormat (DC);

RC:=wglCreateContext (DC);

wglMakeCurrent (DC, RC);

glClearColor (0.6,0.6,0.6,1.0);

glMatrixMode (GL_PROJECTION);

glLoadIdentity;

glFrustum (-1,1,-1,1,2,20);

glMatrixMode (GL_MODELVIEW);

glLoadIdentity;

glTranslatef
(0.0,-1.0,-6.0);

BeginPaint;

end;

Как
видим, сначала мы задали для нашей графики необходимый формат пикселей. Теперь
при помощи функции wglCreateContext создаем OpenGL-контекст, а впоследствии
делаем его текущим контекстом. Далее, используя уже универсальные функции**,
произведем настройку "мира", который будем создавать. Для этого через
glClearColor очистим контекст и заполним ее 60-процентным черным цветом. Далее
выберем матрицу проекций, которая определяет, как будут проецироваться
трехмерные объекты на плоскость экрана (в оконные координаты) и через
glLoadIdentity установим единичную матрицу и зададим границы плана в
"мировых координатах" при помощи вызова glFrustum. После чего
загрузим модельно видовую матрицу и произведем ее смещение (glTranslatef).
Что будем рисовать

Конечно,
можно было нарисовать простую пирамиду или же куб. Но мы сделаем большее - нарисуем
"признание в любви"** (рис. 1). Специально для этого методом
"научного перебора" была разработана модель, описывающая
соответствующую кривую:



Остается
только перевести ее с языка математики на нормальный человеческий.
Прорисовка сцены



Подготовку
сцены начнем с подключения разных дополнительных функций, без которых
дальнейшая работа невозможна. Эти функции прописаны в методе BeginPaint, а
также в методе FormResize (чтобы при изменении размера формы соответственно
менялся размер объекта). Для этого используем функцию glEnable с соответствующими
параметрами.

Далее
в FormPaint используем подготовленные заранее методы DrawFace и DrawElement
(см. листинг ниже) для отрисовки упомянутого объекта. А для придания ему еще
большей "жары" используем возможности OpenGL по освещению сцены.
Итог

С
точки зрения сложности освоения OpenGL сопоставим с другими подобными
библиотеками. Так что с одной стороны нет разницы, в чем разбираться и что
изучать. Но с точки зрения разумного подхода любой проект трехмерной графики
должен как минимум поддерживать OpenGL в качестве одной из опций. Ведь
серьезные вещи считаются и визуализируются, как правило, под
Unix/IRIX/Linux/FreeBSD, и в то же время было бы неправильно игнорировать
пользователей Windows. Так что OpenGL как раз и является тем универсальным
языком и общим знаменателем, позволяющим вашим приложениям свободно мигрировать
с одной платформы на другую.
Листинг программы

Листинг


========

unit
MainForm;

interface

uses

Windows, Messages, SysUtils,
Variants, Classes, Graphics, Controls, Forms,

Dialogs,OpenGL, StdCtrls, ExtCtrls;

type

TForm1 = class(TForm)

Timer1: TTimer;

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Label4: TLabel;

procedure FormCreate(Sender:
TObject);

procedure FormDestroy(Sender:
TObject);

procedure Timer1Timer(Sender:
TObject);

procedure FormPaint(Sender:
TObject);

procedure FormResize(Sender:
TObject);

private

RC:HGLRC;

DC:HDC;

H:THandle;

procedure BeginPaint;

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

const mat1_dif:Array[0..2] of Single
= (0.8,0.8,0.0);

const mat1_amb:Array[0..2] of Single
= (0.2,0.2,0.2);

const mat1_spec:Array[0..2] of
Single = (0.6,0.6,0.6);

const mat1_shininess = 0.5*128;

procedure
DrawElement(A,b,R0,r1:Single);

procedure DrawFace(A,R:Single;Normal:Boolean);

implementation

procedure SetDCPixelFormat(dc:HDC);

var pfd:TPixelFormatDescriptor;

nPixelFormat:Integer;

begin

FillChar(pfd,SizeOf(pfd),0);

with pfd do

begin

nSize := sizeof(pfd);

nVersion := 1;

dwFlags := PFD_DRAW_TO_WINDOW or

PFD_SUPPORT_OPENGL or

PFD_DOUBLEBUFFER;

iPixelType:= PFD_TYPE_RGBA;

cColorBits:= 16;

cDepthBits:= 64;

iLayerType:= PFD_MAIN_PLANE;

end;

nPixelFormat:=ChoosePixelFormat(DC,@pfd);

SetPixelFormat(DC,nPixelFormat,@pfd);

end;

procedure TForm1.BeginPaint;

begin

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

glEnable(GL_DEPTH_TEST);

glEnable(GL_NORMALIZE);

glEnable(GL_COLOR_MATERIAL);

timer1.enabled:=true;

end;

{$R *.dfm}

procedure TForm1.FormCreate(Sender:
TObject);

begin

H:=Handle;

DC:=GetDC(H);

SetDCPixelFormat(DC);

RC:=wglCreateContext(DC);

wglMakeCurrent(DC,RC);

glClearColor(0.6,0.6,0.6,1.0);

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

glFrustum(-1,1,-1,1,2,20);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity;

glTranslatef(0.0,-1.0,-6.0);

BeginPaint;

end;

procedure TForm1.FormDestroy(Sender:
TObject);

begin

wglMakeCurrent(0,0);

wglDeleteContext(RC);

ReleaseDC(H,DC);

DeleteDC(DC);

end;

procedure TForm1.Timer1Timer(Sender:
TObject);

begin

glRotatef(4.0,0.0,1.0,0.0);

SwapBuffers(DC);

InvalidateRect(H,nil,False);

end;

procedure
DrawElement(a,b,r0,r1:Single);

var x1b,y1b:Single;

x1e,y1e:Single;

x0b,y0b:Single;

x0e,y0e:Single;

t0,t1:Single;

dt:single;

begin

t0:=-3;t1:=3;

dt:=0.06;

while t0

begin

x0b:=a*sin(t0)*sin(t0)*sin(t0)*sin(t0)*cos(t0);

y0b:=a*abs(sin(t0)*cos(t0));

x0e:=a*sin(t0+dt)*sin(t0+dt)*sin(t0+dt)*sin(t0+dt)*cos(t0+dt);

y0e:=a*abs(sin(t0+dt)*cos(t0+dt));

x1b:=b*sin(t0)*sin(t0)*sin(t0)*sin(t0)*cos(t0);

y1b:=b*abs(sin(t0)*cos(t0));

x1e:=b*sin(t0+dt)*sin(t0+dt)*sin(t0+dt)*sin(t0+dt)*cos(t0+dt);

y1e:=b*abs(sin(t0+dt)*cos(t0+dt));

glBegin(GL_TRIANGLE_STRIP);

glNormal((x0b+x1e)/2,(y0b+y1e)/2,(r1+r0)/2);

glVertex3f(x0b,y0b,r0);

glVertex3f(x0e,y0e,r0);

glVertex3f(x1e,y1e,r1);

glVertex3f(x1b,y1b,r1);

glEnd;

t0:=t0+dt;

end;

end;

procedure DrawFace(A,R:Single;Normal:Boolean);

var x,y:single; t0,t1,dt:Single;

begin

t0:=-3;t1:=3;

dt:=0.06;

glBegin(GL_POLYGON);

while t0

begin

x:=a*sin(t0)*sin(t0)*sin(t0)*sin(t0)*cos(t0);

y:=a*abs(sin(t0)*cos(t0));

glVertex3F(x,y,r);

t0:=t0+dt;

end;

t0:=0;

x:=a*sin(t0)*sin(t0)*sin(t0)*sin(t0)*cos(t0);

y:=a*abs(sin(t0)*cos(t0));

if Normal then glNormal3f(x,y,-r)
else glNormal3f(x,y,r);

glEnd;

end;

procedure TForm1.FormPaint(Sender:
TObject);

var
m,n:single;dm:Single;a:Single;df:Single;

begin

a:=25;

df:=10;

glClear(GL_COLOR_BUFFER_BIT or
GL_DEPTH_BUFFER_BIT);

glColor(1.0,0.0,0.0,0.0);

glMaterialfv(GL_FRONT,GL_AMBIENT,@mat1_amb);

glMaterialfv(GL_FRONT,GL_DIFFUSE,@mat1_dif);

glMaterialfv(GL_FRONT,GL_SPECULAR,@mat1_spec);

glMaterialf(GL_FRONT,GL_SHININESS,mat1_shininess);

m:=-1;n:=1;dm:=0.5;

while m

begin

DrawElement(Sqrt(a-m*m),Sqrt(a-(m+dm)*(m+dm)),m/df,(m+dm)/df);

m:=m+dm;

end;

DrawFace(Sqrt(a-(m)*(m)),(m)/df,True);

m:=-1;

DrawFace(Sqrt(a-(m)*(m)),(m)/df,True);

end;

procedure TForm1.FormResize(Sender:
TObject);

const lm:Array[0..3] of Single =
(0.5,0.5,0.5,1.0);

const

light_ambient:array[0..3] of glfloat
= (0.0,0.0,0.0,1.0);

light_diffuse:array[0..3] of glfloat
= (1.0,1.0,1.0,1.0);

light_specular:array[0..3] of glfloat
= (2.0,2.0,2.0,1.0);

light_position:array[0..3] of
glfloat = (2.0,1.0,3.0,1.0);

light_emission:array[0..3] of
glfloat = (1.0,1.0,1.0,1.0);

light_spotdirection:array[0..3] of
glfloat = (1.0,1.0,1.0,1.0);

begin

wglMakeCurrent(0,0);

wglDeleteContext(RC);

ReleaseDC(H,DC);

DC:=GetDC(H);

SetDCPixelFormat(DC);

RC:=wglCreateContext(DC);

wglMakeCurrent(DC,RC);

glClearColor(0.6,0.6,0.6,0.0);

glMatrixMode(GL_PROJECTION);

glLoadIdentity;

glFrustum(-1,1,-1,1,2,20);

glMatrixMode(GL_MODELVIEW);

glLoadIdentity;

glTranslatef(0.0,-1.0,-6.0);

glLightModel(GL_LIGHT_MODEL_LOCAL_VIEWER,Ord(True));

glLightModelfv(GL_LIGHT_MODEL_AMBIENT,@lm);

glLightfv(GL_LIGHT0,GL_AMBIENT,@light_ambient);

glLightfv(GL_LIGHT0,GL_DIFFUSE,@light_diffuse);

glLightfv(GL_LIGHT0,GL_SPECULAR,@light_specular);

glLightfv(GL_LIGHT0,GL_POSITION,@light_position);

glLightf(GL_LIGHT0,GL_SPOT_EXPONENT,8);

glLightf(GL_LIGHT0,GL_SPOT_CUTOFF,170);

glLightfv(GL_LIGHT0,GL_SPOT_DIRECTION,@light_spotdirection);

glEnable(GL_LIGHTING);

glEnable(GL_LIGHT0);

glEnable(GL_DEPTH_TEST);

glEnable(GL_NORMALIZE);

glEnable(GL_COLOR_MATERIAL);

end;

end.
Список литературы

Для
подготовки данной работы были использованы материалы с сайта http://www.citforum.ru/


Не сдавайте скачаную работу преподавателю!
Данный реферат Вы можете использовать для подготовки курсовых проектов.

Поделись с друзьями, за репост + 100 мильонов к студенческой карме :

Пишем реферат самостоятельно:
! Как писать рефераты
Практические рекомендации по написанию студенческих рефератов.
! План реферата Краткий список разделов, отражающий структура и порядок работы над будующим рефератом.
! Введение реферата Вводная часть работы, в которой отражается цель и обозначается список задач.
! Заключение реферата В заключении подводятся итоги, описывается была ли достигнута поставленная цель, каковы результаты.
! Оформление рефератов Методические рекомендации по грамотному оформлению работы по ГОСТ.

Читайте также:
Виды рефератов Какими бывают рефераты по своему назначению и структуре.