Table of Contents

Usar el Mega plugin para implementar occlusion

Occlusion es una tecnología clave para mejorar la integración inmersiva de virtual y real content en AR. Este artículo le guía para implementar efectos de occlusion en el environment xr-frame mediante EasyAR cloud localization y annotations.

Antes de empezar

Cómo se implementa occlusion

  • Offline modeling: use el Unity editor para crear geometry con correspondencia 1:1 en el Block coordinate system para entidades del mundo real como walls, columns y large equipment; o bien obtenga un optimized model mediante cropping y face reduction del Block dense model.

  • Runtime alignment: en runtime de xr-frame, alinee el Block coordinate system con el real space mediante cloud localization y cargue la geometry correspondiente.

  • Material replacement: asigne occlusion materials especiales a estas geometries.

  • Visual effect: cuando la GPU renderiza otros virtual objects, los pixels de las partes ocluidas se descartan automáticamente al fallar el depth test, haciendo que los virtual objects sigan la lógica de occlusion del physical space real.

Cómo disponer occlusion con simple geometry

  1. Coloque box annotations con precisión comparándolas con el dense model y el panorama. Tras la colocación, la annotation parece una "wall" o un "column".

    Annotation as occlusion

  2. Modifique el nombre de la annotation, por ejemplo occlusion_wall, registre el ID y suba la annotation.

  3. En el xr-frame Mini Program, use su built-in geometry para cargar la annotation usada como occlusion.

    En el callback de carga de EMA, use scene.createElement(xrFrameSystem.XRMesh,{}) para crear simple geometry y asignar el material easyar-occlusion.

    Nota

    La carga, registration, deregistration y unloading del material easyar-occlusion están controlados por 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, este panda puede bailar detrás de la wall.

Cómo disponer occlusion con complex geometry

Esto se aplica a escenarios que requieren oclusión de alta precisión, como equipos de forma irregular o edificios irregulares. Puede usar el archivo de máscara de los resultados de mapeo, o exportar el modelo denso del Block mediante Mega Studio en Unity, recortarlo y reducirlo para obtener un modelo blanco de oclusión.

Usar el archivo de máscara de los resultados de mapeo

Descargue el archivo de máscara glb del resultado de mapeo mediante Mask file download en la base de datos de localización en la nube y recórtelo. El modelo recortado no necesita rotarse alrededor del eje Y al cargarse en xr-frame.

Nota

Este método solo se aplica a resultados de mapeo de la versión 9.6 o posterior.

  1. Después de agregar el Block a la base de datos, registre el Block ID correspondiente y haga clic en Mask file download en la columna Action.

    Entrada de descarga del archivo de máscara

  2. En la ventana emergente, seleccione Low precision y haga clic en Download para descargar el archivo glb.

    Descargar archivo de máscara

  3. Abra el modelo descargado en software de creación digital, como Blender.

    Archivo de máscara antes de recortar

    Recorte el modelo, conserve solo la parte necesaria para oclusión y guárdelo como glb. Mantenga posición, rotación, escala y sistema de coordenadas originales.

    Archivo de máscara después de recortar

  4. Prepare el archivo glb recortado. Puede subir el archivo a un servidor de hosting HTTPS accesible por el Mini Program y obtener la URL, o poner el archivo en el directorio miniprogram/assets/ del proyecto Mini Program y usar directamente una ruta relativa. Al usar un servidor de hosting, configure el dominio de descarga legal correspondiente en el backend del Mini Program y añada el dominio a la whitelist del Mini Program.

  5. Rellene la dirección del modelo en la configuración de recurso del componente sampleAssets.occlusionMesh.src. Si el modelo se coloca en el directorio assets/, use una ruta relativa, por ejemplo:

    src: "assets/occlusion_mesh_sd.glb",
    

    También puede introducir una URL HTTPS del hosting server, como https://your-domain.example/occlusion.glb.

    El componente debe implementar la carga del modelo, el mounting, la asignación del material de occlusion y la liberación de recursos. Monte el modelo bajo el nodo Block localizado correctamente y mantenga la position, rotation y scale originales del modelo.

    Después de que el modelo se cargue y la localization tenga éxito, cree un XRNode bajo el primer nodo Block y luego monte el modelo 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;
    },
    

    Después de que la localization tenga éxito, monte el modelo bajo el nodo Block. No es necesario configurar manualmente la spatial position.

    Este método muestra directamente el white model original descargado y mantiene la position, rotation, scale y visible material predeterminados del modelo. Para resource loading y node mounting, consulte Cómo cargar contenido 3D en una escena AR durante xr-frame runtime.

  6. Ejecute el Mini Program en la escena real del Block, muestre el archivo de máscara tras localizar y compruebe el ajuste y la oclusión de objetos virtuales.

Usar el modelo denso exportado desde Unity

  1. En la Unity scene, haga clic en el nodo Mega Block y registre el BlockID en el panel Inspector.

    Record BlockID

  2. En Block de Mega Studio, seleccione export.

    Select export

  3. Modifique las export options y exporte.

    Export options

    En la figura, 1 es el LOD level. Cuanto menor sea el level, más simple será el model y menor el número de faces. Si necesita la precision más alta, seleccione 2; si puede aceptar menor precision para reducir el face count, seleccione 1 o 0.

    En la figura, 2 es la texture export option. Como solo necesitamos el white model como occlusion, no se necesitan textures.

  4. Recorte y reduzca el model exportado en digital content creation software, como Blender, y guárdelo como Glb.

    Consejo

    El ejemplo usa el Decimate Modifier de Blender.

    Before cropping

    Después de cropping y reduction:

    After cropping

  5. Coloque el archivo Glb usado para occlusion en el directorio miniprogram/assets/ del proyecto Mini Program y use una ruta relativa, o móntelo en un servidor de archivos HTTPS accesible y use su URL. Al usar una URL de servidor, configure el dominio de descarga legal correspondiente en el backend del Mini Program y añada el dominio a la whitelist del Mini Program.

  6. Cargue el GLTF usado como occlusion en el xr-frame Mini Program.

    Primero cargue el GLTF model usado para occlusion y luego use scene.createElement(xrFrameSystem.XRGLTF,options) para crear el GLTF model.

    Use assets.getAsset("material", "easyar-occlusion") para obtener el material object.

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

    Nota

    La carga, registration, deregistration y unloading del material easyar-occlusion están controlados por 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" //Aquí debe rellenarse el Block ID
    if (!blockHolder.getBlockById(blockParent.id)) {
        // Si no existe un nodo Block, cree uno
        blockHolder.holdBlock({
            id: blockID
        })
    }
    // Obtener el nodo Block en la escena xr-frame
    let blockElement = blockHolder.getBlockById(blockParent.id).el;
    // Montar el modelo de oclusión recortado bajo el nodo Block como nodo hijo
    blockElement.addChild(model);
    /**
     * Debido a diferencias en el comportamiento de los cargadores GLTF, para que la orientación del modelo en xr-frame coincida exactamente con el resultado renderizado en Unity
    * A veces hay que rotar el modelo cargado 180 grados alrededor del eje Y en el lugar
    */
    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: el material debe modificarse después de modificar Transform
    if (assetInfo.assetId == 'occlusion1') {
        //Obtener el material de oclusión proporcionado por el plugin Mega
        let occlusionMaterial = scene.assets.getAsset("material", "easyar-occlusion");
        //Modificar el material de oclusión
        model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {
            m.setData({ neverCull: true, material: occlusionMaterial });
        });
    }
}
```
> [!NOTE]
> Aquí, usar el Mega Block dense model tras cropping como occlusion no requiere annotation synchronization para spatial position. Esto se debe a que en digital content creation software, como Blender, el model puede reducirse y recortarse sin cambiar la coordinate system definition.
>
> Si necesita colocar con precisión su propio GLTF model como occlusion, consulte [Cómo colocar un occlusion model alineado con el espacio](./sample.md#wechat-mega-sample-precise-occulusion-model).

El efecto final en dispositivo real se muestra en el vídeo al principio del artículo.

Efecto esperado de occlusion

El efecto de occlusion en un xr-frame Mini Program se ve afectado principalmente por lo siguiente:

  • La precisión de localization tracking itself
  • La precisión de la colocación del model
  • La precisión del propio model, si no es simple geometry

Es normal que aparezcan varios centímetros de desalineación durante localization drift.

Demasiadas faces en el occlusion model pueden afectar fácilmente al performance. Se recomienda usarlo solo en áreas necesarias y usar simple geometry como occlusion siempre que sea posible.

Siguientes pasos

Temas relacionados