Как сделать правильное отображение тела вращения?
В моем проекте надо сначала поставить точки, потом образуется полигон, и создастся тело вращения на основе этого полигона. В зависимости от того, как поставить точки, тело вращения отобразится либо полностью черным (нормали внутрь), либо нормально с тенями (нормали наружу).
Первая точка - самая левая
Первая точка - третья, если считать справа-налево
Я пытался сделать так, чтобы в массиве точек крайней левой всегда была точка, которую мы ставим самой первой, помогало не во всех случаях((((
Так отрисовывается тело вращения:
Gl.glBegin(Gl.GL_QUADS);
// режим отрисовки полигонов, состоящих из 4 вершин
for (int ax = 0; ax < count_elements; ax++)
{
for (int bx = 0; bx < trackBar2.Value; bx++)
{
// вспомогательные переменные для более наглядного использования кода при
//расчете нормалей
double x1 = 0, x2 = 0, x3 = 0, x4 = 0, y1 = 0, y2 = 0, y3 = 0, y4 = 0, z1 = 0, z2 = 0, z3 = 0, z4 = 0;
// первая вершина
x1 = ResaultGeometric[ax, bx, 0];
y1 = ResaultGeometric[ax, bx, 1];
z1 = ResaultGeometric[ax, bx, 2];
if (ax + 1 < count_elements) // если текущий ax не последний
{
// берем следующую точку последовательности
x2 = ResaultGeometric[ax + 1, bx, 0];
y2 = ResaultGeometric[ax + 1, bx, 1];
z2 = ResaultGeometric[ax + 1, bx, 2];
if (bx + 1 < Iter - 1) // если текущий bx не последний
{
// берем следующую точку последовательности и следующий меридиан
x3 = ResaultGeometric[ax + 1, bx + 1, 0];
y3 = ResaultGeometric[ax + 1, bx + 1, 1];
z3 = ResaultGeometric[ax + 1, bx + 1, 2];
// точка, соответствующая по номеру только на соседнем меридиане
x4 = ResaultGeometric[ax, bx + 1, 0];
y4 = ResaultGeometric[ax, bx + 1, 1];
z4 = ResaultGeometric[ax, bx + 1, 2];
}
else
{
// если это последний меридиан, то в качестве следующего мы берем начальный
//(замыкаем геометрию фигуры)
x3 = ResaultGeometric[ax + 1, 0, 0];
y3 = ResaultGeometric[ax + 1, 0, 1];
z3 = ResaultGeometric[ax + 1, 0, 2];
x4 = ResaultGeometric[ax, 0, 0];
y4 = ResaultGeometric[ax, 0, 1];
z4 = ResaultGeometric[ax, 0, 2];
}
}
else // данный элемент ax последний, следовательно мы будем использовать
//начальный(нулевой) вместо данного ax
{
// следуещей точкой будет нулевая ax
x2 = ResaultGeometric[0, bx, 0];
y2 = ResaultGeometric[0, bx, 1];
z2 = ResaultGeometric[0, bx, 2];
if (bx + 1 < Iter - 1)
{
x3 = ResaultGeometric[0, bx + 1, 0];
y3 = ResaultGeometric[0, bx + 1, 1];
z3 = ResaultGeometric[0, bx + 1, 2];
x4 = ResaultGeometric[ax, bx + 1, 0];
y4 = ResaultGeometric[ax, bx + 1, 1];
z4 = ResaultGeometric[ax, bx + 1, 2];
}
else
{
x3 = ResaultGeometric[0, 0, 0];
y3 = ResaultGeometric[0, 0, 1];
z3 = ResaultGeometric[0, 0, 2];
x4 = ResaultGeometric[ax, 0, 0];
y4 = ResaultGeometric[ax, 0, 1];
z4 = ResaultGeometric[ax, 0, 2];
}
}
// переменные для расчета нормали
double n1 = 0, n2 = 0, n3 = 0;
// нормаль будем рассчитывать как векторное произведение граней полигона
// для нулевого элемента нормаль мы будем считать немного по-другому
// на самом деле разница в расчете нормали актуальна только для последнего и
//первого полигонов на меридиане
if (ax == 0) // при расчете нормали для ax мы будем использовать точки 1, 2, 3
{
n1 = (y2 - y1) * (z3 - z1) - (y3 - y1) * (z2 - z1);
n2 = (z2 - z1) * (x3 - x1) - (z3 - z1) * (x2 - x1);
n3 = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);
}
else // для остальных ‒ 1, 3, 4
{
n1 = (y4 - y3) * (z1 - z3) - (y1 - y3) * (z4 - z3);
n2 = (z4 - z3) * (x1 - x3) - (z1 - z3) * (x4 - x3);
n3 = (x4 - x3) * (y1 - y3) - (x1 - x3) * (y4 - y3);
}
// если не включен режим GL_NORMILIZE, то мы должны в обязательном порядке
// произвести нормализацию вектора нормали, перед тем как передать информацию о нормали
double n5 = (double)Math.Sqrt(n1 * n1 + n2 * n2 + n3 * n3);
n1 /= (n5 + 0.01);
n2 /= (n5 + 0.01);
n3 /= (n5 + 0.01);
// передаем информацию о нормали
Gl.glNormal3d(-n1, -n2, -n3);
// передаем 4 вершины для отрисовки полигона
Gl.glVertex3d(x1, y1, z1);
Gl.glVertex3d(x2, y2, z2);
Gl.glVertex3d(x3, y3, z3);
Gl.glVertex3d(x4, y4, z4);
}
}
Массив ResaultGeometric - это массив всех точек тела вращения.
Я не понял еще зависимость. Как сделать так, чтоб нормали были всегда наружу?
Нет, тут все нормально.