При отображении большого количества одинаковых трёхмерных объектов классическая загрузка отдельной модели для каждого экземпляра приводит к значительным затратам памяти и снижению производительности. В сценах с тысячами деревьев, фонарных столбов, ветрогенераторов, автомобилей или элементов городской инфраструктуры подобный подход становится неэффективным.
Технология Instanced 3D Model в CesiumJS позволяет загружать геометрию модели только один раз, а затем отображать множество её экземпляров с различными позициями, ориентациями, масштабами и атрибутами. GPU получает одну геометрию и набор параметров для каждого экземпляра, что существенно уменьшает объём передаваемых данных и ускоряет рендеринг.
В основе механизма лежит спецификация 3D Tiles Instanced Model (i3dm), предназначенная для массового отображения повторяющихся объектов в трёхмерных геопространственных сценах.
Обычная модель содержит:
Если необходимо отобразить 10 000 одинаковых деревьев, при традиционном подходе информация о модели фактически используется многократно.
Схема без инстансирования:
Tree.glb
Tree.glb
Tree.glb
Tree.glb
...
10000 раз
Схема с инстансированием:
Tree.glb
Экземпляр 1 -> позиция A
Экземпляр 2 -> позиция B
Экземпляр 3 -> позиция C
...
Экземпляр 10000 -> позиция Z
Геометрия хранится один раз, а каждый экземпляр содержит только параметры трансформации.
Файл i3dm является одним из форматов семейства 3D Tiles.
Основные компоненты:
| Компонент | Назначение |
|---|---|
| Header | Заголовок тайла |
| Feature Table | Параметры экземпляров |
| Batch Table | Пользовательские атрибуты |
| GLB | Исходная модель |
Каждый экземпляр может содержать:
Пример логической структуры:
{
"instances": [
{
"position": [100, 200, 50],
"scale": 1.0
},
{
"position": [150, 250, 50],
"scale": 1.2
}
]
}
Наиболее распространённый способ использования — загрузка готового набора 3D Tiles.
const tileset = await Cesium.Cesium3DTileset.fromUrl(
"data/trees/tileset.json"
);
viewer.scene.primitives.add(tileset);
await viewer.zoomTo(tileset);
Если tileset содержит i3dm-тайлы, Cesium автоматически распознает их и отобразит все экземпляры.
Типичный tileset с экземплярами может выглядеть следующим образом:
{
"asset": {
"version": "1.0"
},
"geometricError": 500,
"root": {
"boundingVolume": {
"box": [
0,0,0,
500,0,0,
0,500,0,
0,0,100
]
},
"geometricError": 0,
"content": {
"uri": "trees.i3dm"
}
}
}
В файле tileset содержится только информация о пространственной организации тайлов, тогда как сами параметры экземпляров находятся внутри i3dm.
Каждый экземпляр обладает собственной позицией.
Обычно координаты хранятся в системе:
Пример концептуальных данных:
{
"POSITION": [
[100, 50, 0],
[120, 80, 0],
[140, 90, 0]
]
}
Cesium автоматически преобразует координаты в мировое пространство.
Каждый экземпляр может иметь индивидуальный поворот.
Для этого используются:
Например, деревья могут иметь различный угол поворота:
Дерево 1 -> 15°
Дерево 2 -> 75°
Дерево 3 -> 210°
Дерево 4 -> 310°
Визуально это устраняет эффект искусственного копирования.
Каждый объект способен иметь собственный масштаб.
Пример:
Дерево 1 -> 0.8
Дерево 2 -> 1.0
Дерево 3 -> 1.3
Дерево 4 -> 1.6
Такая вариативность часто используется для:
Небольшие различия размеров существенно повышают реалистичность сцены.
Каждый экземпляр может хранить дополнительные атрибуты.
Например:
{
"id": 1001,
"species": "oak",
"height": 12.4,
"age": 54
}
Эти данные могут использоваться:
Cesium поддерживает механизм выбора объектов сцены.
const handler = new Cesium.ScreenSpaceEventHandler(
viewer.scene.canvas
);
handler.setInputAction(function(click) {
const feature = viewer.scene.pick(click.position);
if (Cesium.defined(feature)) {
console.log(feature);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
После выбора становится доступна информация о конкретном экземпляре модели.
Получение значения свойства:
const type = feature.getProperty("species");
console.log(type);
Получение высоты:
const height = feature.getProperty("height");
Проверка наличия свойства:
if (feature.hasProperty("height")) {
console.log("Свойство существует");
}
Каждый экземпляр может быть визуально выделен.
feature.color = Cesium.Color.RED;
Полупрозрачный вариант:
feature.color = Cesium.Color.BLUE.withAlpha(0.5);
Сброс:
feature.color = Cesium.Color.WHITE;
Такой подход широко применяется для:
Для работы с тысячами объектов удобнее использовать стили.
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${height} > 50", "color('red')"],
["${height} > 20", "color('yellow')"],
["true", "color('green')"]
]
}
});
Логика выполняется на стороне GPU и обеспечивает высокую производительность.
Можно скрывать объекты на основе атрибутов.
tileset.style = new Cesium.Cesium3DTileStyle({
show: "${height} > 30"
});
Отобразятся только экземпляры выше 30 метров.
Пример тематической карты для деревьев:
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["${species} === 'oak'", "color('green')"],
["${species} === 'pine'", "color('darkgreen')"],
["true", "color('gray')"]
]
}
});
Такой подход используется в геоинформационных системах и цифровых двойниках.
Основное преимущество технологии заключается в уменьшении числа draw calls.
Сравнение:
| Параметр | Отдельные модели | Instanced Models |
|---|---|---|
| Память | Высокая | Низкая |
| Draw Calls | Очень много | Минимум |
| Скорость загрузки | Ниже | Выше |
| GPU эффективность | Средняя | Высокая |
Особенно заметен выигрыш при количестве объектов свыше нескольких тысяч.
Instanced Models часто комбинируются с механизмом LOD.
Сценарий:
0–500 м -> полная модель
500–1500 м -> упрощённая модель
1500+ м -> очень простая модель
Благодаря этому сохраняется высокая детализация рядом с камерой и уменьшается нагрузка вдали.
Cesium автоматически исключает из рендеринга объекты, которые находятся вне области видимости камеры.
Процесс:
Камера
|
V
[Видимая область]
Объекты внутри -> рисуются
Объекты снаружи -> пропускаются
Для наборов из десятков тысяч экземпляров это критически важно.
Большие наборы экземпляров обычно разбиваются на тайлы.
Пример:
Город
├── Tile 1
├── Tile 2
├── Tile 3
├── Tile 4
└── Tile 5
Каждый тайл содержит собственный набор моделей.
При перемещении камеры Cesium загружает только необходимые части сцены.
Instanced Models активно используются в системах Digital Twin.
Типичные объекты:
Число экземпляров может достигать сотен тысяч без критического падения производительности.
Лес является одним из наиболее показательных примеров.
Вместо хранения миллиона отдельных моделей:
1 модель сосны
+
1 000 000 экземпляров
используется:
Одна геометрия
+
Массив параметров экземпляров
Экономия памяти может составлять десятки и сотни мегабайт.
Instanced Models применяются для отображения:
При этом разные экземпляры могут иметь:
Несмотря на высокую эффективность, инстансирование подходит не для всех сценариев.
Менее эффективно использовать Instanced Models для объектов, которые:
В подобных случаях предпочтительнее применять отдельные модели glTF или b3dm.
| Характеристика | i3dm | b3dm |
|---|---|---|
| Повторяющаяся геометрия | Да | Нет |
| Уникальные объекты | Ограниченно | Да |
| Экономия памяти | Высокая | Средняя |
| Большие наборы однотипных объектов | Отлично | Хорошо |
| Производительность | Максимальная | Высокая |
Формат i3dm оптимизирован именно для повторяющихся объектов, тогда как b3dm ориентирован на отображение уникальных моделей зданий, сооружений и других сложных элементов сцены.
Использовать минимальное число исходных моделей
Например:
Деревья:
- Oak.glb
- Pine.glb
- Birch.glb
вместо сотен похожих моделей.
Добавлять вариативность
Изменять:
Разбивать данные на тайлы
Это обеспечивает:
Использовать стили вместо ручного изменения объектов
Стилизация через Cesium3DTileStyle значительно
эффективнее изменения каждого экземпляра по отдельности.
Хранить бизнес-атрибуты в метаданных
Например:
{
"assetId": 5321,
"status": "active",
"installDate": "2024-06-15"
}
Это позволяет строить полноценные аналитические и информационные системы поверх визуализации Instanced 3D Models.