Table of Contents

Usando o plug-in Mega para implementar oclusão

Oclusão (Occlusion) é uma tecnologia essencial para melhorar a sensação de imersão na fusão de realidade aumentada (AR). Este guia explicará como implementar efeitos de oclusão usando o EasyAR Cloud Spatial Anchor e anotações em um ambiente xr-frame.

Antes de começar

Métodos de implementação de oclusão

  • Modelagem offline: Utilize o editor Unity para criar geometrias correspondentes 1:1 a entidades do mundo real (como paredes, pilares, equipamentos grandes) no sistema de coordenadas Block; ou obtenha modelos otimizados através do recorte e redução de faces do modelo denso Block.

  • Alinhamento em tempo de execução: Durante a execução no xr-frame, alinhe o sistema de coordenadas Block ao espaço físico usando cloud localization e carregue a geometria correspondente.

  • Substituição de material: Atribua materiais especiais de oclusão a essas geometrias.

  • Efeito visual: Quando a GPU renderiza outros objetos virtuais, os pixels das partes ocluídas são automaticamente descartados devido ao teste de profundidade (depth test), fazendo com que os objetos virtuais sigam a lógica de oclusão do espaço físico real.

Como configurar oclusão com geometria simples

  1. Posicione anotações cúbicas com precisão, alinhando-as ao modelo denso e imagens panorâmicas. Após o posicionamento, as anotações devem parecer uma "parede" ou "pilar".

    Anotação como oclusão

  2. Modifique o nome da anotação (ex: occlusion_wall), registre o ID e faça o upload.

  3. No miniprograma xr-frame, utilize sua geometria embutida para carregar a anotação como oclusão.

    No callback de carregamento do EMA, use scene.createElement(xrFrameSystem.XRMesh,{}) para criar uma geometria simples e atribua o material easyar-occulusion.

    Nota

    O carregamento, registro, desregistro e descarregamento do material easyar-occulusion são controlados pela AR Session.

handleEmaResult(ema: easyar.ema.v0_5.Ema) {
    let blockHolder: easyar.BlockHolder = session.blockHolder;
    ema.blocks.forEach(emaBlock => {
        const blockInfo: easyar.BlockInfo = {
            id: emaBlock.id
        };
        // Se o nó Block não existir, crie o nó Block
        blockHolder.holdBlock(blockInfo, easyarPlugin.toXRFrame(emaBlock.transform));
    });
    ema.annotations.forEach(annotation => {
        if (annotation.type != mega.EmaV05AnnotationType.Node) {
            return;
        }
        const nodeAnnotation = annotation as easyar.ema.v0_5.Node;
        const xrNode: xrfs.XRNode = easyarPlugin.createXRNodeFromNodeAnnotation(nodeAnnotation, blockHolder);
        const emaName: string = nodeAnnotation.name;
        const geometryStr: string = nodeAnnotation.geometry === "cube" ? "cube" : "sphere";
        const assetInfo = AnnotationMetaData[nodeAnnotation.id as keyof typeof AnnotationMetaData];
        let model: xrfs.Element;

        if (assetInfo) {
            // Parte GLTF
        } else {
            model = scene.createElement(
                xrFrameSystem.XRMesh,
                {
                    // Use o material de oclusão registrado pelo plug-in
                    material: "easyar-occlusion",
                    // Use a geometria integrada do xr-frame, também pode usar "cube" diretamente aqui
                    geometry: geometryStr,
                    name: emaName,
                    "receive-shadow": "false",
                    "cast-shadow": "false"
                    // Observe não modificar Scale 
                }
            );
            xrNode.addChild(model);
        }
    })
}
<video src="https://doc-asset.easyar.com/develop/wechat/mega/media/occlusion03.mp4" style="width:480px; max-width:100%; height:auto;" muted playsinline controls></video>

> Com a oclusão implementada, este panda pode dançar atrás da parede.

Como configurar oclusão com geometria complexa

Adequado para cenários que exigem alta precisão de oclusão, como equipamentos irregulares ou estruturas arquitetônicas complexas.

Você pode usar o modelo denso Block, recortá-lo e reduzir suas faces para obter um modelo branco (white model) para oclusão.

  1. Clique no nó Mega Block na cena Unity e registre o BlockID no painel Inspector.

    Registrar BlockID

  2. No Mega Studio, selecione Block > Exportar.

    Selecionar exportação

  3. Ajuste as opções de exportação e exporte.

    Opções de exportação

    O item 1 indica o nível de LOD (Level of Detail). Níveis mais baixos resultam em modelos mais simples com menos faces. Para máxima precisão escolha 2; para reduzir faces aceitando menor precisão, escolha 1 ou 0.

    O item 2 controla a exportação de texturas. Como precisamos apenas de um modelo branco para oclusão, desative esta opção.

  4. Recorte e reduza as faces do modelo exportado em um software de criação de conteúdo digital (ex: Blender) e salve como Glb.

    Dica

    Este exemplo usa o Decimate Modifier do Blender.

    Antes do recorte

    Após recorte e redução de faces:

    Após recorte

  5. Hospede o arquivo Glb de oclusão em um servidor de arquivos para obter uma URL de carregamento.

  6. Carregue o GLTF como oclusão no miniprograma xr-frame.

    Primeiro carregue o modelo GLTF de oclusão. Em seguida, use scene.createElement(xrFrameSystem.XRGLTF,options) para criar o modelo GLTF.

    Use assets.getAsset("material", "easyar-occlusion") para obter o objeto de material.

    Use model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {m.setData({ neverCull: true, material: occlusionMaterial });} para modificar o material do modelo GLTF.

    Nota

    O carregamento, registro, desregistro e descarregamento do material easyar-occulusion são controlados pela AR Session.

const sampleAssets = {
    occlusion1: {
        assetId: "occlusion1",
        type: "gltf",
        src: "url/occlusion1.glb",
        options: {}
    }
}
async loadAsset() {
    if (!scene) {console.error("Empty scene"); return;}
    try {
        await scene.assets.loadAsset(sampleAssets.occlusion1);
    } catch (err) {
        console.error(`Failed to load assets: ${err.message}`);
    }
},
addOcclusion() {
    model = scene.createElement(
        xrFrameSystem.XRGLTF,
        {
            "model": assetInfo.assetId,
            "anim-autoplay": assetInfo.animation ? assetInfo.animation : "",
            "scale": assetInfo.scale ? assetInfo.scale : "1 1 1",
            name: "tree"
        }
    );
    const blockID = "aaaa1234-bbbb-cccc-dddd-eeeeee123456" //Preencher com o Block ID aqui
    if (!blockHolder.getBlockById(blockParent.id)) {
        // Se não existir um nó Block, criar um
        blockHolder.holdBlock({
            id: blockID
        })
    }
    // Obter o nó Block na cena do xr-frame
    let blockElement = blockHolder.getBlockById(blockParent.id).el;
    // Montar o modelo de oclusão recortado como filho do nó Block
    blockElement.addChild(model);
    /**
     * Devido a diferenças no comportamento do carregador GLTF, para garantir que a orientação do modelo no xr-frame 
     * corresponda exatamente ao resultado de renderização do Unity
    * às vezes é necessário girar o modelo carregado 180 graus em torno do eixo Y
    */
    let modelTransform = model.getComponent(xrFrameSystem.Transform);
    let currentRotation = modelTransform.quaternion.clone();
    let targetRotation = currentRotation.multiply(new xrFrameSystem.Quaternion().setValue(0, 1, 0, 0));
    modelTransform.quaternion.set(targetRotation);
    //Atenção: modificar o material APÓS alterar o Transform
    if (assetInfo.assetId == 'occlusion1') {
        //Obter material de oclusão fornecido pelo plug-in mega
        let occlusionMaterial = scene.assets.getAsset("material", "easyar-occlusion");
        //Modificar material de oclusão
        model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {
            m.setData({ neverCull: true, material: occlusionMaterial });
        });
    }
}
> [!NOTE]
> Ao usar o modelo denso Mega Block recortado para oclusão, **não** é necessário usar anotações para sincronizar a posição espacial. Isso ocorre porque softwares como Blender permitem reduzir e recortar modelos sem alterar a definição do sistema de coordenadas.
>
> Para posicionar com precisão um modelo GLTF de oclusão personalizado, consulte [Como posicionar modelos de oclusão alinhados espacialmente](./sample.md#wechat-mega-sample-precise-occulusion-model)

O resultado final em execução no dispositivo está no vídeo do topo do artigo.

Expectativas do efeito de oclusão

A eficácia da oclusão no miniprograma xr-frame é influenciada por:

  • Precisão inerente do rastreamento de localização
  • Precisão do posicionamento do modelo
  • Precisão do próprio modelo (se não for uma geometria simples)

Desalinhamentos de alguns centímetros durante deriva (drift) de localização são normais.

Modelos de oclusão com muitas faces podem impactar o desempenho. Recomenda-se usar apenas em áreas necessárias e preferir geometrias simples.

Próximos passos

Tópicos relacionados