Как сделать правильное отображение тела вращения?

В моем проекте надо сначала поставить точки, потом образуется полигон, и создастся тело вращения на основе этого полигона. В зависимости от того, как поставить точки, тело вращения отобразится либо полностью черным (нормали внутрь), либо нормально с тенями (нормали наружу). Первая точка - самая левая Первая точка - самая левая Первая точка - третья, если считать справа-налево Первая точка - третья, если считать справа-налево Я пытался сделать так, чтобы в массиве точек крайней левой всегда была точка, которую мы ставим самой первой, помогало не во всех случаях(((( Так отрисовывается тело вращения:

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 - это массив всех точек тела вращения.
Я не понял еще зависимость. Как сделать так, чтоб нормали были всегда наружу? введите сюда описание изображения Нет, тут все нормально.


Ответы (0 шт):