У меня есть класс, который генерирует трехмерную фигуру на основе входных данных из вызывающего кода. Входными данными являются такие вещи, как длина, глубина, дуга и т. Д. Мой код прекрасно генерирует геометрию, однако у меня возникают проблемы при вычислении нормалей поверхности. Когда горит, моя форма имеет очень странную окраску / текстуру от неправильных нормалей поверхности, которые рассчитываются. Из всех моих исследований я считаю, что моя математика верна, кажется, что что-то не так с моей техникой или методом.
На высоком уровне, как можно программно рассчитать нормали поверхности для сгенерированной фигуры? Я использую Swift / SceneKit на iOS для своего кода, но общий ответ в порядке.
У меня есть два массива, которые представляют мою форму. Одним из них является массив трехмерных точек, представляющих вершины, которые составляют форму. Другой массив представляет собой список индексов первого массива, которые отображают вершины в треугольники. Мне нужно взять эти данные и сгенерировать 3-й массив, который представляет собой набор нормалей поверхности, которые помогают в освещении фигуры. (см. SCNGeometrySourceSemanticNormal
в SceneKit` )
Список вершин и индексов всегда различается в зависимости от входных данных для класса, поэтому я не могу предварительно рассчитать или жестко закодировать нормали поверхности.
Ответы:
Вы просто не хотите полностью гладких результатов. В то время как прокомментированный метод Натана Рида: «Рассчитать каждую вершину, чтобы найти нормаль, сложить их, нормализовать сумму», обычно работает, но иногда это не удается. Но это не имеет значения, мы можем использовать этот метод, добавив к нему предложение отклонения.
В этом случае вы просто хотите, чтобы определенные части не были сглажены относительно определенных других частей. Вы хотите избирательные жесткие края. Так, например, плоская вершина и низ являются отдельными от треугольной полосы на стороне, как и каждая плоская область.
Изображение 1 : Результат, который вы хотите.
По сути, вы хотите усреднить только вершины искривленной области, все остальные могут использовать нормали, которые они получают из своего треугольника. Таким образом, вам лучше думать о сетке как о 9 отдельных областях, которые обрабатываются без других.
Изображение 2 : Изображение, показывающее структуру сетки и нормали.
Вы можете, конечно, автоматически сделать это, не включая нормали, которые находятся за пределами определенного угла от первичных вершин нормали. псевдокод:
Это работает, но вы можете просто избежать всего этого во время создания, потому что вы понимаете, что отдельные плоскости работают по-разному. Таким образом, только изогнутые стороны нуждаются в нормальном слиянии направления. И на самом деле вы можете просто напрямую вычислить их из базовой математической формы.
источник
Я вижу в основном три способа вычисления нормалей для сгенерированной фигуры.
Аналитические нормы
В некоторых случаях у вас достаточно информации о поверхности для генерации нормалей. Например, нормаль любой точки на сфере тривиальна для вычисления. Проще говоря, когда вы знаете производную функции, вы также знаете нормальную.
Если ваш случай достаточно узок, чтобы позволить вам использовать аналитические нормали, они, вероятно, дадут лучший результат с точки зрения точности. Тем не менее, техника не слишком хорошо масштабируется: если вам также нужно обрабатывать случаи, когда вы не можете использовать аналитические нормали, может быть проще сохранить технику, которая обрабатывает общий случай, и отбросить аналитическую вообще.
Нормали вершин
Перекрестное произведение двух векторов дает вектор, перпендикулярный плоскости, к которой они принадлежат. Таким образом, получить нормаль треугольника просто:
Более того, в приведенном выше примере длина поперечного произведения пропорциональна площади внутри abc . Таким образом, сглаженная нормаль в вершине, разделяемой несколькими треугольниками, может быть вычислена путем суммирования перекрестных произведений и нормализации в качестве последнего шага, таким образом взвешивая каждый треугольник по его площади.
Если вы работаете с квадраторами, есть хороший прием, который вы можете использовать: для квадроциклов abcd используйте,
crossProduct(c - a, d - b)
и он отлично справится со случаями, когда квад на самом деле является треугольником.Иньго Квилес написал несколько коротких статей на эту тему: умная нормализация сетки , нормаль и площадь n-сторонних многоугольников .
Нормалы из частных производных
Нормы могут быть вычислены в фрагментном шейдере из частных производных. Математика позади та же самая, за исключением того, что на этот раз это делается на экране. Эта статья Анджело Песче описывает технику: нормали без нормалей .
источник