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
- Essere in grado di usare Mega Studio in Unity.
- Essere in grado di creare e caricare annotations con Unity editor.
- Essere in grado di creare content allineato con il real world.
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
Posizionare con precisione box annotations confrontandole con dense model e panorama. Dopo il posizionamento, l'annotation appare come una "wall" o una "column".

Modificare il nome dell'annotation, ad esempio
occlusion_wall, registrare l'ID e caricare l'annotation.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 materialeasyar-occlusion.Nota
Loading, registration, deregistration e unloading del material
easyar-occlusionsono 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.
Dopo aver aggiunto il Block al cloud localization database, registrare il Block ID corrispondente e fare clic su Mask file download nella colonna Action.

Nel popup, selezionare Low precision e fare clic su Download per scaricare il file maschera
glb.
Aprire il modello scaricato in un software di creazione contenuti digitali, ad esempio Blender.

Ritagliare il modello, mantenere solo la parte necessaria per occlusion e salvarlo come
glb. Mantenere invariati posizione, rotazione, scala e sistema di coordinate.
Preparare il file
glbritagliato. È possibile caricare il file su un hosting server HTTPS accessibile dal Mini Program e ottenere l'URL, oppure inserire il file nella directoryminiprogram/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.Inserire l'indirizzo del modello nella configurazione risorsa del componente
sampleAssets.occlusionMesh.src. Se il modello è collocato nella directoryassets/, 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
XRNodesotto il primo nodo Block, quindi montare il modelloXRGLTF: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.
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
Nella Unity scene, fare clic sul node Mega Block e registrare il BlockID nel panel Inspector.

In Block di Mega Studio selezionare export.

Modificare le export options ed esportare.

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

Dopo cropping e reduction:

Inserire il file
Glbusato per occlusion nella directoryminiprogram/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.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-occlusionsono 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.