Низкополигональный мост в 3D

Данный код показывает систему 3D-рендеринга, способную создавать и отображать детализированные архитектурные элементы с возможностью интерактивного взаимодействия пользователя.

Управеление (работает когда курсор мыши находится на холсте):

  • Врачение - зажмите ЛКМ и перемещайте курсор
  • Перемещение - зажмите ALT + ЛКМ и перемещайте курсор
  • Масштабирование - используйте колесо мыши

Класс Vector2d представляет двумерный вектор и включает в себя методы для работы с ним.

Класс Vector3d аналогично представляет трехмерный вектор.

Класс Shape3d представляет трёхмерный объект с его геометрией и параметрами отрисовки.
Методы:

  • constructor(vertices, edges, faces, color) - Инициализирует новый объект Shape3d с заданными вершинами, рёбрами, гранями и цветом.
  • transform({ scale, angles, moves }, dist) - Применяет трансформации к вершинам фигуры и вычисляет их 2D-проекции.
  • render(ctx) - Отрисовывает фигуру на холсте с использованием алгоритма отсечения невидимых граней.
  • darkenColor(color) - возвращает более тёмный оттенок заданного цвета. Используется для указания цветы ребер

createRectangles(array, color, isFarthest = false) - создаёт сложные фигуры из массивов прямоугольников в 3D-пространстве, соединённых между собой. Она формирует вершины, рёбра и грани, которые затем используются для построения и рендеринга фигур на основе класса Shape3d.

drawAxes(ctx, { angles, moves }, dist) - Рисует оси координат для ориентации в 3D-пространстве

update() - отвечает за обновление состояния сцены, вычисление трансформаций объектов и их сортировку по глубине (z-координате) и за отрисовку объектов и вспомогательных осей.

Алгоритм отсечения невидимых граней (Алгоритм Робертса) - Реализован в методе Shape3d.render. Вычисляет нормаль каждой грани и её скалярное произведение с вектором обзора. Отрисовываются только грани, направленные к камере (скалярное произведение > 0).

Создание объекта:

  • Используем функцию `createRectangles`, передавая ей:
  • Массив точек фигуры
  • Цвет (например "#FF0000")
  • Флаг `isFarthest` (true, если объект должен быть на заднем плане) - это костыль

На данной строке можно изменить начальные значения в `transform` для изменения начального вида сцены:
let transform = { angles: { x: 0, y: 0, z: 0 }, moves: { x: -3, y: -2.5, z: 15 }, scale: 1 }

Исходники: