¬аше окно в мир —јѕ–
Ќовости —татьи јвторы —обыти€ ¬акансии Ёнциклопеди€ –екламодател€м
—татьи

20 но€бр€ 2023

“ехнологии создани€ графических веб-приложений на примере C3D Web Vision

—ергей  лимкин, руководитель группы C3D WebVision, C3D Labs

—ергей  лимкин


ќригинал в блоге компании C3D Labs


ѕоследние три года € занимаюсь разработкой компонента C3D Web Vision. Ёто модульное клиент-серверное решение дл€ визуализации 3D в браузере, которое легко интегрируетс€ с любым веб-приложением. я поделюсь нашим опытом разработки и инструментами, которые мы используем при разработке C3D Web Vision. ѕредлагаю рассмотреть графический API, используемый в браузере, сборку проекта C++ под веб и работу с микросервисом.

ѕервые шаги

C3D Labs начала разработку веб-визуализации три года назад. ” нас уже был опыт создани€ десктопных продуктов. ѕеред стартом разработки мы посмотрели на наше приложение C3D Viewer и подумали, как его перенести в веб-среду. ¬ыделили основные модули Ч модуль десктопной визуализации C3D Vision, модуль математики C3D Modeler, модуль конвертора C3D Converter, бизнес-логику, написанную на C++, и графический интерфейс на Qt.  омпоненты C3D Modeler и C3D Converter перенесли на сторону сервера, модули без проблем работают на backend без наших дополнительных доработок. Business logic решили реализовать на TypeScript, чтобы св€зать ее с интерфейсом. ƒл€ реализации интерфейсной части мы вз€ли фреймворк Vue. ¬ качестве библиотеки визуализации мы решили оставить собственное решение Ч C3D Vision, собрать в Web Assembly, это была сама€ сложна€ часть разработки.

TypeScript

¬ браузере выполн€етс€ JavaScript, но на самом деле большинство программистов не хочет работать с JavaScript. ѕричиной этому €вл€етс€ то, что это сложный €зык, динамический, не типизированный, в нем посто€нно можно Ђнаступать на граблиї. ¬ основном разработка ведетс€ на TypeScript. Ётот €зык типизирован, есть возможность реализовывать объекты классов. » мы не стали исключением, вс€ frontend-часть проекта у нас написана на TypeScript. Ќа рис. 1 слева вы видите написание класса на TypeScript, а справа это результат сборки TypeScript в JavaScript.

C3D Web Vision 1

–ис. 1

—огласитесь, TypeScript выгл€дит при€тнее, а на этапе отладки разобратьс€ в JavaScript будет уже т€желовато.

” TypeScript и JavaScript есть модули. ¬ основном программисты, когда разрабатывают программный продукт, разбивают его на отдельные части, куски Ч логически выдел€ют файлы, подпапки и модули. “ак же можно сделать и в TypeScript. ≈динственна€ проблема в том, что JavaScript работает не только в браузере, но и может функционировать на backend под управлением node. ѕоэтому разновидностей модулей дл€ JavaScript очень много Ч commonjs, umd, amd. ѕример того, как выгл€д€т эти модули, изображен на рис. 2.

C3D Web Vision 2

–ис. 2

—лева изображен пример, написанный на TypeScript, а справа вы видите umd-модуль, с которым работать не очень удобно. ѕричем к правому модулю нужно подключать зависимую стороннюю библиотеку, чтобы все заработало в браузере.

Modules: commonjs, umd, amd

–азработчики могут разрабатывать собственные модули, как мы и сделали с модул€ми визуализации, и делитьс€ с другими разработчиками. ¬ состав модул€ обычно входит package.json, сам JavaScript и описание TypeScript. — помощью такого инструмента, как npm, можно подключать внешние модули в свой проект и публиковать их дл€ других пользователей. Ќа рис. 3 можно увидеть примерное подключение npm-модул€.

C3D Web Vision 3

–ис. 3

ѕосередине рисунка изображен package.json, внизу располагаетс€ devDependencies, где мы подключили наш C3D Vision wasm. —права показано, как мы с ним работаем внутри самого исходного кода. ћы делаем импорт обычного модул€ и начинаем его использовать. Ќа этапе, когда мы уже работаем с внешними модул€ми, в директории проекта по€вл€етс€ папка node_modules, на этапе инсталл€ции в нее подкачиваютс€ все зависимые модули.

ƒл€ того чтобы из большого массива исходных файлов собрать уже готовый модуль, мы использовали webpack. Webpack очень мощный инструмент, он позвол€ет подключать ресурсы к сборке проекта, подключить компил€тор TypeScript, уменьшать результирующий файл со скриптами, включать в проект разные типы модулей, генерировать проект под браузер или node и т. д.

Worker, многопоточность, promise

¬ своей практике € сталкиваюсь с тем, что иногда разработчики не вид€т различий в таких пон€ти€х, как многопоточный и асинхронный код. јсинхронный код может работать как в нескольких потоках, так и в одном. ћногопоточна€ программа тоже может быть синхронной и асинхронной, например, когда вы смотрите фильм, обработка звука и картинки выполн€етс€ в разных потоках, но синхронно, чтобы голос не отставал или убегал от картинки. ¬ браузере весь код выполн€етс€ асинхронно.

Ќа рис. 4 изображен Task 1:

C3D Web Vision 4

–ис. 4

” первой задачи выполн€етс€ запрос на загрузку (она что-то загружает, запрашивает какой-то файл с сервера), и после ожидани€ загрузки запускаютс€ Task 2 и Task 3. Ќо мы можем с помощью promise решить эту задачу таким образом Ч запустить загрузку, а в то же врем€ будут выполн€тьс€ следующие задачи. “ут можно сказать, что в этом случае все работает в два потока, но давайте рассмотрим другой пример.

≈сли у нас есть долга€ по времени задача, € рекомендую ее делить на маленькие таски (рис. 5). ƒелать в какой-то период времени тайм-ауты, чтобы можно было, например с помощью UI, прервать задачу. »наче может получитьс€ так, что мы на двадцать секунд заблокировали браузер и он больше не отвечает на наши запросы, а пользователь будет посто€нно открывать-закрывать вкладку браузера и не понимать, почему все зависает.

C3D Web Vision 5

–ис. 5

¬ браузере можно выполн€ть код в нескольких потоках. ƒл€ этих целей предусмотрены webworker. Webworker Ч это отдельный поток или процесс (рис. 6), он позвол€ет выполн€ть долгоиграющие задачи отдельно от основного потока. —уществует два вида worker Ч shared и обычные. »х отличие в том, что shared worker можно использовать между двум€ разными вкладками браузера. Ќапример, вы запустили яндекс.ћузыка Ч дл€ прослушивани€ в одной вкладке, а потом открываете вторую вкладку и можете управл€ть плеером там.

C3D Web Vision 6

–ис. 6

’очетс€ дополнить про работу с данными между потоками. Ќельз€ получить доступ к данным из другого потока, их необходимо передать (скопировать) через механизмы сообщений. Ѕольшие данные, такие как массивы, можно перемещать.

Local store, offline mode

—уществует еще один вид worker Ч service worker. ≈го отличие от обычного и shared worker состоит в том, что он работает даже тогда, когда браузер выключен. ќн необходим дл€ реализации такой задачи, как offline mode Ч инструмент, который позвол€ет нам реализовать режим работы с данными без подключени€ к »нтернету. Ќапример, мы подключились к рабочей сети, чтобы открыть модельку, синхронизировали данные с сервером и потом поехали в командировку. ¬ первом случае в service worker мы могли сохранить данные в кэше браузера, а во втором случае сервис выступил бы в виде офлайн-сервера и подн€л бы нам все данные из кэша браузера. ƒл€ работы с данными существует четыре вида хранилища:

  • IndexDB Ч хранилище базы данных;
  • LocalStorage Ч хранилище дл€ ключа значени€;
  • SessionStorage Ч хранилище дл€ ключа значени€;
  • Storage Ч хранилище, которое позвол€ет использовать 50% диска.

API дл€ визуализации в браузере

— выходом HTML5 по€вилс€ такой тег, как canvas, позвол€ющий рисовать в браузере 2D и 3D-графику. Ќа сегодн€шний день дл€ визуализации 3D доступны WebGl и WebGl2. ¬ 2022 году WebGL2 стал официально поддерживатьс€ на всех устройствах, сегодн€ всем разработчикам рекомендуют переходить на WebGl2. API WebGL почти полностью отражает возможности на OpenGL ES, но есть небольшие отличи€ в некоторых функци€х. Ќапример, при работе с пам€тью: так как у браузера есть сво€ особенность работы с пам€тью, такие функции, как glMapBufferRange, недоступны в вебе. ќна реализована через функцию glGetBufferSubData, а в OpenGl ES нет этой функции.

 то работал с OpenGL, знает про такую возможность, как shared context, Ч возможность рисовать в двух окнах одну и ту же модель одновременно. ¬роде как в браузере тоже есть shared context (в документации), а на самом деле ни один браузер не поддерживает shared context. ¬ыход есть Ч это offscreen context. Ќапример, мы можем рисовать не в канву (canvas), а сразу рисовать в картинку, а картинку, в свою очередь, выводить на canvas. ≈сли использовать offscreen context совместно с shared web worker, то есть возможность рисовать в двух вкладках одновременно. Ёто очень удобна€ возможность, если у вас более одного монитора Ч интерфейс управлени€ можно вывести в одну вкладку, а визуализацию 3D-модели вытащить на другую вкладку и тем самым разделить управление и визуализацию (рис. 7).

C3D Web Vision 7

–ис. 7

Ќапример, на одной вкладке выбираем узлы модели в интерфейсном представлении дерева модели, на другой отрабатываем выделение графической части в окне визуализации, подсвечива€ необходимую геометрию.

¬ третьем квартере 2023 года запланирован выпуск WebGPU Ч это уже более продвинута€ графика на основе Vulcan и DirectX 12. ќна уже доступна в браузере дл€ разработчиков, но в пользовательских браузерах ее еще нет.

C++ в браузере

—амое интересное то, как мы решили собирать проект C++ под веб. —уществует такой компил€тор, как Emscripten. ќн позвол€ет собрать проект C++ дл€ выполнени€ в вебе, по итогу мы получаем два файла Ч JavaScript и WebAssembly. Wasm Ч это ассемблерный код дл€ браузера, т. е. браузер воспроизводит его так же, как и JavaScript. Ќа рис. 8 показано, как выгл€дит исходный текст на C++, который мы собрали, а справа Ч инициализаци€ собранного модул€, который выведет текст в output.

C3D Web Vision 8

–ис. 8

ћодуль hello.js подключаетс€ к странице в виде глобальной переменной, к которой добавл€етс€ функци€-обработчик onRuntimeInitialized. Ёта функци€ вызываетс€, когда wasm скомпилирован браузером и инициализированы все binding, после этого мы можем использовать функции из wasm.

emscripten очень хорошо интегрируетс€ с CMake и conan. ƒл€ того чтобы использовать внешние conan-библиотеки дл€ веб-сборки, необходимо в рецепте указать архитектуру wasm. ј дл€ сборки зависимостей под веб необходимо в зависимость добавить emsdk_installer. Ќа этапе сборки conan подменит компил€тор из системы (например gcc) на emcc. ¬ составе emsdk есть заголовочные файлы, которые мы можем использовать в проекте. Ќапример, мы можем использовать OpenGL, а на этапе сборки он подмен€ет функции OpenGL на функции WebGl. ƒл€ нас ничего не мен€етс€ Ч у нас как был кроссплатформенный код, так он и остаетс€.

ƒл€ того чтобы была возможность вызывать функции C++ из JavaScript, на этапе сборки у нас есть два варианта св€зки (binding) Ч Embind (который мы используем) и WebIDl.

Ќа рис. 9 слева представлен список типов, который можно использовать. ” Embind намного больше возможностей:

C3D Web Vision 9

–ис. 9

“ак это выгл€дит внутри исходных кодов (рис. 10):

C3D Web Vision 10

–ис. 10

—лева с помощью специальных макросов мы описываем класс, как будет он выгл€деть в JavaScript. —права мы пишем definition, который описывает нам, как он выгл€дит в TypeScript. “ак как результатом сборки €вл€етс€ JavaScript-файл, а мы работаем с TypeScript, то TypeScript definition нам приходитс€ описывать вручную.

—борка проекта C++ под веб: проблемы

–езультатом сборки проекта —++ под веб €вл€етс€ модуль JavaScript, а именно экспортна€ функци€, котора€ загружает wasm-файл дл€ компил€ции и возвращает promise с модулем. Ќемного нестандартное поведение дл€ модул€, поэтому есть проблемы с описанием его в TypeScript. ƒл€ решени€ проблемы мы реализовали обертку, котора€ экспортирует объект с функцией инициализации модул€. ≈ще есть проблемы с зависимост€ми от wasm-файла: так как мы поставл€ем библиотеку визуализации, то всегда есть условие, что wasm-файл должен быть подключен в проект, и про него не нужно забывать. Ќа помощь приходит webpack, позвол€ющий собрать проект таким образом, что wasm-файл будет содержатьс€ как ArrayBuffer в проекте.

≈сть еще несколько нюансов, про которые необходимо знать при сборке C++ под веб. ѕервое то, что дл€ объектов, созданных в модуле C++, необходимо вызывать деструктор, так как ресурсы используют wasm-пам€ть (эмул€ци€ кучи). ƒл€ JavaScript используетс€ garbage collector, а дл€ объектов —++ garbage collector не работает, потому что вс€ пам€ть дл€ объектов —++ представл€етс€ в одном array buffer. — этим можно смиритьс€, главное не забыть вызвать деструктор.

¬торое Ч у нас есть ограничение по пам€ти в два гигабайта по умолчанию. ≈го можно расширить до четырех гигабайт с помощью опции компил€ции, но можно столкнутьс€ с проблемой OpenGl, потому что в компил€торе есть ошибки, именно в модуле OpenGL. ћы смогли пропатчить компил€тор и исправить эти ошибки, а именно добитьс€ правильной работы OpenGL при использовании 4 √б пам€ти. Ќо сами вкладки тоже имеют ограничение четыре гигабайта в браузере.

“ретье Ч у нас медленные вызовы функций C++ из JavaScript, это описано в документации. —++ все-таки типизированный €зык, а JavaScript все равно, какую переменную использовать, и внутри стоит много проверок Ч передали нам указатель или нужную переменную и т. д., поэтому вызов C++ из JavaScript выполн€етс€ медленно. ѕредложение Ч поменьше вызывать функции —++ из JavaScript, если такое возможно. ” нас были проблемы с загрузкой данных, например при загрузке большой сборки. “ам очень много мелких объектов, и на них мы получали большую потерю производительности. Ќам пришлось перенести всю сборку на уровень C++. ¬сю реализацию мы уже делаем внутри C++, на уровне TypeScript мы выдел€ем с помощью внешних функций кусок пам€ти, кладем туда загруженный буфер, а потом сериализуем плюсовые объекты внутри wasm-модул€. Ёто дало нам существенный прирост в производительности.

≈ще существует проблема с инструментами отладки. “ак выгл€дит отладка кода C++ в браузере, рис. 11:

C3D Web Vision 11

–ис. 11

ѕосередине кусок кода, мы можем поставить точку на отладку, прийти туда, но никогда не увидим там переменные, что и кака€ переменна€ означает. ћы можем это увидеть справа под номерами var23, var24. ≈сть небольшой стек справа, но он не очень информативный.


¬ данном материале € рассказал про опыт разработки front-части графических веб-приложений на примере C3D Web Vision. Ёто наш взгл€д на разработку веб-версий программных продуктов. Ќадеюсь, этот опыт будет полезен и поможет компани€м-разработчикам в создании веб-приложений.



¬акансии:

јктуальное обсуждение

RSS-лента комментариев

-->

ƒавид Ћевин
ƒавид Ћевин
ќт редактора: «вЄзды импортозамещени€, запрет изображени€ €блока и другое
ѕроект ЂЌародное —јѕ–-интервьюї

—лучайна€ стать€:

 ак сократить врем€ при повторных проверках проектной документации, использу€ [...] — јмир »слам, ¬адим ѕронин, ƒмитрий ћедведев, ѕавел ќстапенко (14 но€бр€ 2023)
isicad Top 10

—амые попул€рные материалы

   ‘орумы isicad:

isicad-2010 isicad-2008
isicad-2006 isicad-2004

ќ проекте

ѕриглашаем публиковать на сайте isicad.ru новости и пресс-релизы о новых решени€х и продуктах, о проводимых меропри€ти€х и другую информацию. јдрес дл€ корреспонденции - info@isicad.ru

ѕроект isicad нацелен на

  • укрепление контактов между разработчиками, поставщиками и потребител€ми промышленных решений в област€х PLM и ERP...
ѕодробнее

»нформаци€ дл€ рекламодателей


¬се права защищены. © 2004-2023 √руппа компаний «Ћ≈ƒј—»

ѕерепечатка материалов сайта допускаетс€ с согласи€ редакции, ссылка на isicad.ru об€зательна.
¬ы можете обратитьс€ к нам по адресу info@isicad.ru.