Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Системы автоматизированного проектирования. Моделирование в машиностроении. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
08.09.2026
Размер:
2 Мб
Скачать
☆
if mass[j]>=mass2[j] then begin glVertex3d(j/10,i/10,mass[j]/10); mass3[j]:=mass[j]; end else begin glVertex3d(j/10,i/10,mass2[j]/10); mass3[j]:=mass2[j]; end; end; glEnd(); end; for i:=0 to 10 do begin glBegin(GL_LINE_STRIP); glVertex3d(i/10,0,mass3[i]/10); glVertex3d(i/10,0.9,mass3[i]/10); glEnd(); end; glPopMatrix; SwapBuffers (Canvas.Handle); end;
procedure TForm1.FormDestroy(Sender: TObject); begin wglMakeCurrent(0, 0); wglDeleteContext(hrc); ReleaseDC (Handle, DC); DeleteDC (DC); end;
В обработчик события закрытия формы OnDestroy в Object Inspector во вкладке Events прописать следующий код:
Пример выполненной программы представлен на рисунке 5.24.
81
Рисунок 5.24 – Экранная форма запущенного приложения
5.6.4 Задание на выполнение работы
Проверить работу программного кода и выполнить изменения в нем, по указанию преподавателя.
Содержание отчета:
– название работы;
– цель работы;
– перечень используемых команд;
– экранные формы;
– листинг программы.
5.6.5 Контрольные вопросы
Что собой представляет поверхность Кунса?
Как построить поверхность Кунса?
Основные этапы построения поверхности Кунса?
Как осуществляется расчет поверхности?
82
5.7 Применение булевых операций для построения сложных
объектов
5.7.1 Цель работы
Целью работы является приобретение навыков применения булевых операции при построении сложных объектов, используя функции графиче­ской библиотеки OpenGL.
5.7.2 Понятие и виды булевых операций
Как и для многих терминов компьютерной графики, термин «булева» происходит от имени человека, который ввел это понятие (в данном случае это Джордж Буль). Булевыми операциями называют операции объединения, пересечения и вычитания тел, так как они выполняют одноименные операции
над внутренними объемами тел.
Булеву операцию объединения тел будем обозначать формулой:     , где А и В - исходные тела, Р - результирующее тело. Булеву операцию пересечения тел будем обозначать формулой:     . Булеву операцию вычитания тел будем обозначать формулой:     . Результатом опера­ции объединения двух тел является тело, которое содержит точки, принадле­жащие внутреннему объему или первого, или второго тела. Результатом опе­рации пересечения двух тел является тело, которое содержит точки, принад­лежащие внутреннему объему как первого, так и второго тела. Результатом операции вычитания двух тел является тело, которое содержит точки, при­надлежащие внутреннему объему первого, но не принадлежащие внутренне­му объему второго тела.
Рассмотрим булеву операцию объединения тел. Кратко суть операции молено описать следующим образом: нужно найти линии пересечения граней тел, удалить ту часть первого тела, которая попала внутрь второго тела и ту часть второго тела, которая попала внутрь первого тела, а из всего остально-
го построить новое тело.
Операцию условно можно разбить на три этапа. На первом этапе стро-
ятся линии пересечения поверхностей граней и на их базе — новые ребра.
Построенные новые ребра будем называть ребрами пересечения, а ребра тел будут называться старыми ребрами. На втором этапе определяем точки пере­сечения новых ребер со старыми ребрами и в этих точках разрежем старые ребра на несколько ребер. На третьем папе операции перестроим циклы пе­ресекшихся граней. После этого добавим к пересекшимся граням тел грани,
типологически связанные ними.
На рисунке 5.25 показан результат операции объединения сферы и куба.
83
Рисунок 5.25 – Результат операции объединения
Суть булевой операции пересечения тел можно описать следующим образом: нужно найти линии пересечения тел, удалить ту часть первого тела, которая не попала внутрь второго, и ту часть второго тела, которая не попала
внутрь первого, а из всего остального построить новое тело.
Операцию разобьем на три этапа. Первый и второй этапы операции пе­ресечения тел полностью совпадают с соответствующими этапами операции объединения тел. Третий этап операции пересечения тол выполняется анало­гично третьему этапу операции объединения тел, но имеет одно отличие в том, с каким флагом входят в циклы ребра пересечения. Ребра пересечения входят в перестроенные циклы граней первого тола с положительным фла-
гом, а в перестроенные циклы граней второго тела — с отрицательным фла-
гом (в объединении тел флаги ребер пересечения в циклах имеют противопо­ложное значение). Все остальные действия над гранями обоих тел в обеих
операциях одинаковы. На рисунке 5.26 изображен результат операции пере-
сечения сферы и куба.
84
Рисунок 5.26 – Результат операции пересечения
Суть булевой операции вычитания тел можно описать следующим об­разом: нужно найти линии пересечения тел, удалить ту часть первого тела, которая попала внутрь второго, и ту часть второго тела, которая не попала
внутрь первого, а из всего остального построить новое тело.
Булева операция вычитания тел сводится к булевой операции пересе­чения уменьшаемого тела и вывернутого наизнанку вычитаемого тела. Вы­вернутое наизнанку тело мы получим из исходного тела путем переориента­ции направлений нормалей граней и направлений циклов граней. Переориен­тация направления нормали грани производится изменением признака совпа­дения нормали поверхности и нормали ее грани. Переориентация направле­ния цикла грани производится перестроением списка ребер (изменением на обратный порядок следования ребер в списке) и заменой на противополож-
ные ребра в списках. Для вывернутого тела внутренним объемом является
часть пространства, находящаяся вне его оболочки. Поэтому при пересече­нии уменьшаемого тела и вывернутого наизнанку вычитаемого тела резуль­тирующая оболочка будет содержать ту часть объема уменьшаемого тела,
которая лежит вне вычитаемого тела. На рисунке 5.27 приведен результат
операции разности тел. В верхней части рисунка показан результат вычита-
ния куба из сферы, а в нижней - сферы из куба.
85
Рисунок 5.27 – Результат операции вычитания: сверху – вычитание куба
из сферы, снизу – сферы из куба
5.7.3 Ход работы
Для реализации булевых операций в OpenGl используется буфер тра-
фарета. Выполнение теста трафарета разрешается командой glEnable с аргу­ментом GL_STENCIL_TEST. Команда glStencilFunc отвечает за сравнение, а команда glStencilop позволяет определить действия, базирующиеся на ре-
зультате проверки трафарета. Программа демонстрирует, как использовать буфер трафарета для реализации логических операций с твердыми телами. Рисование фигур вынесено в отдельные процедуры, для манипуляций с ними
введены еще две процедуры.
По конструкции, программа демонстрирующая работу буфера трафаре­та, а соответственно и булевы операции, будет довольна проста. Состоять она
будет из одного RadioGroup, в котором будут отображаться названия буле­вых операций, RadioGroup в котором пользователь сможет выбрать вокруг какой оси вращать сцену и двух «кнопок» BitBtn, с помощью которых предо-
86
ставляется выбор направления вращения получившейся в результате булевой
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, OpenGL, StdCtrls;
private
{ Private declarations }
DC : HDC; hrc: HGLRC; ry : GLfloat;
implementation uses DGLUT;
{$R *.DFM}
type proctype = procedure;
операции фигуры. Рассмотрим структуру приложения более подробно.
Создайте в среде программирования Delphi новый проект. Переместите
в каталог с программой файл DGLUT.pas.
В разделе uses программы подключаем библиотеку OpenGL:
В разделе private инициализировать следующие переменные и проце­дуры:
Подключаем библиотеку DGLUT и введем процедурный тип:
Добавим на форму компонент RadioGroup. Активировав свойство Cap- tion в Object Inspector, впишем «Выберете операцию». Затем активируем свойство Items и впишем 4 строки, содержание которых соответствует назва­ниям операций (рисунок 28). Свойству Columns присвоим значение 4 (задаем количество столбцов RadioGroup, это необходимо чтобы переключатели рас­полагались горизонтально).
Добавим на форму еще один компонент RadioGroup. В свойстве Caption впишем «Вращать вокруг оси». В Items вписываем X, Y, Z в отдель­ных строках.
Добавить на форму два компонента BitBtn взятых с вкладки Additional, выбрать для них желаемые пиктограммы активировав свойство Glyph в Ob- ject Inspector и инициализировать события OnClick двойным щелчком мыши по данным компонентам, после чего вписать код:
87
procedure TForm1.BitBtn1Click(Sender: TObject); begin ry:=ry-5.0; // Вращаем сцену по часовой стрелке end;
procedure TForm1.BitBtn2Click(Sender: TObject); begin ry:=ry+5.0; // Вращаем сцену против часовой стре лки end;
Пример получившейся формы представлен на рисунке 5.28.
Рисунок 5.28 – Экранная форма создаваемого приложения
88
Зададим формат пиксела:
procedure TForm1.SetDCPixelFormat; var nPixelFormat: Integer; pfd: TPixelFormatDescriptor; begin FillChar(pfd, SizeOf(pfd), 0); pfd.dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER; // множество битовых флагов,определяющих
устройство и интерфейс
nPixelFormat := ChoosePixelFormat(DC, @pfd); // устанавливаем формат пик-
селей в контексте устройства
SetPixelFormat(DC, nPixelFormat, @pfd); end;
procedure TForm1.FormCreate(Sender: TObject); const lightposition : Array [0..3] of GLfloat = ( -3.0, 3.0, 3.0, 0.0 ); begin DC := GetDC (Handle); SetDCPixelFormat(DC); hrc := wglCreateContext(DC); wglMakeCurrent(DC, hrc); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHT0); glEnable(GL_LIGHTING); glLightfv(GL_LIGHT0, GL_POSITION, @lightposition); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); glEnable(GL_COLOR_MATERIAL); glEnable(GL_CULL_FACE); glClearColor(1.0, 1.0, 1.0, 0.0); ry:=0.0; end;
Перейдите к конструктору и сделайте двойной щелчок клавишей мыши на форме – создастся функция обработчика события загрузки формы FormCreate. В ней мы поместим следующий код:
OnResize. Для этого необходимо в Object Inspector перейти на вкладку Events,
где щелкнуть по вышеперечисленным событиям два раза.
Инициализировать обработчики событий OnDestroy, OnPaint,
В обработчики событий добавить следующий код:
89
OnDestroy:
procedure TForm1.FormDestroy(Sender: TObject); begin wglMakeCurrent(0, 0); wglDeleteContext(hrc); ReleaseDC(Handle, DC); DeleteDC (DC); end;
procedure TForm1.FormPaint(Sender: TObject); var x,y,z: single; begin glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT or
GL_STENCIL_BUFFER_BIT); // очистка буфера цвета
glPushMatrix; x:=0.0; y:=0.0; z:=0.0; if radiobutton1.Checked then x:=1.0; if radiobutton2.Checked then y:=1.0; if radiobutton3.Checked then z:=1.0; glRotatef (ry, x, y, z); glTranslatef (0.0, 0.0, 0.0); //Объединение А и В if RadioGroup1.ItemIndex=0 then begin glPushAttrib(GL_ALL_ATTRIB_BITS); glEnable(GL_DEPTH_TEST); B; A; glPopAttrib; end; //Вычитание А-В if RadioGroup1.ItemIndex=1 then begin inside(A, B, GL_FRONT, GL_NOTEQUAL); fixup(B); inside(B, A, GL_BACK, GL_EQUAL); end; //Пересечение А и В if RadioGroup1.ItemIndex=2 then
OnPaint:
90
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]