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
- Poder usar Mega Studio en Unity.
- Poder crear y subir annotations con el Unity editor.
- Poder crear content alineado con el real world.
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
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".

Modifique el nombre de la annotation, por ejemplo
occlusion_wall, registre el ID y suba la annotation.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 materialeasyar-occlusion.Nota
La carga, registration, deregistration y unloading del material
easyar-occlusionestá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.
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.

En la ventana emergente, seleccione Low precision y haga clic en Download para descargar el archivo
glb.
Abra el modelo descargado en software de creación digital, como Blender.

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.
Prepare el archivo
glbrecortado. 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 directoriominiprogram/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.Rellene la dirección del modelo en la configuración de recurso del componente
sampleAssets.occlusionMesh.src. Si el modelo se coloca en el directorioassets/, 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
XRNodebajo el primer nodo Block y luego monte el modeloXRGLTF: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.
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
En la Unity scene, haga clic en el nodo Mega Block y registre el BlockID en el panel Inspector.

En Block de Mega Studio, seleccione export.

Modifique las export options y exporte.

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.
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.

Después de cropping y reduction:

Coloque el archivo
Glbusado para occlusion en el directoriominiprogram/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.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-occlusionestá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.