Usar o Mega plugin para implementar occlusion
Occlusion é uma tecnologia chave para melhorar a integração imersiva de virtual e real content em AR. Este artigo orienta como implementar efeitos de occlusion no environment xr-frame por meio de EasyAR cloud localization e annotations.
Antes de começar
- Ser capaz de usar Mega Studio no Unity.
- Ser capaz de criar e fazer upload de annotations com o Unity editor.
- Ser capaz de criar content alinhado com o real world.
Como occlusion é implementada
Offline modeling: use o Unity editor para criar geometry com correspondência 1:1 no Block coordinate system para entidades do mundo real, como walls, columns e large equipment; ou obtenha um optimized model por cropping e face reduction do Block dense model.
Runtime alignment: no runtime xr-frame, alinhe o Block coordinate system com o real space por cloud localization e carregue a geometry correspondente.
Material replacement: atribua occlusion materials especiais a essas geometries.
Visual effect: quando a GPU renderiza outros virtual objects, os pixels nas partes ocluídas são automaticamente descartados por falharem no depth test, fazendo com que virtual objects sigam a lógica de occlusion do physical space real.
Como posicionar occlusion com simple geometry
Posicione box annotations com precisão comparando com o dense model e o panorama. Após o posicionamento, a annotation parece uma "wall" ou "column".

Modifique o nome da annotation, como
occlusion_wall, registre o ID e faça upload da annotation.No xr-frame Mini Program, use sua built-in geometry para carregar a annotation usada como occlusion.
No callback de carregamento da EMA, use
scene.createElement(xrFrameSystem.XRMesh,{})para criar simple geometry e atribuir o materialeasyar-occlusion.Nota
O loading, registration, deregistration e unloading do material
easyar-occlusionsão 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>
> Com occlusion, este panda pode dançar atrás da wall.
Como posicionar occlusion com complex geometry
Aplica-se a cenários que exigem oclusão de alta precisão, como equipamentos de formato irregular e edifícios irregulares. Você pode usar o arquivo de máscara dos resultados de mapeamento, ou exportar o modelo denso do Block pelo Mega Studio no Unity, depois recortá-lo e reduzi-lo para obter um modelo branco de oclusão.
Usar o arquivo de máscara dos resultados de mapeamento
Baixe o arquivo de máscara glb do resultado de mapeamento pela entrada Mask file download no banco de dados de localização em nuvem e recorte-o. O modelo recortado não precisa ser rotacionado em torno do eixo Y ao ser carregado no xr-frame.
Nota
Este método se aplica apenas a resultados de mapping da versão 9.6 ou posterior.
Depois de adicionar o Block ao banco de dados de localização em nuvem, registre o Block ID correspondente e clique em Mask file download na coluna Action.

Na janela pop-up, selecione Low precision e clique em Download para baixar o arquivo de máscara
glb.
Abra o modelo baixado em um software de criação de conteúdo digital, como Blender.

Recorte o modelo, mantendo apenas a parte necessária para oclusão, e salve como
glb. Mantenha posição, rotação, escala e sistema de coordenadas originais.
Prepare o arquivo
glbrecortado. Você pode enviar o arquivo para um hosting server HTTPS acessível pelo Mini Program e obter a URL, ou colocar o arquivo no diretóriominiprogram/assets/do projeto Mini Program e usar diretamente um caminho relativo. Ao usar um hosting server, configure o domínio legal de download correspondente no backend do Mini Program e adicione o domínio à whitelist do Mini Program.Preencha o endereço do modelo na configuração de recurso do componente
sampleAssets.occlusionMesh.src. Se o modelo for colocado no diretórioassets/, use um caminho relativo, por exemplo:src: "assets/occlusion_mesh_sd.glb",Também é possível preencher uma URL HTTPS do hosting server, como
https://your-domain.example/occlusion.glb.O componente deve implementar o carregamento do modelo, mounting, atribuição do material de occlusion e liberação de recursos. Monte o modelo sob o nó Block localizado com sucesso e mantenha position, rotation e scale originais do modelo.
Depois que o modelo for carregado e a localization tiver sucesso, crie um
XRNodesob o primeiro nó Block e então monte o 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; },Após o sucesso da localization, monte o modelo sob o nó Block. Não é necessário configurar manualmente a spatial position.
Esse método exibe diretamente o white model original baixado e mantém a default position, rotation, scale e visible material do modelo. Para resource loading e node mounting, consulte Como carregar conteúdo 3D em uma AR scene no xr-frame runtime.
Execute o Mini Program na cena real correspondente ao Block, exiba o arquivo de máscara após a localization e verifique o alinhamento e a oclusão dos objetos virtuais.
Usar o modelo denso exportado do Unity
Na Unity scene, clique no node Mega Block e registre o BlockID no panel Inspector.

Em Block do Mega Studio, selecione export.

Modifique as export options e exporte.

Na figura, 1 é o LOD level. Quanto menor o level, mais simples o model e menor o número de faces. Se precisar da precision mais alta, selecione 2; se puder aceitar menor precision para reduzir o face count, selecione 1 ou 0.
Na figura, 2 é a texture export option. Como precisamos apenas do white model como occlusion, textures não são necessárias.
Faça crop e reduce do model exportado em digital content creation software, como Blender, e salve como
Glb.Dica
O exemplo usa o Decimate Modifier do Blender.

Após cropping e reduction:

Coloque o arquivo
Glbusado para occlusion no diretóriominiprogram/assets/do projeto Mini Program e use um caminho relativo, ou monte-o em um servidor de arquivos HTTPS acessível e use sua URL. Ao usar uma URL de servidor, configure o domínio legal de download correspondente no backend do Mini Program e adicione o domínio à whitelist do Mini Program.Carregue o GLTF usado como occlusion no xr-frame Mini Program.
Primeiro carregue o GLTF model usado para occlusion e depois use
scene.createElement(xrFrameSystem.XRGLTF,options)para criar o GLTF model.Use
assets.getAsset("material", "easyar-occlusion")para obter o material object.Use
model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {m.setData({ neverCull: true, material: occlusionMaterial });}para modificar o material do GLTF model.Nota
O loading, registration, deregistration e unloading do material
easyar-occlusionsão 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" //Preencha o Block ID aqui
if (!blockHolder.getBlockById(blockParent.id)) {
// Se não houver um nó Block existente, crie um
blockHolder.holdBlock({
id: blockID
})
}
// Obter o nó Block na cena xr-frame
let blockElement = blockHolder.getBlockById(blockParent.id).el;
// Anexar o modelo de oclusão recortado sob o nó Block como seu nó filho
blockElement.addChild(model);
/**
* Como os loaders GLTF se comportam de formas diferentes, para manter a orientação do modelo no xr-frame exatamente igual ao resultado renderizado no Unity
* Às vezes é preciso girar o modelo carregado 180 graus em torno do eixo Y no próprio local
*/
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);
//Observação: o material deve ser alterado depois de modificar Transform
if (assetInfo.assetId == 'occlusion1') {
//Obter o material de oclusão fornecido pelo plugin Mega
let occlusionMaterial = scene.assets.getAsset("material", "easyar-occlusion");
//Modificar o material de oclusão
model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {
m.setData({ neverCull: true, material: occlusionMaterial });
});
}
}
```
> [!NOTE]
> Aqui, usar o Mega Block dense model após cropping como occlusion não exige annotation synchronization para spatial position. Isso ocorre porque, em digital content creation software como Blender, é possível reduzir e recortar o model sem alterar a coordinate system definition.
>
> Se precisar posicionar com precisão seu próprio GLTF model como occlusion, consulte [Como posicionar um occlusion model alinhado com o espaço](./sample.md#wechat-mega-sample-precise-occulusion-model).
O efeito final em dispositivo real é mostrado no vídeo no início deste artigo.
Efeito esperado de occlusion
O efeito de occlusion em um xr-frame Mini Program é afetado principalmente pelos seguintes pontos:
- A accuracy do localization tracking em si
- A accuracy do posicionamento do model
- A accuracy do próprio model, se não for simple geometry
É normal ocorrer desalinhamento de vários centímetros durante localization drift.
Muitas faces no occlusion model podem facilmente afetar performance. Recomenda-se usá-lo apenas em áreas necessárias e usar simple geometry como occlusion sempre que possível.