Table of Contents

Como carregar conteúdo 3D em scenes AR em runtime no xr-frame

Este artigo descreve em detalhes o mecanismo de separação entre resource loading e node mounting no xr-frame. Por meio de scripts dinâmicos, o conteúdo 3D pode ser montado de forma flexível sob nodes Block para realizar AR.

Recursos oficiais

Os recursos oficiais já trazem conteúdo suficiente sobre como carregar conteúdo 3D em runtime. Este artigo apenas explica brevemente alguns conteúdos e métodos de carregamento comuns em scenes AR.

Resource loading vs node mounting

No xr-frame, exibir um modelo 3D é dividido em duas etapas:

  1. Resource loading: baixar o arquivo do modelo (como .glb) da rede ou localmente e analisá-lo na memória. Nesse momento o modelo está pronto, mas não visível na scene.

  2. Node mounting: criar um node na scene tree e associar o resource carregado a esse node. Só então o modelo aparece oficialmente no rendering canvas.

Como carregar dinamicamente conteúdo 3D usando código

  1. Resource loading

    Carregue resources manualmente chamando loadAsset pelo sistema de gerenciamento de resources da scene xr-frame.

    O parâmetro type indica o tipo de resource, assetId indica o id do resource após o carregamento, e src indica a url do resource, geralmente o endereço do resource hosting server.

    É necessário registrar assetId para mounting e liberação de resource posteriores.

    try {
        await scene.assets.loadAsset({type: 'gltf', assetId: 'panda', src: 'url/EasyARPanda.glb'});
    } catch (err) {
        console.error(`Failed to load assets: ${err.message}`);
    }
    
  2. Node mounting

    Use element.addChild() para colocar o modelo carregado sob ShadowRoot.

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

    O elemento ShadowRoot é o root node usado especialmente pelo xr-frame para impedir a criação e remoção dinâmicas de nodes. Veja Shadow node para detalhes.

    O método createXRNodeFromNodeAnnotation fornecido pelo plugin object pode criar child nodes de Block com base nos dados EMA, garantindo que o conteúdo 3D seja exibido na posição espacial correta.

    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);
    

Como montar conteúdo diretamente sob Block sem usar annotation

Aviso

O pré-requisito para usar este método é que você já tenha verificado que o valor LocalTransform consegue alcançar o efeito de rendering esperado no sistema de coordenadas xr-frame.

Para outros casos, use a função annotation do Unity Editor.

Obtenha o block node object na scene tree por meio de getBlockById(id). Se o block node correspondente não existir, isso indica que a localization deste Block ainda não teve sucesso (o node será criado automaticamente na primeira localization bem-sucedida deste Block). Você pode usar holdBlock(blockInfo, blockTransformInput) para criar um node deste Block, ou verificar no localization callback se a localization deste Block teve sucesso antes de montar o conteúdo.

Dica

Selecione o node Block na scene tree do Unity Editor e registre o ID exibido no painel Inspector

BlockID no Unity Editor

Também é possível encontrar o Block ID na página da cloud localization library

BlockID na localization library

const blockID = "aaaa1234-bbbb-cccc-dddd-eeeeee123456"
if (!blockHolder.getBlockById(blockParent.id)) {
    // nao existe nenhum no Block; crie um
    blockHolder.holdBlock({
        id: blockID
    })
}
let blockElement = blockHolder.getBlockById(blockParent.id).el;

Monte o model node sob o Block especificado e use position.setArray(), quaternion.set() e scale.setArray() para modificar o LocalTransform do model node.

export interface LocalTransform {
    /** @description posicao */
    position: xrfs.Vector3;
    /** @description rotacao */
    rotation: xrfs.Quaternion;
    /** @description Scale */
    scale: xrfs.Vector3;
}

// suponha que exista um LocalTransform conhecido sob 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
    ]);

Tipos de resource suportados pelo xr-frame

  • Texture, texturas e imagens
  • CubeTexture, texturas cúbicas
  • VideoTexture, texturas de vídeo
  • EnvData, environment
  • GLTF models
  • Keyframe, frame animation
  • Atlas

Os métodos detalhados de carregamento de cada resource podem ser encontrados na documentação oficial WeChat e nos exemplos oficiais xr-frame

Nota

Para formatos e extensions GLTF suportados, consulte as instruções oficiais de uso GLTF do xr-frame