Лабораторная работа №9 Цель работы: Разработать форму и

advertisement
Лабораторная работа №9
Цель работы: Разработать форму и интерфейс приложения, реализовать
алгоритмы решения задачи, проверить правильность работы программы.
“Работа с OpenGL”.
Используя листинг программы, показывающей работу с OpenGL на примере
вращающегося куба (куб также можно вращать в разные стороны (меню вызывается
нажатием правой кнопкой мыши на форме; клавиши управления - 'x','y','z','X','Y','Z'), а
также задавать скорость вращения) . Необходимо изменить тип фигуры на фигуры
рис. 1, 2, 6, 9.
Загрузить .exe
файл
Стереометрия — раздел геометрии, в котором изучаются свойства фигур в
пространстве (пространственных фигур). Слово «стереометрия» состоит из
греческих слов «стереос» — телесный, пространственный и «метрео» — измеряю.
Не нужно путать этот раздел с планиметрией, поскольку в планиметрии
изучаются свойства фигур на плоскости (т.е. свойства плоских фигур), а в
стереометрии – свойства фигур в пространстве (т.е. свойства пространственных
фигур).
Для лучшего понимания напомним некоторые сведения о многогранниках и
дадим каждому многограннику наглядное описание.
Многогранник представляет собой
тело, поверхность которого состоит
из конечного числа плоских
многоугольников (рис. 1–10). Эти
многоугольники называются гранями
многогранника, а стороны и вершины
многоугольников называются соответственно ребрами и
вершинами многогранника. Многогранники могут быть
выпуклыми (рис. 1) и невыпуклыми (рис. 2).
Выпуклый многогранник расположен по одну сторону относительно
плоскости, проходящей через любую его грань . (Мы будем изучать только
выпуклые многогранники.)
Приведем примеры отдельных многогранников.
Куб представляет
собой многогранник, у
которого шесть
граней, и все они —
равные квадраты. У
куба 12 равных ребер
и 8 вершин (рис. 3).
Параллелепипед
представляет собой многогранник, у которого шесть граней, и каждая из них —
параллелограмм. Параллелепипед может быть прямым (рис. 4) или наклонным
(рис. 5).
Параллелепипед, все грани которого прямоугольники,
называют прямоугольным. Прямоугольный параллелепипед
изображается также, как и прямой. Из сказанного следует,
что куб — это прямоугольный параллелепипед с равными
ребрами.
n-угольная пирамида представляет собой многогранник,
одна грань которого, называемая основанием пирамиды, —
некоторый выпуклый n-угольник, а остальные n граней —
треугольники с общей вершиной (рис. 6). Эта общая вершина называется
вершиной пирамиды, а треугольники — боковыми гранями пирамиды. Отрезки,
соединяющие вершину пирамиды с вершинами ее основания, называются
боковыми ребрами пирамиды.
Пирамида, в основании которой лежит правильный n-угольник, а боковые
ребра равны между собой, называется правильной пирамидой (рис. 7).
Пирамида, в основании
которой лежит треугольник, называется
треугольной пирамидой или тетраэдром.
Таким образом, тетраэдр — это
четырехгранник. Все его четыре
грани — треугольники. Тетраэдр, все
четыре грани которого — равные
правильные треугольники, называется
правильным тетраэдром (рис. 8). Правильный тетраэдр — это частный случай
правильной треугольной пирамиды .
n-угольная призма представляет собой
многогранник, две грани которого, называемые
основаниями призмы, — равные n-угольники, а
все остальные n граней — параллелограммы.
Они называются боковыми гранями призмы.
Призма может быть прямой (рис. 9) или
наклонной (рис. 10). У прямой призмы все
боковые грани — прямоугольники, у наклонной призмы хотя бы
одна грань — параллелограмм, не являющийся
прямоугольником.
Параллелепипед — это призма, в основании которой лежит параллелограмм.
Эта общая вершина называется вершиной пирамиды, а треугольники —
боковыми гранями пирамиды. Отрезки, соединяющие вершину пирамиды с
вершинами ее основания, называются боковыми ребрами пирамиды. Пирамида, в
основании которой лежит правильный n-угольник, а боковые ребра равны между
собой, называется
Листинг программы "Вращающийся куб".
unit mgl;
interface
uses
Windows, Messages, Classes, Graphics, Forms, ExtCtrls, OpenGL, StdCtrls,
Controls, SysUtils, Spin, Menus, Dialogs;
type
TForm1 = class(TForm)
Timer1: TTimer;
PopupMenu1: TPopupMenu;
Rotatespeed1: TMenuItem;
x1: TMenuItem;
y1: TMenuItem;
z1: TMenuItem;
X2: TMenuItem;
Y2: TMenuItem;
Z2: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure Rotatespeed1Click(Sender: TObject);
procedure x1Click(Sender: TObject);
procedure y1Click(Sender: TObject);
procedure z1Click(Sender: TObject);
procedure Z2Click(Sender: TObject);
procedure X2Click(Sender: TObject);
procedure Y2Click(Sender: TObject);
private
DC : HDC;
hrc : HGLRC;
Angle, AngleX, AngleY, AngleZ: GLfloat;
procedure DrawScene;
procedure InitializeRC;
procedure SetDCPixelFormat;
protected
Обработка сообщения WM_PAINT - аналог события OnPaint
procedure WMPaint(var Msg: TWMPaint); message WM_PAINT;
end;
var
Form1: TForm;
ch, c, i: integer;
s: string;
ShowHelp: boolean=true;
implementation
const
массив свойств материала
MaterialColor: Array [0..3] of GLfloat = (0.5, 0.0, 1.0, 1.0);
Процедура инициализации источника цвета
procedure TForm1.InitializeRC;
begin
glEnable(GL_DEPTH_TEST); // разрешаем тест глубины
glEnable(GL_LIGHTING); // разрешаем работу с освещенностью
glEnable(GL_LIGHT0); // включаем источник света 0
end;
Отрисовка картинки
procedure TForm1.DrawScene;
begin
очистка буфера цвета и буфера глубины
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
трехмерность
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
glTranslatef(0.0, 0.0, -8.0); влево/вправо, вверх/вниз, назад/вперед
glRotatef(AngleX, 1.0, 0.0, 0.0); поворот на угол X
glRotatef(AngleY, 0.0, 1.0, 0.0); поворот на угол Y
glRotatef(AngleZ, 0.0, 0.0, 1.0); поворот на угол Z
Шесть сторон куба
glBegin(GL_POLYGON);
glNormal3f(0.0, 0.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glEnd;
glBegin(GL_POLYGON);
glNormal3f(0.0, 0.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(-1.0, 1.0, -1.0);
glEnd;
glBegin(GL_POLYGON);
glNormal3f(-1.0, 0.0, 0.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(-1.0, -1.0, 1.0);
glEnd;
glBegin(GL_POLYGON);
glNormal3f(1.0, 0.0, 0.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(1.0, -1.0, 1.0);
glVertex3f(1.0, -1.0, -1.0);
glVertex3f(1.0, 1.0, -1.0);
glEnd;
glBegin(GL_POLYGON);
glNormal3f(0.0, 1.0, 0.0);
glVertex3f(-1.0, 1.0, -1.0);
glVertex3f(-1.0, 1.0, 1.0);
glVertex3f(1.0, 1.0, 1.0);
glVertex3f(1.0, 1.0, -1.0);
glEnd;
glBegin(GL_POLYGON);
glNormal3f(0.0, -1.0, 0.0);
glVertex3f(-1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, -1.0);
glVertex3f(1.0, -1.0, 1.0);
glVertex3f(-1.0, -1.0, 1.0);
glEnd;
SwapBuffers(DC); конец работы
end;
Обработка таймера
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Angle:=Angle+1.0;
if (Angle>=90.0)
then Angle:=0.0;
Application.ProcessMessages;
InvalidateRect(Handle, nil, False); перерисовка региона (Windows API)
end;
Дальше идут обычные для OpenGL действия, Создание окна
procedure TForm1.FormCreate(Sender: TObject);
begin
Form1.PopupMenu:=PopupMenu1;
Angle:=0;
AngleX:=30;
AngleY:=0;
AngleZ:=0;
c:=1;
DC:=GetDC(Handle);
SetDCPixelFormat;
hrc:=wglCreateContext(DC);
wglMakeCurrent(DC, hrc);
InitializeRC;
Определяем свойства материала - лицевые стороны - рассеянный
цвет материала и диффузное отражение материала - значения из массива
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, @MaterialColor);
end;
Установка формата пикселей
procedure TForm1.SetDCPixelFormat;
var
nPixelFormat: integer;
pfd: TPixelFormatDescriptor;
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:=24; // 24
cDepthBits:=32; // 32
iLayerType:= PFD_MAIN_PLANE;
end;
nPixelFormat := ChoosePixelFormat(DC, @pfd);
SetPixelFormat(DC, nPixelFormat, @pfd);
end;
Изменение размеров окна
procedure TForm1.FormResize(Sender: TObject);
begin
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(30.0, Width/Height, 1.0, 10.0);
glViewport(0, 0, Width, Height);
glMatrixMode(GL_MODELVIEW);
InvalidateRect(Handle, nil, False);
end;
Обработка сообщения WM_PAINT, рисование окна
procedure TForm1.WMPaint(var Msg: TWMPaint);
var
ps: TPaintStruct;
begin
BeginPaint(Handle, ps);
DrawScene;
EndPaint(Handle, ps);
end;
Конец работы программы
procedure TForm1.FormDestroy(Sender: TObject);
begin
Timer1.Enabled:=False;
wglMakeCurrent(0, 0);
wglDeleteContext(hrc);
ReleaseDC(Handle, DC);
end;
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
if (key='x') then c:=1;
if (key='y') then c:=3;
if (key='z') then c:=5;
if (key='X') then c:=2;
if (key='Y') then c:=4;
if (key='Z') then c:=6;
if ord(key)=27 then Application.Terminate; // Esc
//
if key='h' then
begin
ShowHelp:=not(ShowHelp);
key:='g';
end;
//
FormResize(nil);
end;
procedure TForm1.Rotatespeed1Click(Sender: TObject);
begin
ch:=StrToInt(InputBox('Rotate','Sleep:','0'));
i:=1;
if Form1.CanFocus then Form1.SetFocus;
while i=1 do
case c of
1:
begin
AngleX:=AngleX-1.0;
if (AngleX>=90.0)
then AngleX:=0.0;
Sleep(ch);
if Application.Terminated then Break;
Application.ProcessMessages;
InvalidateRect(Handle, nil, False); перерисовка региона (Windows API)
end;
2:
begin
AngleX:=AngleX+1.0;
if (AngleX>=90.0)
then AngleX:=0.0;
Sleep(ch);
if Application.Terminated then Break;
Application.ProcessMessages;
InvalidateRect(Handle, nil, False); перерисовка региона (Windows API)
end;
3:
begin
AngleY:=AngleY-1.0;
if (AngleY>=90.0)
then AngleY:=0.0;
Sleep(ch);
if Application.Terminated then Break;
Application.ProcessMessages;
InvalidateRect(Handle, nil, False); перерисовка региона (Windows API)
end;
4:
begin
AngleY:=AngleY+1.0;
if (AngleY>=90.0)
then AngleY:=0.0;
Sleep(ch);
if Application.Terminated then Break;
Application.ProcessMessages;
InvalidateRect(Handle, nil, False); перерисовка региона (Windows API)
end;
5:
begin
AngleZ:=AngleZ-1.0;
if (AngleZ>=90.0)
then AngleZ:=0.0;
Sleep(ch);
if Application.Terminated then Break;
Application.ProcessMessages;
InvalidateRect(Handle, nil, False); перерисовка региона (Windows API)
end;
6:
begin
AngleZ:=AngleZ+1.0;
if (AngleZ>=90.0)
then AngleZ:=0.0;
Sleep(ch);
if Application.Terminated then Break;
Application.ProcessMessages;
InvalidateRect(Handle, nil, False); перерисовка региона (Windows API)
end;
end;
end;
procedure TForm1.x1Click(Sender: TObject);
begin
c:=2;
end;
procedure TForm1.y1Click(Sender: TObject);
begin
c:=1;
end;
procedure TForm1.z1Click(Sender: TObject);
begin
c:=3;
end;
procedure TForm1.Z2Click(Sender: TObject);
begin
c:=6;
end;
procedure TForm1.X2Click(Sender: TObject);
begin
c:=4;
end;
procedure TForm1.Y2Click(Sender: TObject);
begin
c:=5;
end;
end.
Download