Table of Contents

Usare il Mega plugin per implementare occlusion

Occlusion è una tecnologia chiave per migliorare l'integrazione immersiva di virtual e real content in AR. Questo articolo guida all'implementazione di effetti di occlusion nell'environment xr-frame tramite EasyAR cloud localization e annotations.

Prima di iniziare

Come viene implementata occlusion

  • Offline modeling: usare Unity editor per creare geometry con corrispondenza 1:1 nel Block coordinate system per entità del mondo reale come walls, columns e large equipment; oppure ottenere un optimized model tramite cropping e face reduction del Block dense model.

  • Runtime alignment: durante runtime di xr-frame, allineare il Block coordinate system con il real space tramite cloud localization e caricare la geometry corrispondente.

  • Material replacement: assegnare speciali occlusion materials a queste geometries.

  • Visual effect: quando la GPU renderizza altri virtual objects, i pixels delle parti occluse vengono automaticamente eliminati perché non superano il depth test, facendo sì che i virtual objects seguano la logica di occlusion del physical space reale.

Come disporre occlusion con simple geometry

  1. Posizionare con precisione box annotations confrontandole con dense model e panorama. Dopo il posizionamento, l'annotation appare come una "wall" o una "column".

    Annotation as occlusion

  2. Modificare il nome dell'annotation, ad esempio occlusion_wall, registrare l'ID e caricare l'annotation.

  3. Nel xr-frame Mini Program, usare la built-in geometry per caricare l'annotation usata come occlusion.

    Nel callback di caricamento EMA, usare scene.createElement(xrFrameSystem.XRMesh,{}) per creare simple geometry e assegnare il material easyar-occlusion.

    Nota

    Loading, registration, deregistration e unloading del material easyar-occlusion sono controllati da AR Session.

```ts
handleEmaResult(ema: easyar.ema.v0_5.Ema) {
    let blockHolder: easyar.BlockHolder = session.blockHolder;
    ema.blocks.forEach(emaBlock => {
        const blockInfo: easyar.BlockInfo = {
            id: emaBlock.id
        };
        // 若 Block 节点不存在,创建 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) {
            // GLTF部分
        } else {
            model = scene.createElement(
                xrFrameSystem.XRMesh,
                {
                    // 使用插件注册好的遮挡材质
                    material: "easyar-occlusion",
                    // 使用 xr-frame 内置几何体,此处也可以直接使用 "cube"
                    geometry: geometryStr,
                    name: emaName,
                    "receive-shadow": "false",
                    "cast-shadow": "false"
                    // 注意不要修改 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>

> Con occlusion, questo panda può ballare dietro la wall.

Come disporre occlusion con complex geometry

È adatto a scenari che richiedono occlusion ad alta precisione, come dispositivi dalla forma irregolare o edifici non regolari. È possibile usare il file maschera dai risultati di mapping, oppure esportare il dense model del Block tramite Mega Studio in Unity e poi ritagliarlo e ridurlo per ottenere un modello bianco per occlusion.

Usare il file maschera dai risultati di mapping

Scaricare il file maschera glb dal risultato di mapping tramite Mask file download nel cloud localization database e ritagliarlo. Il modello ritagliato non deve essere ruotato attorno all'asse Y quando viene caricato in xr-frame.

Nota

Questo metodo vale solo per risultati di mapping versione 9.6 o successiva.

  1. Dopo aver aggiunto il Block al cloud localization database, registrare il Block ID corrispondente e fare clic su Mask file download nella colonna Action.

    Voce download file maschera

  2. Nel popup, selezionare Low precision e fare clic su Download per scaricare il file maschera glb.

    Scaricare file maschera

  3. Aprire il modello scaricato in un software di creazione contenuti digitali, ad esempio Blender.

    File maschera prima del ritaglio

    Ritagliare il modello, mantenere solo la parte necessaria per occlusion e salvarlo come glb. Mantenere invariati posizione, rotazione, scala e sistema di coordinate.

    File maschera dopo il ritaglio

  4. Preparare il file glb ritagliato. È possibile caricare il file su un hosting server HTTPS accessibile dal Mini Program e ottenere l'URL, oppure inserire il file nella directory miniprogram/assets/ del progetto Mini Program e usare direttamente un percorso relativo. Quando si usa un hosting server, configurare il dominio di download legale corrispondente nel backend del Mini Program e aggiungere il dominio alla whitelist del Mini Program.

  5. Inserire l'indirizzo del modello nella configurazione risorsa del componente sampleAssets.occlusionMesh.src. Se il modello è collocato nella directory assets/, usare un percorso relativo, ad esempio:

    src: "assets/occlusion_mesh_sd.glb",
    

    È anche possibile inserire un URL HTTPS dal hosting server, ad esempio https://your-domain.example/occlusion.glb.

    Il componente deve implementare il caricamento del modello, il mounting, l'assegnazione del material di occlusion e il rilascio delle risorse. Montare il modello sotto il nodo Block localizzato correttamente e mantenere position, rotation e scale originali del modello.

    Dopo il caricamento del modello e il successo della localization, creare un XRNode sotto il primo nodo Block, quindi montare il modello XRGLTF:

    showOcclusionMesh() {
        if (!scene) { console.error("Empty scene"); return; }
        const blockHolder = session?.blockHolder;
        if (!blockHolder) { console.warn("Session not initialized"); return; }
        if (occlusionMeshNode) { return; }
        const root = blockHolder.blocks[0]?.el;
        if (!root) { console.warn("Localization must succeed before showing the occlusion mesh"); return; }
        if (!scene.assets.getAsset("gltf", sampleAssets.occlusionMesh.assetId)) {
            console.warn("Occlusion mesh asset is not loaded");
            return;
        }
        const node = scene.createElement(xrFrameSystem.XRNode);
        root.addChild(node);
        const model = scene.createElement(xrFrameSystem.XRGLTF, {
            model: sampleAssets.occlusionMesh.assetId
        });
        node.addChild(model);
        node.getComponent(xrFrameSystem.Transform).visible = this.data.occlusionMeshVisible;
        occlusionMeshNode = node;
    },
    

    Dopo il successo della localization, montare il modello sotto il nodo Block. Non è necessario impostare manualmente la spatial position.

    Questo metodo visualizza direttamente il white model originale scaricato e mantiene position, rotation, scale e visible material predefiniti del modello. Per resource loading e node mounting, vedere Come caricare contenuti 3D in una scena AR durante xr-frame runtime.

  6. Eseguire il Mini Program nella scena reale del Block, mostrare il file maschera dopo la localization e verificare allineamento e occlusion degli oggetti virtuali.

Usare il dense model esportato da Unity

  1. Nella Unity scene, fare clic sul node Mega Block e registrare il BlockID nel panel Inspector.

    Record BlockID

  2. In Block di Mega Studio selezionare export.

    Select export

  3. Modificare le export options ed esportare.

    Export options

    Nella figura, 1 è il LOD level. Più basso è il level, più semplice è il model e minore è il numero di faces. Se serve la precision massima selezionare 2; se è accettabile ridurre la precision per diminuire il face count, selezionare 1 o 0.

    Nella figura, 2 è la texture export option. Poiché serve solo il white model come occlusion, le textures non sono necessarie.

  4. Ritagliare e ridurre il model esportato in digital content creation software, come Blender, e salvarlo come Glb.

    Consiglio

    Nell'esempio viene usato Blender Decimate Modifier.

    Before cropping

    Dopo cropping e reduction:

    After cropping

  5. Inserire il file Glb usato per occlusion nella directory miniprogram/assets/ del progetto Mini Program e usare un percorso relativo, oppure montarlo su un file server HTTPS accessibile e usarne l'URL. Quando si usa un URL server, configurare il dominio di download legale corrispondente nel backend del Mini Program e aggiungere il dominio alla whitelist del Mini Program.

  6. Caricare il GLTF usato come occlusion nel xr-frame Mini Program.

    Prima caricare il GLTF model usato per occlusion, poi usare scene.createElement(xrFrameSystem.XRGLTF,options) per creare il GLTF model.

    Usare assets.getAsset("material", "easyar-occlusion") per ottenere il material object.

    Usare model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {m.setData({ neverCull: true, material: occlusionMaterial });} per modificare il material del GLTF model.

    Nota

    Loading, registration, deregistration e unloading del material easyar-occlusion sono controllati da AR Session.

```ts
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" //Inserire qui il Block ID
    if (!blockHolder.getBlockById(blockParent.id)) {
        // Se non esiste un nodo Block, crearne uno
        blockHolder.holdBlock({
            id: blockID
        })
    }
    // Ottiene il nodo Block nella scena xr-frame
    let blockElement = blockHolder.getBlockById(blockParent.id).el;
    // Monta il modello di occlusione ritagliato sotto il nodo Block come nodo figlio
    blockElement.addChild(model);
    /**
     * Poiché i loader GLTF si comportano in modo diverso, per mantenere l’orientamento del modello in xr-frame esattamente coerente con il risultato renderizzato in Unity
    * A volte il modello caricato deve essere ruotato sul posto di 180 gradi attorno all’asse 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);
    //Nota: il materiale deve essere modificato dopo aver modificato Transform
    if (assetInfo.assetId == 'occlusion1') {
        //Ottiene il materiale di occlusione fornito dal plugin Mega
        let occlusionMaterial = scene.assets.getAsset("material", "easyar-occlusion");
        //Modifica il materiale di occlusione
        model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {
            m.setData({ neverCull: true, material: occlusionMaterial });
        });
    }
}
```
> [!NOTE]
> Qui, usare il Mega Block dense model dopo cropping come occlusion non richiede annotation synchronization della spatial position. Questo perché in digital content creation software, come Blender, è possibile ridurre e ritagliare il model senza cambiare la coordinate system definition.
>
> Se è necessario posizionare con precisione il proprio GLTF model come occlusion, vedere [Come posizionare un occlusion model allineato con lo spazio](./sample.md#wechat-mega-sample-precise-occulusion-model).

L'effetto finale su dispositivo reale è mostrato nel video all'inizio dell'articolo.

Effetto atteso di occlusion

L'effetto di occlusion su un xr-frame Mini Program è influenzato principalmente da:

  • Precisione del localization tracking itself
  • Precisione del posizionamento del model
  • Precisione del model stesso, se non è simple geometry

Durante localization drift, un disallineamento di alcuni centimetri è normale.

Troppe faces nel occlusion model possono facilmente influire sulla performance. Si consiglia di usarlo solo nelle aree necessarie e di usare il più possibile simple geometry come occlusion.

Passaggi successivi

Argomenti correlati