Лабораторная работа №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.