Генерация процедурной геометрии

10

Недавно я изучал SceneKit для OS X и заметил, что существует несколько заводских методов для создания геометрических фигур, таких как:

Коробка, Капсула, Конус, Цилиндр, Самолет, Пирамида, Сфера, Тора и Трубка.

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

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

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

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

Кто-нибудь может предоставить какие-либо подробности по процедурной геометрии? Что мне действительно нужно, так это некоторый исходный код, чтобы почерпнуть некоторую информацию. Я искал учебные пособия, но пока придумал только несколько разумных сайтов или блогов. Любые хорошие книги, учебники, блоги или исследовательские работы будут оценены.

Редактировать на основе комментариев

Я должен был уточнить, что я знаю, как создавать вершины для основных фигур, большинство из которых, вероятно, могут быть достигнуты с помощью простых циклов. Чего я не понимаю, так это как создавать грани из сгенерированного массива вершин. Как мне создать треугольную полосу или треугольники из неупорядоченного, казалось бы, множества вершин?

Я предполагаю, что, как только я преодолею эту точку, я могу создать нормали для каждого лица. Хотя я еще не углубился в это, я видел много ссылок на это и уверен, что это будет достаточно легко реализовать.

В идеале я хотел бы иметь возможность генерировать геометрию из заданного набора свойств, таких как способ, который предоставляет SceneKit. Учитывая, что SceneKit сделал это, и вы можете делать подобные вещи в Blender, Maya и т. Д., Я предполагаю, что я не пытаюсь реализовать невозможное.

Последний аспект - применение текстур. Опять же, это не то, что я реализовал, но прочитал и знаю требования.

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

CaptainRedmuff
источник
Вы говорите, что ваша проблема состоит в подразделении геометрии, но затем вы говорите, что создание вершин должно быть легким, а затем вы говорите, что ваша проблема заключается в том, как создавать грани, а затем вы говорите, что ваша проблема - наложение текстур. В чем твоя проблема? Можете ли вы генерировать позиции вершин? Можете ли вы генерировать края и грани? Кроме того, координаты текстуры зависят от вашей текстуры и того, чего вы хотите достичь, поэтому вопрос о координатах текстуры не очень хороший. Наконец, поколение примитивов - это просто геометрия, и люди редко называют это «процедурной геометрией», хотя это так.
Джрсала
Я понимаю, как создать геометрию для простых фигур, таких как куб или плоскость, это создание граней, которые я не понимаю. Как создать грани из группы вершин? Построение точек для более сложных форм является частью проблемы, хотя у меня есть базовое понимание. Склеить их все вместе в треугольную полосу или треугольники - вот что я пытаюсь обернуть вокруг.
CaptainRedmuff
ОК, спасибо за подробности. Вы можете отредактировать свой вопрос, чтобы уточнить. Время ответа!
Джрсала

Ответы:

11

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

Существуют алгоритмы, которые принимают в качестве входных данных набор точек в пространстве и вычисляют над ним так называемую « триангуляцию набора точек », но проблема триангуляции набора точек является NP-полной , так что быстрее сделать ребра и грани как вы идете, чем просто вычислить вершины и позволить алгоритму сделать работу. Просто сообщаю вам, что это решение существует.

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

Сетка - это вершины и грани . Края содержатся в описании граней, если ваша сетка не содержит линий, которые не образуют граней. Вершины - это кортежи из трех координат с плавающей точкой. Ребра - это просто пары ссылок на вершины, но опять же они вам точно не понадобятся. Скажем, например, что ваши вершины находятся в индексированном массиве. Тогда ваши ребра могут быть парами индексов этого массива. Грани являются триплетами ссылок на вершины или триплетами индексов в случае индексированного массива .

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

шишка

Для конуса с n + 2 вершинами, 3n ребрами и 2n гранями:

  1. Сделайте две отдельные вершины.
  2. Сделайте круг вокруг одной из вершин (базовой вершины), которая находится в плоскости, перпендикулярной сегменту между первыми двумя вершинами. Надеюсь, вы можете сделать круг с помощью тригонометрии, верно? Это уже все вершины конуса. Это также одна треть всех ребер ( в круге n ребер и всего 3n ).
  3. Сделайте n ребер от базовой вершины до n вершин в окружности. Вы можете сделать половину лица (это n лиц), как вы это делаете.
  4. Сделайте n ребер от вершины вершины до n вершин в окружности. Вы можете сделать другую половину лица (это n лиц), как вы это делаете.

1) Две вершины 2) и круг
3) и лица
4) и лица
Конечный результат:результат

Вы также можете создавать ребра и грани, выполняя цикл, который образует круг. Та же сложность, та же самая вещь. Сделайте одну вершину на окружности, сохраните ее в массиве вершин, добавьте соответствующее ребро (пару индексов) к массиву пар индексов, если хотите, и, наконец, добавьте соответствующее лицо к вашему массиву триплетов индексов. , Переходите к следующей вершине.

Цилиндр и труба: не выполняю одинаковую работу дважды, а квадроцикл

Опять же, для трубы она начинается с вершины и круга, который будет центром либо верхнего, либо нижнего диска цилиндра:

  1. Сделайте вершину.
  2. Сделайте круг вокруг вершины. Добавьте ребра (если вы хотите ребра) между последовательными вершинами окружности и между центральной вершиной и каждой вершиной окружности. Добавьте грани между каждым триплетом вершин, состоящим из центральной вершины и двумя последовательными вершинами на окружности.
  3. Дублируйте все это, переведите копию в направлении, перпендикулярном только что сделанному основанию, на длину нужного цилиндра.
  4. Свяжите верх и низ.

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

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

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

Вы всегда должны использовать геометрические свойства объектов, которые вы делаете, чтобы упростить их создание . А именно, их симметрии и инварианты .

Для цилиндра, просто не делайте базовую вершину, просто сделайте круг, продублируйте, переведите копию, сделайте квадраты, готово.

Сфера и капсула: сложность сложная, еще не та же самая работа дважды

Чтобы создать капсулу, мы хотим создать ультрафиолетовую сферу, разделить ее на две половины, перевести первую половину и затем связать две с боковыми сторонами капсул.

Опять же, можно сделать только одну восьмую (!!) сферы, затем продублировать ее и повернуть ее вспять, а затем продублировать и инвертировать результат, кроме как вдоль другой оси и т. Д., Чтобы получить полную сферу, за 4 шага (создайте восьмую) , дублируйте и переверните три раза). Может быть, излишним, но меньше, чем в случае с кругом.

Простая УФ сфера:
сфера

Фактически мы делаем только половину (например), дублируем эту половину, переворачиваем копию вверх дном и переводим ее по длине капсулы:
половинки

Мы связываем верхнюю и нижнюю половину:
капсула

Настоящая (несколько) тяжелая работа происходит от тригонометрии, которая входит в создание сферы. Множество всех вершин, принадлежащих УФ сфере, можно описать как множество всех точек вида:

точки

где R - радиус сферы, и для некоторого положительного четного целого числа N имеем постоянную

θ = × π / N ,

k и n являются целыми числами, где k варьируется от 0 до 2N-1, а n варьируется от -N / 2 до + N / 2 .

Чтобы сделать полусферу или восьмую сферу, вы должны ограничить набор значений, принимаемых k и n .

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

Страшный тор : это легко после всего, что мы видели!

Опять же, больше тригонометрии, больше вершин, больше квадратов, больше симметрий, больше инвариантов ... больше геометрии! Найдите уравнение для поверхности тора, правильно "растеризуйте его", упростите задачу, используя (очевидные) симметрии тора, и, наконец, проведите цикл по множеству вершин, которые вы только что определили, и сделайте ребра и грани такими, как вы идти!

Видеть? Совершенно просто.

jrsala
источник
Ух ты. Спасибо за такой подробный ответ и за множество примеров. Я не рассматривал идею простого создания половины сферы и отражения симметричных элементов. Большое спасибо за то, что нашли время написать это так, как я могу легко понять и, надеюсь, легко применить на практике.
CaptainRedmuff
Пожалуйста! Мне жаль, что не было кода, хотя
2013 года
Схема методов была больше того, что мне действительно нужно. Я могу начать разрабатывать план действий по крайней мере оттуда:] Я не думаю, что у вас есть какая-либо информация о коробках / кубах с скошенными краями? docs.autodesk.com/3DSMAX/15/ENU/3ds-Max-Help/images/...
CaptainRedmuff