Table of Contents

Как загружать 3D-контент во время выполнения в сценарии AR с помощью xr-frame

В этой статье подробно объясняется механизм разделения загрузки ресурсов и подключения узлов в xr-frame. С помощью динамического скрипта обеспечивается гибкое подключение 3D-контента под узлом Block для реализации AR.

Официальные материалы

Официальные материалы уже содержат достаточно информации о том, как загружать 3D-контент во время выполнения. В этой статье кратко описаны распространённые методы загрузки в сценариях AR.

Загрузка ресурсов vs Подключение узлов

В xr-frame отображение 3D-модели разделено на два этапа:

  1. Загрузка ресурсов: Загрузка и парсинг файла модели (например, .glb) из сети или локально в память. Модель готова, но не видна в сцене.

  2. Подключение узлов: Создание узла в дереве сцены и связывание загруженного ресурса с этим узлом. Только тогда модель появится на холсте отрисовки.

Как динамически загружать 3D-контент с помощью кода

  1. Загрузка ресурсов

    Вызов loadAsset через систему управления ресурсами сцены xr-frame для ручной загрузки ресурсов.

    Параметр type указывает тип ресурса, assetId — идентификатор загруженного ресурса, src — URL ресурса (обычно адрес сервера хостинга).

    Запомните assetId для последующего подключения и освобождения ресурсов.

    try {
        await scene.assets.loadAsset({type: 'gltf', assetId: 'panda', src: 'url/EasyARPanda.glb'});
    } catch (err) {
        console.error(`Failed to load assets: ${err.message}`);
    }
    
  2. Подключение узлов

    Используйте element.addChild(), чтобы поместить загруженную модель под ShadowRoot.

    const root = scene.getElementById("shadow-root");
    let panda = scene.createElement(xrFrameSystem.XRGLTF,
        {
            "model": "panda",
            "anim-autoplay": ""
        }
    );
    root.addChild(panda);
    

    Элемент ShadowRoot специально предназначен для динамического создания и удаления узлов. Подробнее см. Теневой узел.

    Метод createXRNodeFromNodeAnnotation, предоставляемый объектом плагина, позволяет создавать дочерние узлы Block на основе данных EMA, гарантируя правильное расположение 3D-контента в пространстве.

    const nodeAnnotation = annotation as easyar.ema.v0_5.Node;
    const xrNode: xrfs.XRNode = easyarPlugin.createXRNodeFromNodeAnnotation(nodeAnnotation, blockHolder);
    let panda = scene.createElement(xrFrameSystem.XRGLTF,
        {
            "model": "panda",
            "anim-autoplay": ""
        }
    );
    xrNode.addChild(panda);
    

Как подключить контент под Block напрямую без аннотаций

Предупреждение

Используйте этот метод только если вы убедились, что значения LocalTransform в системе координат xr-frame обеспечивают ожидаемый результат рендеринга.

Во всех остальных случаях используйте функцию аннотирования в редакторе Unity.

Получите объект узла block в дереве сцены через getBlockById(id). Если узел отсутствует, значит Block ещё не был успешно локализован (узел создаётся автоматически при первой успешной локализации). Можно создать узел для этого Block с помощью holdBlock(blockInfo, blockTransformInput) или подключить контент после успешной локализации в колбэке.

Совет

В дереве сцены редактора Unity выберите узел Block и запишите его ID, отображаемый на панели Inspector.

BlockID в редакторе Unity

Block ID также можно найти на странице облачной библиотеки локализации.

BlockID в библиотеке локализации

const blockID = "aaaa1234-bbbb-cccc-dddd-eeeeee123456"
if (!blockHolder.getBlockById(blockParent.id)) {
    // Создать узел Block, если он отсутствует
    blockHolder.holdBlock({
        id: blockID
    })
}
let blockElement = blockHolder.getBlockById(blockParent.id).el;

Подключите узел модели к указанному Block. Используйте position.setArray(), quaternion.set() и scale.setArray(), чтобы изменить LocalTransform узла модели.

export interface LocalTransform {
    /** @description Позиция */
    position: xrfs.Vector3;
    /** @description Вращение */
    rotation: xrfs.Quaternion;
    /** @description Масштаб */
    scale: xrfs.Vector3;
}

// Предположим, что известен LocalTransform относительно Block
const targetTransform: LocalTransform;

blockElement.addChild(modelNode);
let modelTransform = modelNode.getComponent(xrFrameSystem.Transform);
    modelTransform.position.setArray([
        targetTransform.position.x,
        targetTransform.position.y,
        targetTransform.position.z
    ]);
    let annoRotation = new xrFrameSystem.Quaternion().setValue(
        targetTransform.rotation.x,
        targetTransform.rotation.y,
        targetTransform.rotation.z,
        targetTransform.rotation.w
    );
    modelTransform.quaternion.set(annoRotation);
    modelTransform.scale.setArray([
        targetTransform.scale.x,
        targetTransform.scale.y,
        targetTransform.scale.z
    ]);

Поддерживаемые типы ресурсов в xr-frame

  • Texture (текстуры и изображения)
  • CubeTexture (кубические текстуры)
  • VideoTexture (видеотекстуры)
  • EnvData (окружение)
  • GLTF (модели)
  • Keyframe (анимация по ключевым кадрам)
  • Atlas (атласы)

Подробные методы загрузки для каждого типа ресурсов см. в официальной документации WeChat и официальных примерах xr-frame

Примечание

Поддерживаемые форматы GLTF и расширения см. в официальной спецификации GLTF для xr-frame