Программно генерирование вершинных нормалей

11

Я работаю с API-интерфейсом для лица Kinect, он предоставляет массив вершин и индексов для треугольников, которые должны быть визуализированы для создания изображения лица.

Нет вершин и их порядок в массиве, а также индексы, заданные kinect, всегда постоянны.

Однако API не дает информации о данных УФ и нормалях вершин.

Приложение требует, чтобы я сохранял порядок вершин, заданный kinect, так как их положения в трехмерном пространстве изменяются в соответствии с движением лица, так что генерация ультрафиолета и нормалей в программном обеспечении для трехмерного редактирования не подлежит сомнению.

Мне удалось сгенерировать UV, спроецировав положения вершин на 2D-плоскость, поскольку в одной плоскости было очень мало вершин.

Тем не менее, я не знаю, как генерировать нормали вершин для сетки, без нормали вершин сетка граней отрисовывается без глубины своих элементов от предполагаемой, хотя силуэт виден, поскольку положения вершин верны.

Я понимаю, что из-за отсутствия нормалей вершин освещение не будет работать правильно на нем, и, следовательно, бледная безликая сетка, которую он смотрит прямо сейчас.

Итак, как я могу генерировать нормали вершин, когда все, что у меня есть, это просто положение вершины и индекс вершин, чтобы сделать из нее треугольники?

Allahjane
источник
n = (v1 - v0) x (v2 - v0), где v0, v1 и v2 - вершины рассматриваемой грани (треугольника). Заказ является важным. Нормализуйте это, если вам действительно нужно. (и xявляется кросс-продуктом)
3Dave

Ответы:

14

Вычислить нормаль из позиций вершин довольно просто, используя векторное произведение.

UvU×vUvUv||U×v||знак равно||U||||v||sяN(θ)θUvU×vv×U

Если вы не знакомы с кросс-продуктом, я предлагаю вам прочитать об этом и освоиться с ним. Нормалы тогда будут казаться простыми.

Плоские штриховые нормали

AВСAВ×AС

Nзнак равноAВ×AС||AВ×AС||

В коде это будет выглядеть, n = normalize(cross(b-a, c-a))например. Просто примените это на все ваши лица, и вы будете иметь свои нормали на лицо.

For each triangle ABC
    n := normalize(cross(B-A, C-A))
    A.n := n
    B.n := n
    C.n := n

Обратите внимание, что это предполагает, что вершины не являются общими для треугольников. Я не знаком с API Kinect; вполне возможно, что они являются общими, и в этом случае вам придется дублировать их или перейти к следующему решению:

Плавное затенение нормалей

После освещения с помощью нормалей, рассчитанных, как указано выше, вы заметите, что края треугольника очевидны. Если это нежелательно, вы можете вместо этого вычислять гладкие нормали, принимая во внимание все грани, которые имеют одну и ту же вершину.

T1T2T3NN1N2N3T1T2NN1N2

Помните, как поперечное произведение пропорционально площади? Если вы сложите перекрестные продукты, а затем нормализует сумму, она получит именно ту весовую сумму, которую мы хотим. Таким образом, алгоритм становится:

For each vertex
    vertex.n := (0, 0, 0)

For each triangle ABC
    // compute the cross product and add it to each vertex
    p := cross(B-A, C-A)
    A.n += p
    B.n += p
    C.n += p

For each vertex
    vertex.n := normalize(vertex.n)

Этот метод более подробно объясняется в статье Иньиго Квилеса: умная нормализация сетки .


Подробнее о нормалях смотрите также:

Жюльен Геро
источник
Я сделаю это как можно скорее и вернусь с результатами
Аллахжане
Это сработало. Спасибо, тонна человек, сработало именно так, как я и хотел
Аллахжане,
увидеть результат здесь ДО ДОПОЛНЕНИЯ i.gyazo.com/a314d1f7a0509788c272f83279c5077b.png и ПОСЛЕ i.gyazo.com/b879db7294d82a72b86cc4eaf0132a13.png
Аллахжан
@Allahjane: рад слышать, что это работало нормально. :)
Жюльен Геро