Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка OpenGL.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
504.83 Кб
Скачать

Хід роботи

Реалізація алгоритму середньої точки для кола. Значення радіуса кола і координат її центра повідомляються процедурі circleMidpoint. Після цього обчислюються координати пікселів на колі в першому октанті, які відправляються процедурі circlePlotPoints. Ця процедура задає у буфері кадру колір кола для всіх симетричних точок на колі за допомогою багатократного виклику процедури setPixel, яка реалізована за допомогою функцій зображення точок.

#include <GL/glut.h>

class screenPt {

private:

GLint x,y;

public:

/* Ініціалізація за замовчанням з координатами (0, 0). */ screenPt ( ) {

х = у = 0;

}

void setCoords (GLint xCoordValue, GLint yCoordValue) {

x = xCoordValue;

y = yCoordValue;

}

GLint getx ( ) const {

return x;

}

GLint gety ( ) const {

return y;

}

void incrementx ( ) {

x++;

}

void decrementy ( ) {

y--;

}

};

void init (void){

glClearColor (1.0, 1.0, 1.0, 1.0);

glMatrixMode (GL_PROJECTION);

gluOrtho2D (0.0, 200.0, 0.0, 150.0);

}

void setPixel (GLint xCoord, GLint yCoord) {

glBegin (GL_POINTS);

glVertex2i (xCoord, yCoord);

glEnd ( );

}

void circleMidpoint (GLint xc, GLint yc, GLint radius) {

screenPt circPt;

GLint p = 1 - radius;

/* Початкове значення параметра (метод середньої точки).*/

circPt.setCoords (0, radius);

/* Задаються координати верхньої точки кола.*/

void circlePlotPoints (GLint, GLint, screenPt);

/* У кожному квадранті зображається перша точка. */ circlePlotPoints (xc, yc, circPt);

/* Обчислюються і зображаються точки у всіх октантах.*/ while (circPt.getx ( ) < circPt.gety ( )) {

circPt.incrementx ( );

if (p < 0)

p += 2 * circPt.getx ( ) + 1;

else {

circPt.decrementy ( );

p += 2 * (circPt.getx ( ) - circPt.gety ( )) + 1;

}

circlePlotPoints (xc, yc, circPt);

}

}

void circlePlotPoints(GLint xc,GLint yc,screenPt circPt)

{

setPixel (xc + circPt.getx(),yc + circPt.gety());

setPixel (xc - circPt.getx(),yc + circPt.gety());

setPixel (xc + circPt.getx(),yc - circPt.gety());

setPixel (xc - circPt.getx(),yc - circPt.gety());

setPixel (xc + circPt.gety(),yc + circPt.getx());

setPixel (xc - circPt.gety(),yc + circPt.getx());

setPixel (xc + circPt.gety(),yc - circPt.getx());

setPixel (xc - circPt.gety(),yc - circPt.getx());

}

У наступному фрагменті коду наведені приклади процедур, необхідних для виконання алгоритму середньої точки для еліпса. Значення параметрів еліпса Rx, Ry, xCenter і yCenter вводяться у процедурі ellipseMidpoint. Потім координати точок кривої в першому квадранті обчислюються і повідомляються процедурі ellipsePlotPoints. Для того щоб знайти координати пікселів у решті трьох квадрантів, використовуються умови симетрії, а стандартна процедура setPixel задає колір еліпса у позиціях буфера кадру, відповідних цим точкам.

inline int round (const float a)

{ return int (a + 0.5);}

/*Наступна процедура приймає значення координат центра *еліпса, його великої та малої півосей, а потім за *допомогою алгоритму середньої точки знаходить координати *точок еліпса. */

void ellipseMidpoint (int xCenter,int yCenter,int Rx,int Ry)

{

int Rx2 = Rx * Rx;

int Ry2 = Ry * Ry;

int twoRx2 = 2 * Rx2;

int twoRy2 = 2 * Ry2;

int p;

int x = 0;

int у = Ry;

int px = 0;

int py = twoRx2 * y;

void ellipsePlotPoints (int, int, int, int);

/*У кожному квадранті зображується перша точка. */ ellipsePlotPoints (xCenter, yCenter, x, y);

/* Область 1 */

р = round (Ry2 -(Rx2 * Ry) + (0.25 * Rx2));

while (px < py) {

х++;

px += twoRy2;

if (p < 0)

р += Ry2 + px;

else {

y--;

py -= twoRx2;

р += Ry2 + px - рy;}

ellipsePlotPoints (xCenter, yCenter, x, y); }

/* Область 2 */

p = round (Ry2 * (x+0.5) * (x+0.5) + Rx2 * (y-1) * (y-1) - Rx2 * Ry2);

while (y > 0) {

y--;

py -= twoRx2;

if (p > 0)

p += Rx2 - py;

else {

x++;

px += twoRy2;

p += Rx2 - py + px;

}

ellipsePlotPoints (xCenter, yCenter, x, y); }

}

void ellipsePlotPoints (int xCenter, int yCenter, int x, int y);

{

setPixel (xCenter + x, yCenter + y);

setPixel (xCenter - x, yCenter + y);

setPixel (xCenter + x, yCenter - y);

setPixel (xCenter - x, yCenter - y);

}

Завдання

  1. Вивчити теоретичний матеріал щодо теми лабораторної роботи.

  2. Відповісти на контрольні запитання.

  3. Розглянути|розглядуватимете| роботу кожного прикладу|зразка| програми.

  4. Побудувати на площині коло та еліпс, призначивши колір пікселя та використовуючи наведені заготовки фрагментів програм.

Контрольні питання|

  1. Які методи використовуються для побудови кола та еліпса|?

  2. Наведіть алгоритм, за яким будується коло.

  3. Що таке поточне растрове положення?

  4. Для чого призначена функція бітового зображення, як вона записується?

  5. За допомогою якої функції встановлюється поточне растрове положення?

Література: [8–10].

Лабораторна робота № 6

Тема. Криві та поверхні

Мета роботи: ознайомитися з прийомами апроксимації кривих на прикладі поліномів та сплайнів, використавши опис вершин та примітивів, а також масиви вершин.

Короткі теоретичні відомості

Конічний переріз можна описати за допомогою рівняння другого порядку:

Ax2 + By2 + Cxy + Dx + Ey + F = 0,

де значення параметрів А, В, С, D, Е і F визначають тип кривої, що зображується. Якщо цей набір коефіцієнтів відомий, тоді вид конічного перерізу, який вийде з цього рівняння, можна визначити на основі дискримінанту В2 - 4АС:

Поліноміальна функція n-го порядку по х визначається як

,

де п – від’ємне ціле число, аk – константи, ап 0. При п = 1 отримаємо пряму лінію, при п = 2 – криву другого порядку, при п = 3 – кубічний поліном, при п = 4 – криву четвертого порядку і т. д. Поліноми використовуються при проектуванні форми предметів, коли описують траєкторії в анімації, будують графіки даних.

При проектуванні форми предмета або траєкторії руху, як правило, спочатку задається декілька точок, які визначають загальний вигляд кривої та є необхідним контуром, а потім за вибраними точками підбирається відповідний поліном. Один зі способів підбору кривої – це з'єднати кожну пару заданих точок кубічною частиною кривої. Кожна така частина описується в параметричній формі:

де параметр і набуває значень від 0 до 1. Значення коефіцієнтів і в попередніх рівняннях визначаються з граничних умов для частин кривої. Одна з граничних умов полягає у тому, що кінець однієї частини кривої збігається з початком наступної, а друга умова – це збіг тангенсів кута нахилу двох кривих на спільній межі, таким чином, у результаті виходить безперервна гладка крива. Безперервні криві, які утворені з поліноміальних фрагментів, називаються онлайновими кривими або просто сплайнами.

Коли описують елементи рисунка, використовується ще одна конструкція – область, яка зафарбована одним кольором або заповнена певним узором. Такі елементи рисунка зазвичай називають кольоровими фігурами або зафарбованими областями. Як правило, вони є плоскими поверхнями, головним чином, багатокутниками.

Терміном вироджений багатокутник часто описують набір вершин, які є колінеарними або координати яких повторюються. Продовження деяких сторін увігнутого багатокутника перетинатимуть інші ребра, а деякі пари внутрішніх точок дають відрізки, що перетинають межі багатокутника. Будь-яку з цих ознак увігнутого багатокутника можна покласти в основу алгоритму розпізнавання увігнутих багатокутників. Увігнутий багатокутник можна розділити на декілька опуклих багатокутників за допомогою векторів сторін та їх векторного добутку або, використовуючи місцезнаходження вершин щодо лінії продовження однієї зі сторін, та визначити з якої сторони від цієї лінії знаходяться вершини.

Для реалізації векторного методу розділення увігнутого багатокутника, спочатку необхідно побудувати вектори сторін. Якщо відомі координати двох сусідніх вершин Vk і Vk+1, тоді вектор між ними визначається таким чином:

.

Потім потрібно знайти векторні добутки сусідніх векторів сторін на всьому периметрі багатокутника. Якщо компонент z одних векторних добутків буде додатним, а інших – від’ємними, тоді багатокутник є увігнутим.

Найчастіше об'єкти сцени описують як набори багатокутних граней поверхонь. Графічні пакети пропонують функції визначення форми поверхні у вигляді сітки багатокутних частин. Щоб описати кожний об'єкт, необхідно включити інформацію про координати, за допомогою яких задається геометрія багатокутних граней та інші параметри поверхні, такі як колір, прозорість і властивості.

Геометричну інформацію про об'єкти сцени зручно розподілити за трьома списками: таблиці вершин, таблиці сторін і таблиці граней. Координати всіх вершин об'єкта записуються до таблиці вершин. У таблиці сторін містяться посилання на таблицю вершин, що дозволяють визначити вершини, які належать кожній стороні багатокутника. У таблиці граней поверхні містяться посилання на таблицю сторін, що визначають межі кожного багатокутника.

До додаткової геометричної інформації, яка зазвичай зберігається в інформаційних таблицях, належить тангенс кута нахилу кожної сторони і координатні межі сторін багатокутників, багатокутних граней і кожного об'єкта сцени в цілому.

При створенні зображення тривимірної сцени графічна система обробляє вхідні дані за допомогою декількох процедур. До цих процедур належать: перетворення координат моделювання і зовнішніх координат при проходженні конвеєра спостереження (viewing pipeline), визначення видимих поверхонь, застосування стандартних процедур візуалізації до окремих граней поверхонь. Деяким з цих процедур необхідна інформація про просторову орієнтацію елементів поверхонь. Цю інформацію можна отримати з координат вершин і рівнянь, що описують багатокутні поверхні.

Оскільки зазвичай багатокутні поверхні, з якими доводиться мати справу в графічних додатках, є зовнішньою оболонкою об'єкта, необхідно розрізняти дві сторони кожної поверхні. Та сторона багатокутника, яка направлена всередину об'єкта, називається задньою, а видима, або зовнішня, сторона є передньою. Визначення положення точок у просторі щодо передньої та задньої сторін багатокутника є основним завданням багатьох графічних алгоритмів, наприклад, алгоритму визначення видимих частин об'єкта. Кожен багатокутник розташовано в нескінченній площині, що розділяє простір на дві частини. Будь-яка точка, що не належить цій площині, яку видно з лицьового боку поверхні багатокутника, знаходиться перед площиною (або зовні), отже, за межами об'єкта. Будь-яка точка, яку видно зі зворотного боку багатокутника, знаходиться за площиною (або всередині). Точка, яка знаходиться за всіма площинами поверхонь багатокутника, знаходиться всередині об'єкта. Класифікація "усередині-зовні" проводиться щодо площини, що містить багатокутник.

У пакеті OPENGL заповнена область повинна задаватися у вигляді опуклого багатокутника. Таким чином, список вершин для зафарбованого багатокутника повинен містити щонайменше три вершини та в ньому не повинно бути пересічних сторін, а всі внутрішні кути багатокутника повинні бути менше 180°. Зафарбована область у вигляді одного багатокутника може задаватися за допомогою одного списку вершин, і в цьому випадку неможливі конфігурації, що містять отвори у внутрішній області багатокутника.

У пакеті OPENGL колір заповнення й інші параметри можна задавати для кожної сторони окремо, визначення передньої (задньої) сторони необхідне як у двох, так і в тривимірних стандартних процедурах візуалізації. Вершини багатокутника повинні задаватися в напрямку проти годинникової стрілки, якщо дивитися на багатокутник "ззовні", таким чином визначається передня сторона цього багатокутника.

У деяких версіях OPENGL процедура glVertex може виявитися ефективнішою, ніж побудова зафарбованого прямокутника за допомогою функції.

glRect* (xl, yl, x2, y2);

Один кут цього прямокутника знаходиться в точці з координатами (x1, y1), а протилежний кут прямокутника – у точці з координатами 2, y2). Індекси функції glRect позначають тип даних – i (для цілих чисел), s (для коротких цілих чисел), f (для чисел з плаваючою комою), d (для чисел подвійної точності) і v (для векторів). Прямокутник зображується таким чином, що його сторони паралельні координатним осям площини ху. Приклад функції, яка зображує квадрат.

glRecti (200, 100, 50, 250);

Якщо задавати значення координат цього прямокутника у вигляді масиву даних, той самий квадрат можна отримати за допомогою наступного коду.

int vertexl [ ] = {200, 100};

int vertex2 [ ] = {50, 250};

Решта шести примітивів зафарбованих багатокутників у пакеті OPENGL задається за допомогою символьної константи у функції glBegin разом зі списком команд glVertex. За допомогою константи OPENGL GL_POLYGON можна отримати зображення одного зафарбованого багатокутника glRectiv (vertexl, vertex2);