Каждая вершина принадлежит одной или нескольким граням (обычно треугольникам, иногда четырехугольникам - в этом ответе я буду использовать треугольники).
Треугольник, который не присоединен к другим треугольникам, не может быть «сглажен». Он плоский. Только когда у лица есть соседи, можно подумать о том, чтобы сгладить их вместе.
Для вершины, в которой встречаются несколько граней, вычислите нормали для каждой из этих граней. Перекрестное произведение двух векторов возвращает перпендикулярный (нормальный) вектор, что нам и нужно.
A --- B
\ /
C
v1 = B - A
v2 = C - A
normal = v1 cross v2
Будьте осторожны, чтобы вычислить эти векторы последовательно для всех граней, иначе нормаль может быть в отрицательном направлении по сравнению с тем, что вам нужно.
Итак, в вершине, где встречаются несколько граней, просуммируйте нормали граней, нормализуйте полученный вектор и примените его к вершине.
Иногда у вас есть сетка, в которой одни части нужно сглаживать, а другие нет. Легко изобразить пример - цилиндр из треугольников. Круглая поверхность цилиндра будет гладкой хорошо, но если рассматривать треугольники с плоских концов в вершинах вокруг острого выступа, это будет выглядеть странно. Чтобы избежать этого, вы можете ввести правило, которое игнорирует нормали от граней, которые слишком сильно отклоняются от нормали лица, для которого вы рассчитываете.
EDIT есть действительно хороший видео, демонстрирующий технику расчета затенения по Гураду , хотя в нем не обсуждается реальный алгоритм.
Возможно, вам захочется взглянуть на исходный код Three.js. В частности, функция computeVertexNormals
. Он не поддерживает сохранение острых краев. Эффективность вашего алгоритма в значительной степени зависит от того, как вы моделируете свои примитивы.
person
Drew Noakes
schedule
07.02.2013