Как Unity3D снижает количество импортированных вершин .obj?

8

У меня есть вопрос относительно того, как Unity3D обрабатывает импорт файлов .obj. Я импортирую этот чайник: http://groups.csail.mit.edu/graphics/classes/6.837/F03/models/teapot.obj

Число вершин этого чайника составляет 3644. Я знаю, что класс Mesh в Unity должен реплицировать эти вершины для каждой грани, разделяемой одной и той же вершиной. Я попробовал это с кубом, импортированным из .obj, и с помощью Debug.Log (), чтобы напечатать количество вершин, я обнаружил, что в массиве вершин меша было 24 вершины.

Однако в чайнике исходный файл имел 3644 вершины, поэтому в Unity число вершин должно составлять 18960. Вместо этого, когда я печатаю длину массива вершин меша, он печатает 3260 (даже меньше, чем исходный файл).

Конечная цель этого заключается в том, что я пытаюсь модифицировать скрипт OBJ Importer из вики Unity, чтобы число вершин, полученных из этого скрипта, было таким же, как и у собственного импортера Unity. Ссылка: http://wiki.unity3d.com/index.php?title=ObjImporter Примечание. С помощью этого импортера я распечатал количество вершин, и результат составил 18960.

У кого-нибудь есть представление о том, как можно добиться сокращения вершин?

VitorOliveira
источник
Сложные алгоритмы, я не уверен, что использует единство, но вы можете найти их в Интернете.
MickLH

Ответы:

5

Есть несколько факторов, которые способствуют тому, как геометрия сохраняется и обрабатывается в различных средах (программы, форматы файлов, API). Я реализовал несколько коммерческих программ анализа геометрии, поэтому у меня есть некоторый опыт в этом.

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

Вот некоторые из этих факторов:

Что делает вершину уникальной?

Это может сильно различаться в зависимости от того, как программа, API или формат файла работает с вершиной. Вершина может быть уникальной, если она имеет уникальную позицию, но в других случаях она уникальна, если у нее есть какой-либо уникальный атрибут. Например, если две вершины разделяют одну и ту же позицию, но имеют разные нормали, их следует «дублировать» в случае OpenGL, это особенно очевидно в случае упомянутого вами куба.

введите описание изображения здесь Хард против гладких краев.

Нормальные значения могут определять, считается ли ребро жестким или гладким, если вершина вносит вклад в резкое ребро, то ее необходимо дублировать, чтобы текущие API-интерфейсы рендеринга могли понять, как правильно визуализировать (заштриховать) эту грань.

введите описание изображения здесь

индексы

Многие форматы файлов позволяют вершинам грани иметь несколько индексов для позиции вершины / texCoords / normals, это не относится к текущим API рендеринга. Прекрасным примером этого является файл Obj, который заставит Unity перестроить индексы и часто дублировать многие атрибуты, чтобы соответствовать индексам вершин.

связь

Многие вершины, которые на самом деле связаны и являются уникальными, сохраняются многократно, это связано с тем, как оригинальный обработчик файлов обрабатывал и сохранял сетку. Unity уменьшит количество дублирующихся вершин (помните, если у него другой атрибут, тогда он не уникален), чтобы сделать его более эффективным для хранения и обработки без ущерба для качества.

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

concept3d
источник
О, я понял это сейчас! В импортере .obj, который я использовал, вершины всегда дублируются для каждой грани, в которой они используются, и поэтому я всегда получаю жесткие края на своем чайнике (я не упоминал об этом раньше, потому что думал, что это другая проблема). Отличный ответ!
ВиторОливейра
2

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

Во время загрузки все эти три атрибута должны быть объединены вместе, чтобы одна позиция вершины могла закончиться дублированно, потому что грань, связанная с этой позицией вершины, связана с двумя нормалями . Это может происходить и в обратном порядке, поэтому у большинства загрузчиков есть шаг для оптимизации объекта, но в случае вашего куба оптимизация не будет работать, так как у куба есть жесткие ребра и каждая вершина имеет свою нормаль (или координату текстуры). Вот почему вы насчитали 6 позиций вершин, но единица дублировала эти позиции, в результате чего получилось 24 вершины.

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

Raxvan
источник
Этот ответ стал отличным дополнением к тому, что сказал concept3d, и помог мне понять эту проблему. Так что я предполагаю, что у моего импортера .obj всегда будут жесткие ребра, но если я хочу улучшить его, я должен поискать алгоритмы, чтобы помочь мне узнать, какие вершины должны дублироваться или нет, чтобы иметь модель с гладкими краями с минимумом ( или, по крайней мере, оптимизировано) количество вершин.
ВиторОливейра