3D в браузере кажется сложным. Со правильным стеком — это обычная инженерия
Когда заказчик говорит «нужен 3D-конфигуратор», в голове часто всплывает тяжёлая картинка: CAD, дорогое моделирование, Unreal, отдельная 3D-команда, месяцы до первого демо.
На практике для многих product-конфигураторов это не та задача. Нужен не фотореализм ради фотореализма, а понятная сцена, в которой пользователь:
- видит изделие;
- меняет параметры;
- ставит элементы;
- сразу получает спецификацию.
Именно такой MVP мы собрали для конфигуратора внутреннего наполнения ящиков Blum AMBIA-LINE: системы LEGRABOX / MERIVOBOX / TANDEMBOX, каталог разделителей, drag в 3D, snap, коллизии, печать заказа.
Короткий ответ: сложность 3D взрывается, когда вы тащите CAD-мышление в веб. Она падает, когда стек разделён на три слоя — UI, доменная логика размещения, лёгкий WebGL-рендер — и модели процедурные, а не «все STEP-файлы мира».
Какую задачу решали
Нужен был веб-демо для дистрибьюторского/клиентского контура Blum:
- выбрать систему ящика;
- задать внутренние размеры (ширина 450–1300 мм и связанная глубина);
- выбрать цвет фасада;
- добавить элементы AMBIA-LINE из каталога;
- разместить их в ящике (drag, поворот 90°, копия, удаление);
- видеть свободные зоны и snap к стенкам;
- сформировать спецификацию заказа и распечатать.
Это классический product configurator, а не digital twin завода. Значит, и стек должен быть product-web, а не CAD-pipeline.
Почему 3D часто кажется сложнее, чем есть
| Страх команды | Что обычно имеется в виду | Что нужно для конфигуратора |
|---|---|---|
| «Нужны дорогие 3D-модели» | Полные CAD/GLTF со всеми фасками | Узнаваемая процедурная геометрия |
| «Нужен отдельный 3D-движок» | Unity/Unreal | WebGL через Three.js в браузере |
| «Нужна физика» | Полноценный physics engine | 2D AABB-коллизии на полу ящика |
| «Нужен сложный state» | Свой event-bus на всё | Один store (Zustand) + React |
| «Долго до первого результата» | Пайплайн ассетов | Скелет сцены за дни, не месяцы |
Главная ошибка — смешать визуализацию и бизнес-логику в одном комке мешей. Тогда любое правило «не ставь в стенку» превращается в отладку Three.js вместо простой геометрии на миллиметрах.
Правильный стек для этой задачи
| Слой | Технология | Роль |
|---|---|---|
| Приложение | Vite + React 19 + TypeScript | Быстрый SPA, строгие типы |
| Состояние | Zustand | Система ящика, размеры, placed items, selection |
| 3D | React Three Fiber + drei + Three.js | Сцена, свет, камера, меши |
| Логика | Чистые utils (geometry.ts, placement.ts) |
Коллизии, snap, свободные зоны |
| Данные | catalog.ts, drawerGeometry.ts |
Артикулы, габариты, параметры систем |
Почему именно так:
- React Three Fiber даёт Three.js в привычной React-модели: компоненты, props, хуки. Не нужно писать «второй фреймворк» на голом
requestAnimationFrame. - Zustand держит конфигурацию вне Canvas. UI-панели и 3D читают один источник правды.
- Процедурные меши (
box, простые материалы) закрывают 80% узнаваемости без склада GLB. - Геометрия в мм считается в обычном TypeScript; в сцену уходит только масштаб
1 unit = 10 mm.

Итоговая схема:
LeftPanel / RightPanel (DOM)
│
useConfiguratorStore (Zustand)
│
Scene3D (R3F Canvas)
├── DrawerBox
├── PlacedItemMesh
└── SnapGuides / FreeZones
│
geometry.ts + placement.ts
3D здесь — view. Правила — отдельный слой. Это и делает задачу управляемой.
Как устроено «моделирование» без CAD
Ящик
DrawerBox собирается из примитивов: дно, стенки, фасад, ручка, направляющие. Параметры систем (толщины, металл боковин, reveal фасада) лежат в drawerGeometry.ts.
Меняется система или цвет — меняются материалы и размеры, а не «переимпортируется модель».
Элементы каталога
Каждый товар в каталоге имеет:
- реальные артикулы/цены (для демо);
- габариты в мм;
visualType— какой процедурный шаблон рисовать вCatalogItemModel.
Новый товар чаще всего = новая запись в данных + при необходимости один case визуала. Не полноценный 3D-пайплайн.
Почему этого достаточно
Для конфигуратора важны:
- пропорции;
- занятое место на полу;
- понятный drag;
- читаемая спецификация.
Фотореалистичный AMBIA-LINE с микрофасками на демо почти не добавляет конверсии, зато сильно добавляет срок и стоимость.

Настоящая сложность — не меши, а размещение
Именно здесь обычно «ломается» ощущение простоты. Но и она хорошо решается, если не тащить её в шейдеры.
| Задача | Решение в проекте |
|---|---|
| Поворот 0/90/180/270 | getRotatedSize() — footprint отдельно от 3D rotation |
| Не выходить за стенки | isInsideDrawer + margin |
| Не пересекаться | AABB 2D + COLLISION_GAP |
| Drag с «скольжением» | resolveDragPosition |
| Прилипание | applySnapping (порог ~12 мм), оранжевые guides |
| Автодобавление из каталога | findBestPlacement — offsets × повороты × free zones |
| Свободное место | computeFreeZones + статус «Свободно ~N%» |
Важный архитектурный принцип:
- в store хранятся логические мм и rotation;
- 3D-модель при повороте вращает группу, а не пересчитывает width/depth меша;
- для коллизий используется footprint после
getRotatedSize().
Так визуал и правила не конфликтуют.

Производительность: что сознательно не делали
Чтобы демо летало в браузере:
- без тяжёлого
Environmentи realtime-теней; - ограниченный
dpr([1, 1.25]); - во время drag обновляется локальный state, в store — на
pointerup; OrbitControlsотключается, пока пользователь тащит элемент.
Это снова про правильный scope: конфигуратор должен быть отзывчивым, а не «игровым AAA».
Что получил заказчик на выходе
Рабочее веб-демо:
- 3 системы ящиков;
- размеры и цвет;
- каталог AMBIA-LINE с поиском;
- 3D-сцена с drag/rotate/copy/delete;
- snap и свободные зоны;
- спецификация + печать/PDF;
- onboarding и toast-уведомления.
И понятный roadmap без иллюзии, что «3D уже = готовый enterprise»:
| Уже есть | Следующий этап |
|---|---|
| Клиентский конфигуратор | Backend / админка |
| Локальный каталог | Синхронизация с 1С/API |
| Процедурный 3D | Более детальные ассеты точечно |
| Демо-продажа сценария | AI-render / расширенные режимы |
Чеклист: когда 3D-конфигуратор можно делать «просто»
Подходит стек уровня R3F + процедурная геометрия, если:
- изделия собираются из повторяемых модулей;
- важны габариты и комплектация, а не киношный рендер;
- взаимодействие — select / drag / rotate / snap;
- результат нужен как спецификация/заказ;
- первый демо-стенд нужен быстро для согласования.
Лучше сразу усложнять стек (CAD viewer, WASM-ядро, Unreal pixel streaming), если:
- нужна точная инженерная модель «как в CAD»;
- критичны сложные кривые поверхности и BOM из PLM;
- пользователь должен инспектировать допуски/сборку на уровне производства.
Для Blum AMBIA-LINE первый путь оказался правильным.
Практические выводы
1. Не начинайте с «моделей».
Начните с координат, единиц измерения и правил размещения.
2. Отделите store от Canvas.
UI и 3D должны читать одно состояние, а не жить в двух мирах.
3. Рисуйте процедурно, пока хватает узнаваемости.
GLTF подключайте точечно, когда ассет реально повышает доверие.
4. Коллизии делайте на логической плоскости.
2D AABB на полу ящика закрывает 90% UX-кейсов конфигуратора.
5. Оптимизируйте под демо-устройство.
Меньше эффектов — больше ощущения «продукт уже живой».
Итог
3D-моделирование для product-конфигуратора — это не обязательно сложная мультимесячная дисциплина. При стеке Vite + React + TypeScript + React Three Fiber + Zustand и процедурной геометрии задача раскладывается на понятные инженерные куски: данные каталога, логика размещения, лёгкая сцена, спецификация.
Кейс Blum AMBIA-LINE как раз про это: быстро показать объём ящика, дать поставить разделители «руками» в 3D и сразу собрать заказ — без превращения демо в CAD-платформу.
Сложность появляется не от слова «3D». Она появляется от неправильного выбора инструмента под класс задачи.
FAQ
Нужен ли Three.js «с нуля», если есть React?
Для такого продукта удобнее React Three Fiber: меньше бойлерплейта, проще связка с UI.
Когда переходить на готовые GLTF-модели?
Когда процедурные примитивы перестают убеждать на демо или нужен маркетинг-shot. Не до первого работающего сценария.
Почему коллизии 2D, если сцена 3D?
Потому что элементы стоят на полу ящика. Задача размещения — планировка площади, а не полёт в пространстве.
Можно ли на этом стеке вырасти до production?
Да: добавить backend, синхронизацию каталога, auth и более детальные ассеты. Архитектура store + utils + scene к этому готова.


