на начало
На главную страницу
Форум   

Статья :: Как создать сферу

 

Как создать сферу

Для того чтобы из существующей заготовки — икосаэдра из двадцати граней — создать сферу, круглую, блестящую и без изъянов, нужно осуществить предельный переход, как в матанализе, бесконечно увеличивая число треугольников при бесконечном уменьшении их размеров. В дискретном мире нет места предельным переходам, поэтому вместо бесконечного деления надо ограничиться каким-то конечным числом и начать делить каждый из двадцати треугольников икосаэдра на все более мелкие правильные треугольники. Вычисление нормали при этом упрощается, так как при приближении к шару нормаль в каждой вершине треугольника приближается к нормали поверхности шара. А последняя равна нормированному вектору радиуса текущей точки. Алгоритм деления проиллюстрируем рисунком (рис. 6.3).

Рис. 6.3. Деление треугольника икосаэдра

Треугольник с вершинами VI, V2 и V3 разбивается на четыре треугольника: (V1,V12,V31), (V2,V23,V12), (V3,V32,V23) и (V12.V23.V31). После этого промежуточные точки деления надо посадить на поверхность шара, то есть изменить их координаты так, чтобы концы векторов (V12, V23 и V31) дотянулись до поверхности шара. Для этого достаточно нормировать векторы с помощью уже существующей процедуры Scale. Она впоследствии будет использована как для масштабирования нормали, так и для нормировки координат вершин новых треугольников. Но сейчас мы будем вычислять нормаль приближенно. Введем еще две вспомогательные функции:

//=== Команды OpenGL для изображения одного треугольника

void setTria(double *vl, double *v2, double *v3)

{

//====== Нормаль и вершина задаются одним вектором

glNormal3dv(vl);

glVertex3dv(vl);

glNormalSdv (v2);

glVertex3dv(v2);

glNormal3dv(v3);

glVertex3dv(v3);

glEnd() ;

}

//====== Генерация внутренних треугольников

void Split(double *vl, double *v2, double *v3)

{

//====== Промежуточные вершины

double v!2[3], v23[3], v31[3);

for (int l=0; l< 3; i++) {

//====== Можно не делить пополам,

//====== так как будем нормировать

v12[i] = vl[i]+v2[i];

v23[i] = v2[i]+v3[i];

v31 [i] = v3[i]+vl [i];

}

//====== Нормируем три новые вершины

Scale(v!2);

Scale(v23);

Scale(v31); //====== и рисуем четыре треугольника

setTria(vl, v!2, v31);

setTria (v2, v23, v!2);

setTria(v3, v31, v23);

setTria(v!2,v23, v31);

}

Вставьте эти глобальные функции в файл и дайте следующую версию функцию DrawScene, в которой отсутствует вызов функции getNorm для точного вычисления нормали, но есть вызов функции Split для каждой из 20 граней икосаэдра. В результате мы получаем фигуру из 80 треугольных граней, которая значительно ближе к сфере, чем икосаэдр:

void DrawScene()

{

static double

angle = 3. * atan(l.)/2.5, V = cos (angle), W = sin (angle),

v[12] [3] =

{-V,0.,W}, {V,0.,W}, {-V,.0.,-W},

(V,0.,-W), {0.,W,V}, {0.,W,-V},

(0.,-W,V), (0.,-W,-V), {W,V,0.},

{-W,V,0.}, {W,-V,0.}, {-W,-V,0.}

};

static GLuint id[20][3] =

{

(0,1, 4), (0,4, 9), {9,4, 5}, (4,8, 5), (4,1,8),

(8,1,10), (8,10,3), (5,8, 3), (5,3, 2), (2,3,7),

(7,3,10), (7,10,6), (7,6,11), (11,6,0), (0,6,1),

(6,10,1), (9,11,0), (9,2,11), (9,5, 2), (7,11,2)

};

glNewList(l,GL_COMPILE);

glColor3d (1., 0.4, 1.) ;

glBegin(GLJTRIANGLES);

for (int i = 0; i < 20; i++)

Split (v[id[i][0]], v[id[i][l]], v[id[i] [2] ]) ;

glEnd() ;

glEndList () ;

}

На этой стадии я рекомендую посмотреть, какие интересные и неожиданные результаты могут быть получены вследствие ошибок. Все мы ошибаемся, вот и я так долго возился с направлением обхода и со знаком нормали, что в промежуточных вариантах получал чудовищные комбинации. Многие из них «канули в Лету», но один любопытный вариант легко смоделировать. Если ошибки происходят в условиях симметричного отражения, то возникают ситуации, сходные со случайными изменениями узоров в калейдоскопе. Замените на обратные знаки компонентов вектора в функции Scale. Это действие в предыдущих версиях программы было эквивалентно изменению знака нормали. Найдите строку, похожую на ту, что приведена ниже, и замените знаки так, как показано, на минусы.

v[0] /= -d; v[l] /= -d; v[2] /= -d;

 

Как создать сферу

страницы в данном разделе 
Урок 6. Графика OpenGL Графика OpenGL
Обзор возможностей библиотеки OpenGL Подключаемые библиотеки
Ограничения Microsoft Примитивы OpenGL
OpenGL — автомат с конечным числом состояний Конвейер передачи OpenGL
Основные этапы Анимация
Другие функции OpenGL Контекст передачи изображения
Подготовка окна Создание консольного проекта
Штриховка линий Штриховка полигонов
Как убирать внутренние линии Перспективная проекция
Вносим свет Интерактивное управление положением и ориентацией
Двойная буферизация Использование списков
Интерполяция цвета Строим икосаэдр
Как создать сферу Выбор способа вычисления нормалей
Рекурсивное деление Массивы вершин, нормалей и цветов
Создание сферы >  


Содержание сайта (выборка)
Apache
Протоколы TCP/IP (принципы, протоколы и архитектура)



PHP, PELR, JSP
PHP
JavaServer Pages (JSP)

Базы данных
Основы mysql
СУБД INFORMIX
СУБД POSTGRES
Основы проектирования реляционных баз данных

HTML, javascript
Спецификация HTML 4.01
Каскадные Таблицы Стилей, Уровень 2
Клиентский JavaScript. Справочник.
JavaScript руководство пользователя
Серверный JavaScript 1.4. Руководство по Использованию.

Паскаль, C, C++, C#
GCC (примеры)
FAQ Валентинa Озеровa DELPHI
C



 
© faq.pp.ru, справочник программиста