Как создать сферу
Для того чтобы из существующей заготовки – икосаэдра из двадцати граней – создать сферу, круглую, блестящую и без изъянов, нужно осуществить предельный переход, как в матанализе, бесконечно увеличивая число треугольников при бесконечном уменьшении их размеров. В дискретном мире нет места предельным переходам, поэтому вместо бесконечного деления надо ограничиться каким-то конечным числом и начать делить каждый из двадцати треугольников икосаэдра на все более мелкие правильные треугольники.
Вычисление нормали при этом упрощается, так как при приближении к шару нормаль в каждой вершине треугольника приближается к нормали поверхности шара. А последняя равна нормированному вектору радиуса текущей точки. Алгоритм деления проиллюстрируем рисунком (рис. 6.3).
Рис. 6.3. Деление треугольника икосаэдра
Треугольник с вершинами V1, V2 и V3 разбивается на четыре треугольника: (V1,V12,V31), (V2,V23,V12), (V3,V32,V23) и (V12.V23.V31). После этого промежуточные точки деления надо посадить на поверхность шара, то есть изменить их координаты так, чтобы концы векторов (V12, V23 и V31) дотянулись до поверхности шара. Для этого достаточно нормировать векторы с помощью уже существующей процедуры Scale. Она впоследствии будет использована как для масштабирования нормали, так и для нормировки координат вершин новых треугольников. Но сейчас мы будем вычислять нормаль приближенно. Введем еще две вспомогательные функции:
//=== Команды OpenGL для изображения одного треугольника void setTria (double *v1, double *v2, double *v3) { //====== Нормаль и вершина задаются одним вектором glNormal3dv(vl); glVertex3dv(vl); glNormalSdv (v2); glVertex3dv(v2); glNormal3dv(v3); glVertex3dv(v3); glEnd(); } //====== Генерация внутренних треугольников void Split(double *v1, double *v2, double *v3) { //====== Промежуточные вершины double v12[3], v23[3], v31[3); for (int l=0; l< 3; i++) { //======Можно не делить пополам, //====== так как будем нормировать v12[i] = v1[i]+v2[i]; v23[i] = v2[i]+v3[i]; v31 [i] = v3[i]+v1 [i]; } //====== Нормируем три новые вершины Scale(v12); Scale(v23); Scale(v31); //====== и рисуем четыре треугольника setTria(v1, v12, v31); setTria (v2, v23, v12); setTria(v3, v31, v23); setTria(v12,v23, v31); }