Управление элементами поверхности
КУРСОВОЙ ПРОЕКТ
на тему:
«Управление элементами
поверхности»
Орел, 2010
Введение
Понятие «компьютерная
графика» существует уже давно. Трудно определить, когда именно и кем были
разработаны первые понятия компьютерной графики. В настоящее время компьютерная
графика – это огромный мир, такой же, как мир операционных систем, или
программирования, это нечто большее, чем просто графика. Вообще, все, что на
компьютере рисует пользователь – это и есть компьютерная графика.
Компьютерная
графика применяется в самых разнообразных сферах деятельности человека: в кино,
в сфере рекламы, в полиграфии, в информационных сферах (телевидение, интернет),
в сфере игростроения и многих других.
Исходя из
этого, давайте подробно рассмотрим значимость компьютерной графики на
сегодняшний день. Киноиндустрия получает ежегодную многомиллионную прибыль от
фильмов, в которых использованы современные спецэффекты. Вспомнить хотя бы
такие известные фантастические фильмы, как Люди в черном, Матрица и тому
подобные. Во всех них использовалась компьютерная графика, создающая эффект
максимальной реалистичности происходящего. Смотря на все происходящее в фильме,
создается впечатление, что все это было на самом деле.
Компьютерная
графика широко используется на телевидении. Все больше и больше последнее время
компьютерная графика используется при создании красивых телевизионных заставок,
которые вещают на телеканалах. Красивые заставки – это залог успеха телеканала.
Последнее время проводятся даже соревнования между телеканалами, у кого лучше
заставка. Компьютерная графика стала самым основный ресурсом, который
затрачивается при создании компьютерных игр. Любая компьютерная графика
представляется в играх в так называемом трехмерном виде, или 3d. Данным
подразделением компьютерной графики занимаются специализированные графические
редакторы, например Maya, 3d-Studio Max.
Целью данной
курсовой работы является получение практических знаний по курсу компьютерная
графика.
Задачами
является изучение основных возможностей создания трехмерных объектов в OpenGL, наложения текстур.
Целью данной
курсовой работы является получение практических знаний по курсу компьютерная
графика. С помощью возможностей OpenGL будет создана модель управления элементами
поверхности.
Задачами
является изучение основных возможностей создания трехмерных объектов, наложения
текстур, работа с координатами.
Для упрощения
описания работы программы, алгоритм выполнения
был разбит на
части: подключение библиотек, создание поверхности ландшафта, изменение
поверхности ландшафта, реализация ориентирования на поверхности.
Сначала
необходимо инициализировать библиотеки и установить
общие
свойства сцены. Для этого создадим обработчик события onCreate формы и занесем в него
следующий код:
InitOpenGL(Handle);
glViewport
(0, 0, ClientWidth-Panel1. Width, ClientHeight);
glClearColor
(0,0,0,0);
glEnable
(GL_DEPTH_TEST);
glMatrixMode
(GL_PROJECTION);
gluPerspective
(30.0, ClientWidth / ClientHeight, 0.1, 1000.0);
glMatrixMode (GL_MODELVIEW);
glLoadIdentity;
Первый
оператор инициализирует библиотеку OpenGL и устанавливает связь с окном приложения, в
котором будет производиться вывод. После получения контекста воспроизведения
сообщаем системе OpenGL о том, что необходимо корректировать построения в
соответствии с глубиной командой glEnable (GL_DEPTH_TEST). Команда glClearColor определяет величину,
которой будет заполняться буфер цвета при его очистке, т.е. это будет цвет фона
– черный.
2.2
Создание
поверхности ландшафта
Для того
чтобы создать ландшафт, было принято решение использовать массив, в котором
будет храниться высота координат:
Var
…
height:array
[-11..11, -11..11] of single;
…
При создании
формы происходит вызов процедуры initmas, которая инициализирует
массив высот:
…
procedure
initmas;
var
i, j:integer;
begin
for
i:= -11 to 11 do
for
j:=-11 to 11 do
begin
height
[i, j]:=-1;
end;
end;
…
Рисование
поверхности производится вызовом процедуры Draw в обработчике события OnPaint:
procedure
Draw;
…
for
i:=-10 to 10 do
for
j:=-10 to 10 do
begin
x:=i*zoom;
z:=j*zoom;
glBindTexture
(GL_TEXTURE_2D, MyTextureTex);
glBegin
(GL_QUADS);
glTexCoord2f
(0.0, 0.0); glVertex3f (x, height [i, j], z);
glTexCoord2f
(1.0, 0.0); glVertex3f (x, height [i, j+1], z+zoom);
glTexCoord2f
(1.0, 1.0); glVertex3f (x+Zoom, height [i+1, j+1], z+zoom);
glTexCoord2f
(0.0, 1.0); glVertex3f (x+Zoom, height [i+1, j], z);
glEnd;
end;
end;
В этой
процедуре по каждому значению массива height строится ландшафт.
Для того
чтобы наглядно продемонстрировать ландшафт, было принято решение дать
наблюдателю возможность перемещаться по поверхности. Для того, чтобы это
реализовать в обработчик события OnFormKeyDown формы занесем следующий код:
case
key of
27:
Form1. Close;
65:
begin
Human.
Position.z:=Human. Position.z+
sin
(DegToRad(Human. Rotation.y))*SPEED;
Human.
Position.x:=Human. Position.x+
cos
(DegToRad(Human. Rotation.y))*SPEED;
end;
Human.
Position.z:=Human. Position.z+
cos
(DegToRad(Human. Rotation.y))*SPEED;
Human.
Position.x:=Human. Position.x-
sin
(DegToRad(Human. Rotation.y))*SPEED;
end;
68:
begin
Human.
Position.z:=Human. Position.z-
sin
(DegToRad(Human. Rotation.y))*SPEED;
Human.
Position.x:=Human. Position.x-
cos
(DegToRad(Human. Rotation.y))*SPEED;
end;
83:
begin
Human.
Position.z:=Human. Position.z-
cos
(DegToRad(Human. Rotation.y))*SPEED;
Human.
Position.x:=Human. Position.x+
sin
(DegToRad(Human. Rotation.y))*SPEED;
end;
end;
При нажатии
клавиши изменяется позиция наблюдателя в пространстве.
2.4
Изменение
поверхности ландшафта
Чтобы
изменить поверхность мы сначала должны получить координаты изменяемой
поверхности. Получение координат реализуется процедурой GetCoordinate. Далее происходит
изменение массива высот:
…
i:=Trunc(wx);
j:=Trunc(wz);
height [i, j]:=vis;
…
В переменной vis содержится значение,
определенное пользователем, на которое изменится высота.
В результате
выполнения курсовой работы были выполнены все поставленные цели, изучены основные
возможности создания трехмерных объектов, наложения текстур и перемещения в
пространстве.
Список литературы
1.
Михаил
Краснов, OpenGL в Delphi, электронный вариант.
2.
Эйнджел,
Эдвард, Интерактивная компьютерная графика. Вводный курс на базе OpenGL, 2 изд.: Пер. с англ. – М.:
Издательский дом «Вильяме», 2001. – 592 с: ил. – Парал. тит. Англ.
3.
Райт,
OpenGL. Суперкнига, 3-е издание
[Электронный
ресурс] / Райт, Ричард С.-мл., Липчак, Бенджамин // Книги по
программированию. [Режим доступа: #"_Toc262511650">Приложение
А
unit Unit1;
interface
uses
Windows,
Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,
OpenGL, ExtCtrls, Math, StdCtrls, ComCtrls, TEXTURES;
type
TForm1
= class(TForm)
Timer1:
TTimer;
Panel1:
TPanel;
Button1:
TButton;
Button2:
TButton;
Button3:
TButton;
Button4:
TButton;
TrackBar1:
TTrackBar;
Label1:
TLabel;
Label2:
TLabel;
Label3:
TLabel;
Button5:
TButton;
Button6:
TButton;
procedure
FormKeyDown (Sender: TObject; var Key: Word;
Shift:
TShiftState);
procedure
FormCreate (Sender: TObject);
procedure
FormDestroy (Sender: TObject);
procedure
Timer1Timer (Sender: TObject);
procedure
FormResize (Sender: TObject);
procedure
FormPaint (Sender: TObject);
procedure
FormMouseMove (Sender: TObject; Shift: TShiftState; X,
Y:
Integer);
procedure
FormMouseDown (Sender: TObject; Button: TMouseButton;
Shift:
TShiftState; X, Y: Integer);
procedure
Button3Click (Sender: TObject);
procedure
Button4Click (Sender: TObject);
procedure
Button1Click (Sender: TObject);
procedure
Button2Click (Sender: TObject);
procedure
TrackBar1Change (Sender: TObject);
procedure
Button5Click (Sender: TObject);
procedure
Button6Click (Sender: TObject);
private
{Private
declarations}
public
{Public
declarations}
type
User=record
Position:record
x,
y, z: Single;
end;
Rotation:record
y,
zx: Single;
end;
end;
var
vis:single;
Form1:
TForm1;
DC:HDC;
HRC:HGLRC;
Human:
User;
MyTextureTex:
glUint;
wx,
wy, wz: GLdouble; // возвращаемые мировые x, у, z координаты
height:array
[-11..11, -11..11] of single;
implementation
procedure
glBindTexture (target: GLenum; texture: GLuint); stdcall; external opengl32;
{$R
*.dfm}
procedure
GetCoordinate (const x, y:integer);
var
Viewport:
Array [0..3] of GLInt; // область вывода
mvMatrix, //
матрица модели
ProjMatrix:
Array [0..15] of GLDouble; // матрица проекций
RealY:
GLint; // OpenGL у – координата
Zval:
GLfloat; // оконная z – координата
Begin
glGetIntegerv
(GL_VIEWPORT, @Viewport); // матрица области вывода
//
заполняем массивы матриц
glGetDoublev
(GL_MODELVIEW_MATRIX, @mvMatrix);
glGetDoublev
(GL_PROJECTION_MATRIX, @ProjMatrix); // viewport[3] – высота окна в
пикселах, соответствует Height
RealY:=
viewport[3] – Y – 1;
FloatToStr
(RealY);
glReadPixels
(X, RealY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, @Zval);
gluUnProject
(X, RealY, Zval,
@mvMatrix,
@ProjMatrix, @Viewport, wx, wy, wz);
end;
procedure
initmas;
var
i, j:integer;
begin
for
i:= -11 to 11 do
for
j:=-11 to 11 do
begin
height
[i, j]:=-1;
end;
end;
procedure
changemas;
var
i, j:integer;
begin
i:=Trunc(wx);
j:=Trunc(wz);
height
[i, j]:=vis;
end;
procedure
Draw;
var
i, j:integer;
x,
z:integer;
zoom:integer;
begin
glColor3f
(1,0,0);
glPointSize
(5);
glBegin
(GL_POINTS);
glVertex3f
(wx, wy, wz);
glEnd;
zoom:=1;
glColor3f
(0. 7,1. 0,0.7);
for
i:=-10 to 10 do
for
j:=-10 to 10 do
begin
z:=j*zoom;
glPointSize
(1);
glBindTexture
(GL_TEXTURE_2D, MyTextureTex);
glBegin
(GL_QUADS);
glTexCoord2f
(0.0, 0.0); glVertex3f (x, height [i, j], z);
glTexCoord2f
(1.0, 0.0); glVertex3f (x, height [i, j+1], z+zoom);
glTexCoord2f
(1.0, 1.0); glVertex3f (x+Zoom, height [i+1, j+1], z+zoom);
glTexCoord2f
(0.0, 1.0); glVertex3f (x+Zoom, height [i+1, j], z);
glEnd;
end;
end;
procedure
TForm1. FormKeyDown (Sender: TObject; var Key: Word;
Shift:
TShiftState);
const
SPEED=0.2;
begin
case
key of
27:
Form1. Close;
65:
begin
Human.
Position.z:=Human. Position.z+
sin
(DegToRad(Human. Rotation.y))*SPEED;
Human.
Position.x:=Human. Position.x+
cos
(DegToRad(Human. Rotation.y))*SPEED;
end;
87:
begin
Human.
Position.z:=Human. Position.z+
cos
(DegToRad(Human. Rotation.y))*SPEED;
Human.
Position.x:=Human. Position.x-
sin
(DegToRad(Human. Rotation.y))*SPEED;
end;
68:
begin
Human.
Position.z:=Human. Position.z-
sin
(DegToRad(Human. Rotation.y))*SPEED;
Human.
Position.x:=Human. Position.x-
cos
(DegToRad(Human. Rotation.y))*SPEED;
end;
83:
begin
Human.
Position.z:=Human. Position.z-
cos
(DegToRad(Human. Rotation.y))*SPEED;
Human.
Position.x:=Human. Position.x+
sin
(DegToRad(Human. Rotation.y))*SPEED;
end;
end;
end;
procedure
SetDCPixelFormat;
var
pfd:TPixelFormatDescriptor;
nPixelFormat:
Integer;
begin
FillChar
(pfd, SizeOf(pfd), 0);
pfd.dwFlags:=PFD_DRAW_TO_WINDOW
or
PFD_DOUBLEBUFFER
or
PFD_SUPPORT_OPENGL;
nPixelFormat:=ChoosePixelFormat
(DC,@pfd);
SetPixelFormat
(DC, nPixelFormat,@pfd);
end;
procedure
TForm1. Button1Click (Sender: TObject);
begin
Human.
Rotation.y:=Human. Rotation.y-4;
if
Human. Rotation.y>=360 then Human. Rotation.y:=0;
if
Human. Rotation.y<0 then Human. Rotation.y:=360;
end;
procedure
TForm1. Button2Click (Sender: TObject);
begin
Human.
Rotation.y:=Human. Rotation.y+4;
if
Human. Rotation.y>=360 then Human. Rotation.y:=0;
if
Human. Rotation.y<0 then Human. Rotation.y:=360;
end;
procedure
TForm1. Button3Click (Sender: TObject);
begin
end;
procedure
TForm1. Button4Click (Sender: TObject);
begin
glPolygonMode
(GL_FRONT_AND_BACK, GL_FILL);
end;
procedure
TForm1. Button5Click (Sender: TObject);
begin
Human.
Rotation.zx:=Human. Rotation.zx+0.2;
end;
procedure
TForm1. Button6Click (Sender: TObject);
begin
Human.
Rotation.zx:=Human. Rotation.zx-0.2;
end;
procedure
TForm1. FormCreate (Sender: TObject);
begin
vis:=0;
initmas;
DC:=GetDC(Handle);
SetDCPixelFormat;
HRC:=wglCreateContext(DC);
wglMakeCurrent
(DC, HRC);
glViewport
(0, 0, ClientWidth-Panel1. Width, ClientHeight);
glClearColor
(0,0,0,0);
glEnable
(GL_DEPTH_TEST);
glMatrixMode
(GL_PROJECTION);
glLoadIdentity;
gluPerspective
(30.0, ClientWidth / ClientHeight, 0.1, 1000.0);
glMatrixMode
(GL_MODELVIEW);
glLoadIdentity;
glEnable
(GL_TEXTURE_2D); // Enable Texture Mapping
LoadTexture
('texture.bmp', MyTextureTex, FALSE);
with
Human do
begin
with
Position do
begin
x:=6.4;
y:=0;
z:=-0.3878;
end;
with
Rotation do
begin
y:=91;
zx:=10;
end;
end;
end;
procedure
TForm1. FormDestroy (Sender: TObject);
begin
wglMakeCurrent
(0,0);
wglDeleteContext(HRC);
ReleaseDC
(Handle, DC);
DeleteDC(DC);
end;
procedure
TForm1. Timer1Timer (Sender: TObject);
begin
InvalidateRect
(Handle, nil, false);
end;
procedure
TForm1. TrackBar1Change (Sender: TObject);
begin
Label2.
Caption:=floattostr (TrackBar1. Position);
vis:=TrackBar1.
Position;
end;
procedure
TForm1. FormResize (Sender: TObject);
begin
glViewport
(0, 0, ClientWidth-Panel1. Width, ClientHeight);
glMatrixMode
(GL_PROJECTION);
glLoadIdentity;
gluPerspective
(30.0, ClientWidth / ClientHeight, 0.1, 1000.0);
glMatrixMode
(GL_MODELVIEW);
glLoadIdentity;
procedure
TForm1. FormPaint (Sender: TObject);
var
ps:TPaintStruct;
Const
LPos:
Array [0..3] of GLFloat = (3.0, 10, -100.0, 1.0);
begin
BeginPaint
(Handle, ps);
glClear
(GL_COLOR_BUFFER_BIT or
GL_DEPTH_BUFFER_BIT);
glLoadIdentity;
glRotatef
(Human. Rotation.zx, Abs (cos(DegToRad (Human. Rotation.y))), 0,0);
glRotatef
(Human. Rotation.y, 0,1,0);
glTranslatef
(Human. Position.x,
Human.
Position.y,
Human.
Position.z);
Draw;
EndPaint
(Handle, ps);
SwapBuffers(DC);
end;
procedure
TForm1. FormMouseDown (Sender: TObject; Button: TMouseButton;
Shift:
TShiftState; X, Y: Integer);
begin
changemas;
end;
procedure
TForm1. FormMouseMove (Sender: TObject; Shift: TShiftState; X,
Y:
Integer);
begin
GetCoordinate
(x, y);
end;
end.