Иллюстрированный самоучитель по Visual Studio .NET

Строим икосаэдр

Чтобы нивелировать зависимость цвета вершины от амплитуды нормали, обычно вектор нормали масштабируют (или нормируют), то есть делают его длину равной единице, оставляя неизменным направление. С учетом сказанного создадим две вспомогательные функции. Первая масштабирует, а вторая вычисляет нормаль к плоскости треугольника. Алгоритм вычисления использует координаты двух сторон, прилегающих к текущей вершине треугольника:

//==== Нормирование вектора нормали (или любого другого)
void Scale(double v[3])
{
double d = sqrt(v[0]*v[0]+v[l]*v[l]+v[2]*v[2]);
if (d == 0.)
{
MessageBox(0,"Zero length vector","Error",MB_OK);
return;
}
void getNorm(double vl[3], double v2[3], double out[3])
{
//===== Вычисляем координаты вектора нормали
//====== по формулам векторного произведения
out[0] = vl[l]*v2[2] – vl[2]*v2[l];
out[l] = vl[2]*v2(0] – vl[0]*v2[2];
out[2] =vl[0]*v2[l] – vl[l]*v2[0];
Scale(out);
}

Замените функцию DrawScene. В новом варианте мы аккуратно вычисляем и масштабируем нормали в каждом из двадцати треугольников поверхности икосаэдра:

void DrawScene()
{
static double
angle -3. * atanfl.)/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) 1;
glNewList(l,GL_COMPILE); glColorSd (1., 0.4, 1.);
glBegin(GLJTRIANGLES);
for (int i = 0; i < 20; i++)
{
double dl[3], d2[3], norm[3];
for (int j = 0; j < 3; j++)
{
dl[j] =v[id[i][0]] [j] – v[id[i][l]J [j];
d2[j] =v[id[i][l]] [j] – v[id[i][2J] [j];
}
//====== Вычисление и масштабирование нормали
getNorm(dl, d2, norm);
glNormal3dv(norm);
glVertexSdv(v [ id[i] [1]]);
glVertex3dv(v[id[i] [1] ] glVertex3dv(v[id[i] [2] ]
glEnd();
}
glEndList ();
}

Примечание
Функцию нормировки всех нормалей можно возложить на автомат OpenGL, если включить состояние GL_NORMALIZE, но обычно это ведет к замедлению перерисовки и, как следствие, выполнения приложения, если изображение достаточно сложное. В нашем случае оно просто, и поэтому вы можете проверить действие настройки, если вставите вызов glEnable (GL_NORMALIZE); в функцию Init (до вызова OrawScene) и временно выключите вызов Scale(out); производимый в функции getNorm. Затем вернитесь к исходному состоянию
.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.