Всем привет! Меня зовут Евгений, я backend‑разработчик в компании Bimeister. Сегодня я хочу рассказать о нашем 3D движке Spatium для рендеринга сводных моделей масштаба промышленного предприятия в браузере.
Материал может представлять интерес для разработчиков и пользователей BIM-систем, а также для инженеров и конструкторов, которые выполняют работы по проектированию 3D моделей, получению фотограмметрических моделей и облаков точек для таких систем.
Контекст
Не будет секретом тот факт, что работа с графикой в целом и с 3D-графикой в частности предполагает использование значительных аппаратных ресурсов. И чем выше наши ожидания от качества изображения, от глубины детализации и плавности смены кадров, тем больше этих ресурсов потребуется. И ладно бы, просто картинку отрисовать - хватило бы и видеокарты, так нам интерактив подавай, да подинамичнее. И хранить эту самую графику тоже где-то нужно - в общем, целый набор требований к аппаратной части. И это - первое ограничение. А высокая стоимость таких ресурсов - неприятное следствие из него.
Решить эту проблему можно разными способами, и самый популярный - за счет разделения обязанностей, то есть, архитектурно. Пусть одна часть приложения - клиент - показывает элементы интерфейса, отправляет запросы, принимает данные, помещает их в видеокарту и рисует картинку. А всю логику подготовки, хранения и обработки данных возлагаем на другую часть - производительный сервер. Требования к аппаратной части клиента снижаются, но сразу появляются два недостатка такого подхода - зависимость от наличия подключения к сети и потенциальные ограничения по объему трафика. И это наши ограничения под номерами два и три.
Допустим, что мы построили клиент-серверную архитектуру (подробнее про нее можно прочитать на Хабре или в Википедии, мне лично понравилась вот эта статья) и обеспечили себя безлимитным стабильным подключением к сети. Так давайте поприветствуем разные форматы данных! Часть из них - относительно универсальны, часть - довольно специфичны. Возникает новая проблема - необходимость наличия различных клиентов-приложений для работы с различными форматами. Неприятно. И дорого! И снова вырастают требования на аппаратную часть - эти приложения нужно хранить, и иногда запускать одновременно. И спасением становится неизменный спутник современного человека - веб-браузер. Достаточно универсальная среда выполнения кода, написанного на популярном языке программирования - JavaScript. И самое главное, браузеры можно встретить повсюду: почти любое устройство под управлением наиболее распространенных операционных систем имеет в своем составе браузер - Google Chrome, Safari, Edge и т.д.
В задачах информационного моделирования (BIM) могут быть задействованы - в большей или меньшей степени - 3D-технологии, такие как проектирование в САПР, лазерное сканирование (облака точек), фотограмметрия (подробнее об этом - статья в Википедии и целая книга). Если артефакты этих технологий разместить в едином цифровом пространстве, то результатом будет так называемая сводная модель, которую уже удобно использовать в задачах BIM.
Так как же получить интерактивную сводную 3D модель завода с миллионами элементов в браузере? Ответом будет динамическая сцена. Прежде чем рассмотреть механизм ее работы, остановимся на некоторых определениях.
WebGL
WebGL – кроссплатформенный API для 3D-графики в браузере. WebGL исполняется как элемент HTML5 и поэтому является полноценной частью объектной модели документа (DOM) браузера. Может использоваться с любыми языками программирования, которые умеют работать с DOM (компилируются в WASM) – JS, Rust, C++, C# и Go и т.д.
WebGL – это контекст элемента canvas HTML. Познакомиться с технологией подробнее можно здесь, здесь или здесь.
WebGL выполняется на графическом процессоре компьютера (GPU), и простейшем случае представляет собой набор двух функций: вершинного и фрагментного шейдеров. WebGL использует язык программирования шейдеров GLSL (GL Shader Language).
Шейдер (shader) – программа, выполняемая графическим процессором. Особенность архитектуры GPU – множество параллельных ядер, поэтому шейдеры могут выполняться сразу по несколько тысяч параллельно. Задача вершинного шейдера – вычислять положения вершин. Задача фрагментного шейдера – вычислять цвет для каждого пикселя примитива, который в данный момент отрисовывается.
Frustum
Фрустум - это пространство отсечения или ограниченный объем просмотра. Каждая координата, попавшая во фрустум, окажется на экране, а все, что во фрустум не попало - будет отсечено. Для перспективной проекции используется фрустум в виде усеченной пирамиды, для ортографической проекции - в виде параллелепипеда.
Динамическая сцена
Поскольку клиент ограничен аппаратно, может иметь слабое интернет соединение или не иметь его вовсе (вспоминаем про ограничения из раздела Контекст), то нам потребуются следующие решения:
Поддержка автономного режима.
Оптимизация использования трафика.
Оптимизация использования геометрий.
Алгоритм поиска одинаковых геометрий решает задачи с оптимизацией трафика и переиспользования геометрий. А как организовать автономный режим - вопрос достаточно тривиальный. Поэтому давайте рассмотрим непосредственно механизм формирования динамической сцены:
По положению камеры и направлению "взгляда" формируется фрустум на стороне клиента.
На сервер отправляется запрос объектов, находящихся в данном фрустуме.
На сервере осуществляется поиск по пространственному индексу всех 3D-объектов, попадающих во фрустум из запроса с учетом углового размера и установленного лимита, после чего вычисляется разница между предыдущим запросом и текущим, которая записывается в кэш, а результат возвращается клиенту.
-
Клиент на основании полученной разницы между предыдущим и текущим состоянием сцены:
Удаляет из памяти геометрию "лишних" объектов. Лишние объекты - это объекты вне области видимости и превысившие установленный лимит.
Запрашивает геометрию объектов, которой не хватает для отображения объектов из текущей области видимости. С сервера геометрия передается в удобном для WebGL и GPU виде.
По мере загрузки геометрий, формируются коллекции одинаковых геометрий, которые могут быть отрисованы за один кадр. Одиночные геометрии и коллекции геометрий отправляются на рендеринг в видеокарту.
На каждую смену положения камеры формируется новый фрустум и цикл повторяется.
Таким образом, пользователь видит только те объекты, которые находятся перед камерой с учетом ее положения и настроек. Фрустум не передается целиком, а кэшируется. Для экономии траффика и оптимизации работы с памятью применяется переиспользование геометрий.
Spatium
Итак, Spatium — это инструмент для работы с 3D-графикой в контексте клиент-серверных web-приложений, ориентированный на сводные модели масштаба промышленного предприятия. Физически представляет собой совокупность docker образов с приложениями обработки 3D данных, а также набор npm и nuget пакетов для интеграции с ними.
Движок разработан с использованием открытого ПО и поддерживает парсинг (импорт) следующих форматов:
САПР - ifc, rvm+att, nwd, ipt
Фотограмметрия - obj + mtl + png/jpg/jpeg
Лазерное сканирование - pts, e57, las, laz
Динамическая сцена в Spatium может одновременно отрисовывать до 150 тысяч геометрий и до 30 миллионов точек лазерного сканирования, при этом в сводной модели количество объектов может исчисляться миллионами. Производительность при этом будет ограничена аппаратными средствами клиента.
Вместо заключения
Технология WebGL не нова и широко применяется для создания 3D контента и игр в вебе. Если поверх этой технологии организовать динамическую сцену, снабдить ее алгоритмами для оптимизации памяти и трафика, то появится возможность побывать в огромном виртуальном заводе без использования специализированных программ-клиентов - а это открывает широкий простор для автоматизации промышленности.
Разработка движка Spatium была выполнена ООО "Бимэйстер Холдинг" при поддержки Фонда содействия развитию малых форм предприятий в научно-технической сфере, в рамках реализации инновационного проекта «Исследование алгоритмов оптимизации 3D-моделей для отображения высокодетальных цифровых двойников в информационных системах управления предприятием».