Главная » Хабрахабр » [Из песочницы] Использование функций JavaScript для построения 3D-моделей

[Из песочницы] Использование функций JavaScript для построения 3D-моделей

В данной статье рассмотрено применение геометрической библиотеки функций WebGeometry для построения моделей сложных многогранников. Библиотека написана на языке Javascript. Ссылка на GitHub с примером, в котором приведен простейший пример использования библиотеки. Замечания и критика приветствуются.

Холст (canvas) HTML5 используется для показа отдельных плоских элементов моделей и вывода на экран вспомогательной информации.
Технология WebGL и библиотеки созданные на ее основе, такие как ThreeJS и BadylonJS, используются в интернете для реализации самых разных целей, связанных с 3D графикой. Для отображения моделей, предварительно рассчитанных с помощью функций из библиотеки WebGeometry, применяется библиотека ThreeJS. Если перед нами встает задача создания параметрической модели, то есть такой модели, у которой, в процессе отображения в браузере уже готового объекта, мы можем изменить его отдельные элементы при помощи задания соответствующих параметров модели (например увеличить угол наклона некоторой грани), нам необходимо иметь набор геометрических функций, которые позволят создать модель таким образом, чтобы в дальнейшем существовала возможность интерактивно варьировать форму отдельных элементов модели или в целом всей модели. Но в основном они находят применение для отображения в браузере уже готовых трехмерных моделей (предварительно созданных, например, в программах 3ds Max или Blender). В библиотеке должны присутствовать функции для создания прямых, плоскостей и окружностей, нахождения точек (или прямых) пересечения их между собой, создания наклонных плоскостей и многое другое. Для решения этой задачи нам потребуется набор функций на языке Javascript, которые будут реализовывать методы применяемые в аналитической геометрии. Существуют еще несколько чисто математических Javascript библиотек. В библиотеках ThreeJS и BadylonJS некоторые из этих возможностей присутствуют, но количество осуществляемых с помощью них действий не позволит выполнить все возникающие задачи при построении параметрической модели. Библиотека glMatrix в основном предназначена для работы с векторами, матрицами и кватернионами, но функций для работы с прямыми и плоскостями в ней нет. Из них наиболее широкое распространение получили glMatrix и Sylvester. Однако существует несколько книг в которых описана реализация методов аналитической геометрии на языке C/C++. В библиотеке Sylvester эти функции есть, но присутствуют они в достаточно ограниченном количестве. Поэтому, когда я решил создать трехмерные параметрические модели огранок алмазов для отображения их в браузере, библиотека ThreeJS была выбрана мной только для вывода на экран уже рассчитанных моделей — для расчета формы моделей она не использовалась. Соответствующие программы на C/C++ можно использовать как прототипы при создании математической библиотеки на Javascript. За основу этой библиотеки были взяты ранее использованные мной геометрические функции на C/C++, которые я перевел на язык Javascript. Для самого расчета формы была создана библиотека WebGeometry. Рассмотрим этапы построения модели пирамиды (огранка алмаза типа Pyramid).

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

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

0, 3, 2, 1, 0; // грань 0 - площадка 0, 4, 7, 3, 0, // грань 1 - корона 1, 5, 4, 0, 1, // грань 2 - корона 2, 6, 5, 1, 2, // грань 3 - корона 3, 7, 6, 2, 3, // грань 4 - корона

Обход граней следует производить против часовой стрелки. В файле pyramid_index.js приведен исходный текст обхода всех граней пирамиды и подробные комментарии. Результат обхода записывается в массив index_cut.

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

С этой целью создается файл pyramid_colors.js в котором находится функция facet_colors() которая осуществляет запись цветов всех граней в массив colors.

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

var DEGREE = 0.01745329251994; // величина углового градуса в радианах var lw = 1.2; // отношение длина/ширина модели var r = 0.06; // высота рундиста модели огранки
var angleA = 50*DEGREE; // угол наклона грани A короны var angleB = 60*DEGREE; // угол наклона грани B короны var hCrown = 0.3; // высота короны
var anglePav = 60*DEGREE; // угол наклона грани A павильона

Выбор параметров определяется разработчиком модели. Например, вместо задания двух параметров для двух углов наклона короны, можно задавать единственный параметр сразу для двух углов – тогда эти углы всегда будут одинаковыми. Можно ввести параметр определяющий размер площадки. В этом случае требуется либо не задавать высоту короны, либо не задавать наклон ее граней. Еще один вариант выбора параметров состоит в том, чтобы некоторые параметры сделать вычисляемыми. В этом случае при изменении одних параметров некоторые другие могут менять свое первоначальное значение. Например, если предположить, что для пирамиды мы определили один параметр для задания угла наклона граней короны, другой параметр для высоты короны и и еще один параметр, который будет задавать размер площадки, то при изменении наклона граней мы будем вынуждены изменять либо размер площадки, либо высоту короны. С другой стороны, если изменить параметр задающий размер площадки, то автоматически изменится значение параметра задающего либо высоту, либо наклон граней короны. Вариант связанный с применением вычисляемых параметров в данной программе, а также и при построении остальных моделей огранок, приведенных на сайте, не используется.

Исходными данными для расчета являются значения параметров модели и то как мы представляем себе ее внешний вид. На четвертом этапе производится расчет координат вершин модели. Именно при этом расчете в этой функции и используются функции библиотеки WebGeometry. В файле pyramid_verts.js приведен исходный текст (с подробными комментариями) функции расчета вершин модели, которая имеет название VerticesCalculation. Заметим, что в программе нахождения координат вершин применяются отдельные последовательности номеров для вершин входящих в состав короны (четыре вершины), вершин входящих в состав рундиста (четыре вершины) и вершин входящих в состав павильона (в модели пирамида в состав павильона входит только вершина). Результаты расчета координат вершин заносятся в массив vertices. Такой выбор дополнительной нумерации вершин применяется для более простой ориентации программистом среди вершин огранки, так как количество вершин очень часто превышает число 100.

Исходными данными для его построения служат ранее созданные массивы index_cut, colors и vertices. На пятом этапе после того как расчет координат вершин закончен, требуется программно построить многогранник (полихедрон) модели. Функция CreatePolyhedron находится в файле polyhedron.js. Полихедрон модели можно представить просто как набор граней, которые ограничивают многогранник в пространстве. Каждый полигон описывается следующей функцией (фактически это функция-конструктор вызываемая оператором new при создании нового полигона): В результате работы этой функции создается массив полигонов (многоугольников) из которых состоит трехмерная модель.

function Polygon()
{ this.IndexFacet = []; // индексы вершин грани без дублированной // первой вершиной грани this.IndexFacet_1 = []; // индексы вершин грани с дублированной // первой вершиной грани this.VertexFacet; // массив, содержащий координаты каждой // вершины данной грани this.EdgeFacet = []; // массив, содержащий индексы, // определяющие ребро грани (каждый элемент массива содержит //два индекса вершин) this.IndexTriangle = []; // массив, содержащий индексы каждого // треугольника, из которых состоит грань this.VertexTriangle = []; // массив, содержащий координаты каждой // вершины каждого треугольника, из которых состоит грань this.Faces = []; // смотри комментарий в тексте программы
}

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

Стандартным образом создается сцена, рендерер и камера. На шестом этапе производится отображение модели на экране посредством функций ThreeJS. При создании других моделей огранок, с целью осмотра огранок со всех сторон я использовал не orbitControls, а ввел возможность вращения самой модели. Для того, чтобы осмотреть модель огранки со всех сторон в программе Pyramid используется элемент orbitControls. Можно поступить двумя способами. Затем мы создаем меши модели.

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

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

При нажатии кнопки вызывается функция которая производит увеличение или уменьшение значения соответсвующего параметра. На седьмом этапе создаются кнопки и привязанные к ним функции, которые позволяют изменять значение параметров определяющих форму и размер модели. После пересчета проверяется корректность вновь построенной модели. Это означает, что необходимо пересчитать значение координат вершин модели. В случае моделей огранок алмазов обычно это сводится к проверке того, осталась ли выпуклой огранка после ее перестроения. Например определяется не выходят ли некоторые значения из допустимых пределов. Через каждую грань проводится плоскость, в которой эта грань лежит, и затем определяется положение каждой вершины модели относительно этой плоскости. Проверка выпуклости производится следующим образом. Если модель признана некорректной, то производится возвращение к исходному значению измененного параметра и модель снова перестраивается. Все вершины должны быть расположены по одну и ту же сторону от этой плоскости. Рундист, при этом, исключается из проверки. Для моделей огранок имеющих невыпуклый рундист (только этот элемент некоторых огранок, таких как Heart, может быть невыпуклым) проверка выпуклости производится отдельно для короны и отдельно для павильона. Например, если мы конструируем модель дома, то крыша не должна быть по высоте больше некоторого, наперед заданного, значения. Для простых моделей можно ограничиться простой проверкой параметра. После того как добавлены кнопки параметров очень желательно произвести визуальное отображение значения каждого параметра при его изменении после нажатия на кнопку. Поэтому просто задав ограничение этого параметра по величине, мы получим требуемый результат. Для этого создается двумерный холст (canvas) HTML5 и рядом с соответствующей кнопкой на него выводится значение параметра.

Для пирамиды (впрочем, как и для всех остальных моделей на сайте) мной создана еще одна программа Pyramid_text.html. Таким образом мы рассмотрели все этапы построения модели на примере Pyramid. Если кто-то захочет узнать как строятся сложные модели, то следует рассмотреть построение моделей (смотри GitHub) в следующей последовательности:
Octagon. На примере этой программы показано как можно выводить трехмерный текст для нумерации вершин модели. При построении модели также используются методы используемые при работе с векторами и прямыми в пространстве. Модель в которой демонстрируется создание плоскостей различными способами и работа с этими плоскостями.

Это классическая и наиболее распространенная огранка алмазов. Brilliant. Как рассчитывается рундист этой огранки, имеющей форму суперэллипса, показано отдельно в программе BrilliantGirdlt.html. Некоторые элементы построения трехмерной модели этой огранки применяются в дальнейшем при создании огранок MoonMarquise, MoonPear и Heart. В этой программе линия рундиста строится на двумерном холсте (canvas).

Огранка типа Marquise, также как и Brilliant, является одной из классических огранок алмазов. MoonMarquise. Рундист огранки МoonMarquise образован двумя дугами эллипсами. В отличие от простой огранки этого типа (Marquise) в огранку MoonMarquise на павильон добавлены так называемые “лунные” грани (moon facets). В тексте этой программы есть подробные комментарии к построению. Подробное построение этого рундиста на холсте показано в программе MarquiseGirdle.html. Оно рассматривается, например, в книге «Курс аналитической геометрии» (автор этой книги — Н.И.Мусхелишвили).
MoonPear. Отметим один момент касающийся расчета линии рундиста – в нем используется свойство касательной к эллипсу. Его построение основано на построении рундиста огранки Marquise, но является более сложным. Рундист огранки МoonPear образован дугами трех эллипсов. Увидеть линию рундиста Marquise и способ разделения рундиста на сегменты, можно запустив программу PearGirdle.html.

Огранка “сердце” является одной из классических огранок, но она имеет, в отличие от большинства типов огранок, невыпуклую форму рундиста. Heart. На холсте можно увидеть линию рундиста запустив программу HeartGirdle.html. Рудист огранки сердца составлен из двух наклоненных относительно друг друга рундистов огранок Pear. Построение огранки Heart представляет собой достаточно сложную задачу.

Рундист огранки “Мальтийский крест” выполнен в форме “подушки” (cushion). Maltese Cross. Линия этого рундиста представляет собой восемь сопряженных дуг окружностей – четыре основные дуги окаймляющие подушку с четырех сторон и четыре дуги меньшего размера производящие сопряжение основных дуг подушки по углам рундиста. Огранки с таким рундистом получили в последнее время широкое распространение. Запустив программы CushionGirdle_1.html и CushionGirdle_2.html можно увидеть форму линии рундиста, работу всех параметров задающих его форму и деление рундиста на сегменты.

Рундист огранки “Пятиугольная звезда” образован линией носящий название эпитрохоида. Pentagonal Star. В программе Wavy_Pentagon_Girdle.html путем изменения значений параметров можно изменить “волнистость” рундиста и даже изменить пятиугольник на многоугольник с другим количеством выступов (“лепестков”). Эпитрохоида является кривой родственной циклоиде. Следует однако помнить, что сама модель этой огранки построена для значения параметра “Number of petals” равным 5.

В этих программах сделано переключение между сквозной индикацией всех вершин модели и индикацией номеров вершин для короны, рундиста и павильона по отдельности. Как уже упоминалось ранее, для всех вышеупомянутых моделей созданы программы отображающие номера вершин огранок. Вместо того, чтобы при создании плоскости при помощи функции CreatePlaneThreePoints использовать эти номера для идентификации точек через которые проходит плоскость, гораздо более наглядной является запись использующая отдельную нумерацию вершин для рундиста и павильона: Предположим, что в модели огранки Maltese требуется создать плоскость проходящую через вершины имеющие номера 84, 88 и 145.

var plane = new Plane3D();
plane.CreatePlaneThreePoints(girdle[68], girdle[72], crown[1]);

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

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


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Как открыть ИП в Германии, если ты программист, и не набить шишек

В последние недели Берлин — популярная тема на Хабре. Не случайно — в Германии много возможностей для работы в ИТ с комфортным переездом. Но бюрократия она и в Африке бюрократия, а если встают вопросы об индивидуальном предпринимательстве за рубежом — ...

4 октября, Москва — Backend Stories 2.0

В четверг, 4 октября, на площадке Deworkacy (ул. Большая Полянка, д.2/10, стр 1) мы проведём митап для backend-разработчиков. 00, подробности — под катом.19:20–19:30, Павел Дерендяев, вступительное слово. Начинаем в 19. 30–20:10, Иван Походня, «Как мы хотели в Java 11 и ...