Как вывернуть полигоны?

У полигонов есть лицевая и изнаночная сторона, по-английски Front и Backface. Сторона определяется исключительно по порядку обхода вертексов. Если вертексы идут по часовой стрелке, то сторона лицевая.

Гудини подкрашивает тыльную сторону полигонов синим цветом, это поведение можно изменить в настройках вьюпорта (D над вьюпортом), меню Markers, Tint backfaces. Чтобы эмулировать поведение игровых движков, можно пойти в этом же окне во вкладку Optimize и включить Remove backfaces. В этом случае тыльные стороны полигонов не будут отображаться вообще.

Чтобы вывернуть полигон, необходимо поставить ноду Reverse, которая пересоберет вертексы в противоположном порядке.

Важно, что атрибут N, то есть нормаль, не связан с направлением полигона. При вывернутом полигоне нормаль может смотреть и в правильную сторону. Поэтому, если после ноды Reverse геометрия стала черной, надо пересчитать нормали нодой Normal.

Если вам нужно найти нормаль исходя из направления полигона, можно использовать VEX-функцию prim_normal(geo, prim number, u, v), которая вернет эту нормаль в полигоне prim number в позиции параметрических координат u,v.

Иногда из других пакетов (особенно из КАД) приходят модели с частично вывернутыми полигонами. Прежде чем паниковать, надо задать себе вопрос: а действительно ли это плохо?

Вывернутые полигоны будут вызывать проблемы в нескольких случаях:

  1. Они находятся на полупрозрачной геометрии с преломлениями. На рендере будут артефакты.
  2. Модель для игрового движка. Большинство шейдеров в движках по умолчанию не показывают бэкфейсы для оптимизации.
  3. Планируется еще процедурно менять модель. Например Extrude зависит от направления полигонов.

В остальных случаях, скорее всего, неправильно направленные полигоны не будут заметны на рендере. Можно отключить Tint Backfaces и не обращать на них внимание.

Если вы, все-таки, обнаружили артефакты, то придется эти полигоны корректировать. Универсального метода, который исправляет все плохие полигоны, не существует. Результат будет сильно зависеть от топологии.

Варианты исправления:

  1. Нода Polydoctor, вкладка Topology, Correct Winding of Polygons to Majority… Эта нода найдет направление большинства полигонов в острове геометрии и исправит оставшиеся. Соответственно, полигоны должны быть связанны друг с другом (Fuse).
  2. Добавить ноду Boolean в режиме Union. Если топология связная, то вывернутые полигоны пропадут. Остается найти, какие полигоны пропали и реверснуть их на исходной геометрии. Например, сохранить исходный номер примитива в атрибут index нодой Enumerate, создать на геометрии с булем атрибут @mask=1, а потом нодой Attribute copy скопировать этот атрибут на исходную геометрию, используя Index в качестве атрибута соответствия.

3. Вычислить объем. Создать атрибут сlass на полигонах нодой Connectivity по примитивам. Добавить Measure — Volume — Accumulate Per Piece. Если топология связная, после этого на вывернутых полигонах будет отрицательный объём. Его можно использовать в ноде Reverse, добавив в группу @volume<0

4. Если у вас на модели есть нормали, и они правильно направлены, то можно сравнить нормаль с вектором, который получается после prim_normal(). Если они противоположно направленные, то полигон вывернут. Это определяется функцией dot().

5. Можно вручную расставить точки снаружи объекта и воспользоваться следующим кодом для выделения перевернутых полигонов. Так можно быстро пофиксить полигоны на видимой части объекта. На второй вход врангла подается одна точка, позиция условной «камеры», из которой пускаются лучи. Врангл по примитивам. Можно поставить несколько вранглов подряд с разными точками. На выходе образуется группа с названием rev, по которой можно ставить Reverse.

vector cam = point(1,"P",0);
vector ray = normalize(@P-cam);
vector norm = prim_normal(0,@primnum,0,0);
vector pos, uv;
if (intersect(0, cam, ray*10000, pos, uv)==@primnum)
{
    if (dot(ray, norm)>0) @group_rev=1;
}

Эти методы будут корректно работать далеко не всегда. Если есть возможность, лучше исправлять проблемные места в исходнике.