Table of Contents

Utilizzo del plug-in Mega per implementare l'occlusione

L'occlusione è una tecnologia chiave per migliorare l'immersione della fusione realtà-virtuale in AR. Questo articolo ti guiderà su come implementare l'effetto di occlusione nell'ambiente xr-frame utilizzando il cloud localization e le annotazioni di EasyAR.

Prima di iniziare

Modalità di implementazione dell'occlusione

  • Modellazione offline: utilizzare l'editor di Unity per creare geometrie corrispondenti 1:1 a entità del mondo reale (come pareti, pilastri, grandi attrezzature) nel sistema di coordinate del Block; oppure ottenere modelli ottimizzati ritagliando e decimando il modello denso del Block.

  • Allineamento a runtime: durante l'esecuzione di xr-frame, allineare il sistema di coordinate del Block con lo spazio reale tramite cloud localization e caricare le geometrie corrispondenti.

  • Sostituzione del materiale: assegnare a queste geometrie materiali di occlusione speciali.

  • Effetto visivo: quando la GPU renderizza altri oggetti virtuali, i pixel delle parti occluse verranno automaticamente scartati a causa del fallimento del depth test, facendo sì che gli oggetti virtuali seguano la logica di occlusione dello spazio fisico reale.

Come posizionare l'occlusione con geometrie semplici

  1. Posizionare l'annotazione a cubo con precisione rispetto al modello denso e alle immagini panoramiche. Dopo il posizionamento, l'annotazione dovrebbe apparire come un "muro" o un "pilastro".

    Annotazione come occlusione

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

  3. Nell'app mini-program xr-frame, utilizzare la sua geometria incorporata per caricare l'annotazione come occlusione.

    Nel callback di caricamento EMA, utilizzare scene.createElement(xrFrameSystem.XRMesh,{}) per creare una geometria semplice e assegnarle il materiale easyar-occulusion.

    Nota

    Il caricamento, la registrazione, la deregistrazione e lo scaricamento del materiale easyar-occulusion sono controllati dalla 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 il nodo del blocco non esiste, creare il nodo del blocco
        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,
                {
                    // Utilizzare il materiale di occlusione registrato dal plug-in
                    material: "easyar-occlusion",
                    // Utilizzare la geometria integrata di xr-frame, qui si può anche usare direttamente "cube"
                    geometry: geometryStr,
                    name: emaName,
                    "receive-shadow": "false",
                    "cast-shadow": "false"
                    // Attenzione a non modificare 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 l'occlusione, questo panda può ballare nascosto dietro il muro.

Come posizionare l'occlusione con geometrie complesse

Adatto per scenari che richiedono occlusione ad alta precisione, come attrezzature di forma irregolare o edifici non standard.

Puoi utilizzare il modello denso del Block, ritagliarlo e decimarlo per ottenere il modello bianco da utilizzare per l'occlusione.

  1. Nella scena Unity, fare clic sul nodo Mega Block, nel pannello Inspector registrare il BlockID.

    Registrare BlockID

  2. In Mega Studio, in Block, selezionare esporta.

    Selezionare esporta

  3. Modificare le opzioni di esportazione ed esportare.

    Opzioni di esportazione

    Nella figura, 1 indica il livello LOD: livelli più bassi corrispondono a modelli più semplici con meno poligoni. Per la massima precisione, scegliere 2; per ridurre i poligoni a scapito della precisione, scegliere 1 o 0.

    Nella figura, 2 è l'opzione per esportare le texture. Poiché abbiamo bisogno solo del modello bianco per l'occlusione, non sono necessarie le texture.

  4. Ritagliare il modello esportato in un software di creazione di contenuti digitali (ad esempio Blender), decimarlo e salvarlo come Glb.

    Consiglio

    L'esempio utilizza il Decimate Modifier di Blender.

    Prima del ritaglio

    Dopo il ritaglio e la decimazione:

    Dopo il ritaglio

  5. Caricare il file Glb per l'occlusione su un file server, ottenendo un url per il caricamento.

  6. Nell'app mini-program xr-frame, caricare il GLTF come occlusione.

    Prima caricare il modello GLTF per l'occlusione, quindi utilizzare scene.createElement(xrFrameSystem.XRGLTF,options) per creare il modello GLTF.

    Utilizzare assets.getAsset("material", "easyar-occlusion") per ottenere l'oggetto materiale.

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

    Nota

    Il caricamento, la registrazione, la deregistrazione e lo scaricamento del materiale easyar-occulusion sono controllati dalla 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" //qui dovrebbe essere inserito Block ID
    if (!blockHolder.getBlockById(blockParent.id)) {
        // Se non esiste un nodo Block, crearne uno
        blockHolder.holdBlock({
            id: blockID
        })
    }
    // Ottieni 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 figlio
    blockElement.addChild(model);
    /**
     * A causa del comportamento diverso del caricatore GLTF, per garantire che l'orientamento del modello su xr-frame 
     * corrisponda esattamente al risultato di rendering di Unity
     * a volte è necessario ruotare il modello caricato 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: è essenziale modificare il materiale DOPO aver modificato Transform
    if (assetInfo.assetId == 'occlusion1') {
        //Ottieni 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]
> L'utilizzo del modello denso Mega Block ritagliato come occlusione non richiede l'uso di annotazioni per sincronizzare la posizione spaziale, perché nei software di creazione di contenuti digitali (come Blender) è possibile decimare e ritagliare il modello senza alterare la definizione del sistema di coordinate.
>
> Per posizionare con precisione modelli di occlusione GLTF auto-prodotti, fare riferimento a [come posizionare modelli di occlusione allineati allo spazio](./sample.md#wechat-mega-sample-precise-occulusion-model)

L'effetto finale in esecuzione sul dispositivo è visibile nel video in cima all'articolo.

Aspettative sull'effetto di occlusione

L'efficacia dell'occlusione sull'app mini-program xr-frame è influenzata principalmente dai seguenti fattori:

  • Precisione intrinseca del tracking di localizzazione
  • Accuratezza del posizionamento del modello
  • Precisione del modello stesso (se non è una geometria semplice)

È normale osservare disallineamenti di alcuni centimetri durante la deriva della localizzazione.

I modelli di occlusione con troppi poligoni possono influire sulle prestazioni. Si consiglia di utilizzarli solo nelle aree necessarie e di preferire geometrie semplici per l'occlusione.

Passaggi successivi

Argomenti correlati