Недавно я изучал SceneKit для OS X и заметил, что существует несколько заводских методов для создания геометрических фигур, таких как:
Коробка, Капсула, Конус, Цилиндр, Самолет, Пирамида, Сфера, Тора и Трубка.
Я заинтересован в добавлении таких примитивных форм к моему рендереру, но изо всех сил пытаюсь найти какой-либо разумный источник, из которого я могу получить понимание процедурной генерации. Есть несколько ресурсов, которые детализируют теорию, но не имеют соответствующего исходного кода для ее резервного копирования.
SceneKit предоставляет фабричные методы, которые позволяют динамически устанавливать атрибуты таких фигур. В случае Box вы можете указать целочисленные значения для числа сегментов ширины, высоты и глубины, на которые должна делиться каждая грань.
Я понимаю теорию, но мне не хватает знаний, чтобы начать деление геометрических граней для достижения желаемого эффекта.
Вершины для каждой фигуры, скорее всего, довольно просто генерировать в простых циклах. Что меня озадачивает, так это знание того, как создавать грани, точнее соответствующие координаты текстуры для каждого грани. Нормы можно рассчитать для каждого лица, поэтому я уверен, что смог достичь того, чего хочу, просто зная, с чего начать.
Кто-нибудь может предоставить какие-либо подробности по процедурной геометрии? Что мне действительно нужно, так это некоторый исходный код, чтобы почерпнуть некоторую информацию. Я искал учебные пособия, но пока придумал только несколько разумных сайтов или блогов. Любые хорошие книги, учебники, блоги или исследовательские работы будут оценены.
Редактировать на основе комментариев
Я должен был уточнить, что я знаю, как создавать вершины для основных фигур, большинство из которых, вероятно, могут быть достигнуты с помощью простых циклов. Чего я не понимаю, так это как создавать грани из сгенерированного массива вершин. Как мне создать треугольную полосу или треугольники из неупорядоченного, казалось бы, множества вершин?
Я предполагаю, что, как только я преодолею эту точку, я могу создать нормали для каждого лица. Хотя я еще не углубился в это, я видел много ссылок на это и уверен, что это будет достаточно легко реализовать.
В идеале я хотел бы иметь возможность генерировать геометрию из заданного набора свойств, таких как способ, который предоставляет SceneKit. Учитывая, что SceneKit сделал это, и вы можете делать подобные вещи в Blender, Maya и т. Д., Я предполагаю, что я не пытаюсь реализовать невозможное.
Последний аспект - применение текстур. Опять же, это не то, что я реализовал, но прочитал и знаю требования.
Основная проблема здесь в том, что я знаю, чего хочу достичь, но изо всех сил пытаюсь понять, как реализовать эти вышеупомянутые примитивы. Я надеялся, что смогу найти какое-то подобие знаний с помощью исходного кода, но я действительно не нашел ничего подходящего до сих пор.
источник
Ответы:
Способ создания ребер и граней примитивной формы, такой как квадрат, конус и все, что вы указали, состоит в том, чтобы генерировать их одновременно с созданием вершин. Фактически, вы должны создавать вершины логическим способом, который облегчает вычисление ребер и граней соответственно.
Существуют алгоритмы, которые принимают в качестве входных данных набор точек в пространстве и вычисляют над ним так называемую « триангуляцию набора точек », но проблема триангуляции набора точек является NP-полной , так что быстрее сделать ребра и грани как вы идете, чем просто вычислить вершины и позволить алгоритму сделать работу. Просто сообщаю вам, что это решение существует.
Помимо этого неэффективного решения, я считаю, что вы можете обрабатывать примитивы только для каждого конкретного случая, как в следующих примерах.
Сетка - это вершины и грани . Края содержатся в описании граней, если ваша сетка не содержит линий, которые не образуют граней. Вершины - это кортежи из трех координат с плавающей точкой. Ребра - это просто пары ссылок на вершины, но опять же они вам точно не понадобятся. Скажем, например, что ваши вершины находятся в индексированном массиве. Тогда ваши ребра могут быть парами индексов этого массива. Грани являются триплетами ссылок на вершины или триплетами индексов в случае индексированного массива .
Вы должны быть в состоянии сосчитать вершины, ребра и грани, которые составляют каждую из этих примитивных форм, потому что возможность их подсчета означает понимание свойств объекта, которое помогает вам разработать метод, с помощью которого вы будете их строить, используя циклы и другие инструменты, как мы увидим.
шишка
Для конуса с n + 2 вершинами, 3n ребрами и 2n гранями:
1) 2)
3)
4)
Конечный результат:
Вы также можете создавать ребра и грани, выполняя цикл, который образует круг. Та же сложность, та же самая вещь. Сделайте одну вершину на окружности, сохраните ее в массиве вершин, добавьте соответствующее ребро (пару индексов) к массиву пар индексов, если хотите, и, наконец, добавьте соответствующее лицо к вашему массиву триплетов индексов. , Переходите к следующей вершине.
Цилиндр и труба: не выполняю одинаковую работу дважды, а квадроцикл
Опять же, для трубы она начинается с вершины и круга, который будет центром либо верхнего, либо нижнего диска цилиндра:
Чтобы связать верх и низ, вы должны сделать четырехугольники между парами пар вершин, которые обращены друг к другу. Так что подумайте, а почему бы не сделать себя функцией, которая делает две треугольные грани из четырех вершин?
Выполнено. Обратите внимание, что на этот раз мы используем тот факт, что одна и та же структура (круг + центр) дважды появляется в цилиндре, чтобы использовать ярлык. Нам не нужно делать все вершины, ребра и грани вручную, в отличие от конуса, где это было необходимо.
Следуя этому принципу лени, также можно просто сделать одну четверть круга и продублировать ее, и снова сделать полный круг с очень простыми преобразованиями (действительно для любого круга, также и для конуса), но это действительно излишне для не такая сложная форма.
Вы всегда должны использовать геометрические свойства объектов, которые вы делаете, чтобы упростить их создание . А именно, их симметрии и инварианты .
Для цилиндра, просто не делайте базовую вершину, просто сделайте круг, продублируйте, переведите копию, сделайте квадраты, готово.
Сфера и капсула: сложность сложная, еще не та же самая работа дважды
Чтобы создать капсулу, мы хотим создать ультрафиолетовую сферу, разделить ее на две половины, перевести первую половину и затем связать две с боковыми сторонами капсул.
Опять же, можно сделать только одну восьмую (!!) сферы, затем продублировать ее и повернуть ее вспять, а затем продублировать и инвертировать результат, кроме как вдоль другой оси и т. Д., Чтобы получить полную сферу, за 4 шага (создайте восьмую) , дублируйте и переверните три раза). Может быть, излишним, но меньше, чем в случае с кругом.
Простая УФ сфера:
Фактически мы делаем только половину (например), дублируем эту половину, переворачиваем копию вверх дном и переводим ее по длине капсулы:
Мы связываем верхнюю и нижнюю половину:
Настоящая (несколько) тяжелая работа происходит от тригонометрии, которая входит в создание сферы. Множество всех вершин, принадлежащих УФ сфере, можно описать как множество всех точек вида:
где R - радиус сферы, и для некоторого положительного четного целого числа N имеем постоянную
θ = × π / N ,
k и n являются целыми числами, где k варьируется от 0 до 2N-1, а n варьируется от -N / 2 до + N / 2 .
Чтобы сделать полусферу или восьмую сферу, вы должны ограничить набор значений, принимаемых k и n .
Если бы k были действительными числами, а не просто целыми числами, вы бы получили целую сферу, а не только вершины на ее поверхности. Итак, мы сделали растеризацию поверхностного уравнения примитива .
Страшный тор : это легко после всего, что мы видели!
Опять же, больше тригонометрии, больше вершин, больше квадратов, больше симметрий, больше инвариантов ... больше геометрии! Найдите уравнение для поверхности тора, правильно "растеризуйте его", упростите задачу, используя (очевидные) симметрии тора, и, наконец, проведите цикл по множеству вершин, которые вы только что определили, и сделайте ребра и грани такими, как вы идти!
Видеть? Совершенно просто.
источник