Utiliser le Mega plugin pour implémenter occlusion
Occlusion est une technologie clé pour améliorer l'intégration immersive du virtual et real content en AR. Cet article vous guide pour implémenter des effets d'occlusion dans l'environment xr-frame via EasyAR cloud localization et annotations.
Avant de commencer
- Savoir utiliser Mega Studio dans Unity.
- Savoir créer et upload des annotations avec Unity editor.
- Savoir créer du content aligné avec le real world.
Comment occlusion est implémentée
Offline modeling : utilisez Unity editor pour créer dans le Block coordinate system une geometry correspondant 1:1 aux entités du monde réel, comme murs, colonnes et grands équipements ; ou obtenez un optimized model par cropping et face reduction du Block dense model.
Runtime alignment : au runtime xr-frame, alignez le Block coordinate system avec le real space via cloud localization et chargez la geometry correspondante.
Material replacement : attribuez des occlusion materials spéciaux à ces geometries.
Visual effect : lorsque le GPU rend d'autres virtual objects, les pixels des parties occluded sont automatiquement éliminés car ils échouent au depth test, ce qui fait suivre aux virtual objects la logique d'occlusion du physical space réel.
Comment organiser occlusion avec simple geometry
Placez précisément les box annotations en comparant avec le dense model et le panorama. Après placement, l'annotation ressemble à un "wall" ou une "column".

Modifiez le nom de l'annotation, par exemple
occlusion_wall, notez l'ID et upload l'annotation.Dans le xr-frame Mini Program, utilisez sa built-in geometry pour charger l'annotation utilisée comme occlusion.
Dans le callback de chargement EMA, utilisez
scene.createElement(xrFrameSystem.XRMesh,{})pour créer une simple geometry et lui attribuer le materialeasyar-occlusion.Note
Le loading, registration, deregistration et unloading du material
easyar-occlusionsont contrôlés par 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>
> Avec occlusion, ce panda peut danser derrière le mur.
Comment organiser occlusion avec complex geometry
Cela convient aux scénarios nécessitant une occlusion de haute précision, comme les équipements de forme irrégulière ou les bâtiments irréguliers. Vous pouvez utiliser le fichier de masque issu des résultats de cartographie, ou exporter le modèle dense du Block via Mega Studio dans Unity, puis le découper et le réduire pour obtenir un modèle blanc d'occlusion.
Utiliser le fichier de masque issu des résultats de cartographie
Téléchargez le fichier de masque glb depuis le résultat de cartographie via Mask file download dans la base de données de localisation cloud et découpez-le. Le modèle découpé n'a pas besoin d'être tourné autour de l'axe Y lors du chargement dans xr-frame.
Note
Cette méthode ne s'applique qu'aux résultats de mapping version 9.6 ou ultérieure.
Après avoir ajouté le Block à la base de données de localisation cloud, notez le Block ID correspondant et cliquez sur Mask file download dans la colonne Action.

Dans la fenêtre contextuelle, sélectionnez Low precision et cliquez sur Download pour télécharger le fichier
glb.
Ouvrez le modèle téléchargé dans un logiciel de création de contenu numérique, par exemple Blender.

Découpez le modèle, conservez seulement la partie nécessaire à l'occlusion et enregistrez-le en
glb. Gardez position, rotation, échelle et système de coordonnées d'origine.Si le masque d'un Block contient plusieurs fichiers GLB, vous pouvez les fusionner dans un logiciel de création de contenu numérique ou les découper et les exporter séparément. À l'exécution, attachez-les tous au même nœud Block.

Préparez le fichier
glbrecadré. Vous pouvez téléverser le fichier sur un hosting server HTTPS accessible par le Mini Program et obtenir l'URL, ou placer le fichier dans le répertoireminiprogram/assets/du projet Mini Program et utiliser directement un chemin relatif. Lors de l'utilisation d'un hosting server, configurez le domaine de téléchargement légal correspondant dans le backend du Mini Program et ajoutez le domaine à la whitelist du Mini Program.Indiquez l'adresse du modèle dans
sampleAssets.occlusionMesh.src, dans la configuration des ressources du composant. Utilisez un chemin relatif pour les modèles dansassets/. Une seule entrée suffit pour un GLB ; pour plusieurs parties, ajoutez une entrée par partie à charger, avec unassetIdunique et lesrccorrespondant. Par exemple :const occlusionMeshAssets = [ // Un fichier GLB { assetId: "occlusionMesh00", type: "gltf", src: "assets/Low_Poly_occlusion.glb", options: {} }, // Plusieurs fichiers GLB { assetId: "occlusionMesh01", type: "gltf", src: "assets/Low_Poly_occlusion_part1.glb", options: {} }, { assetId: "occlusionMesh02", type: "gltf", src: "assets/Low_Poly_occlusion_part2.glb", options: {} } ];Utilisez le véritable nom du fichier téléchargé ou découpé.
srcpeut aussi contenir une URL HTTPS du serveur, telle quehttps://your-domain.example/occlusion.glb.Le composant doit implémenter le chargement du modèle, le mounting, l'affectation du material d'occlusion et la libération des ressources. Montez le modèle sous le noeud Block localisé avec succès et conservez les position, rotation et scale d'origine du modèle.
Chargez le GLTF d'occlusion dans le mini-programme xr-frame.
Une fois les modèles chargés et la localisation réussie au moins une fois, créez un
XRNodecommun sous le premier nœud Block. Créez unXRGLTFpour chaque partie chargée et remplacez le matériau de son maillage pareasyar-occlusiondu plugin Mega. La méthode complète suivante associe les modèles et remplace le matériau ; elle peut remplacershowOcclusionMesh()dans l'exemple :showOcclusionMesh() { if (!scene) { console.error("Empty scene"); return; } const blockHolder = session?.blockHolder; if (!blockHolder) { console.warn("Empty block holder. Session not initialized."); return; } if (occlusionMeshNode) { return; } const root = blockHolder.blocks[0]?.el; if (!root) { console.warn("Empty block: localization must succeed at least once before showing the occlusion mesh"); return; } const loadedMeshes = occlusionMeshAssets.filter(meshAsset => scene.assets.getAsset('gltf', meshAsset.assetId)); if (loadedMeshes.length === 0) { console.warn("Occlusion mesh asset is not loaded"); return; } const occlusionMaterial = scene.assets.getAsset("material", "easyar-occlusion"); if (!occlusionMaterial) { console.warn("Occlusion material is not loaded"); return; } const node = scene.createElement(xrFrameSystem.XRNode); root.addChild(node); for (const meshAsset of loadedMeshes) { const occlusionMesh = scene.createElement(xrFrameSystem.XRGLTF, { model: meshAsset.assetId }); node.addChild(occlusionMesh); // Attacher le nœud et régler Transform avant de remplacer le matériau d'occlusion. // Le masque issu de la cartographie conserve ses coordonnées d'origine ; aucune rotation autour de l'axe Y n'est nécessaire. occlusionMesh.getComponent(xrFrameSystem.GLTF).meshes.forEach((mesh: any) => { mesh.setData({ neverCull: true, material: occlusionMaterial }); }); } node.getComponent(xrFrameSystem.Transform).visible = this.data.occlusionMeshVisible; occlusionMeshNode = node; },Toutes les parties partagent le nœud parent
occlusionMeshNode. Utilisez sonTransform.visiblepour les afficher ou les masquer ensemble sans définir de positions spatiales séparées.Note
AR Session contrôle le chargement, l'enregistrement, la désinscription et le déchargement de
easyar-occlusion. Récupérez et utilisez le matériau après le démarrage de la Session.Exécutez le mini-programme dans l'environnement réel du Block correspondant. Attendez le chargement des ressources et la réussite de la localisation, activez Fichier de masque, puis vérifiez que les parties conservées du modèle occultent bien les objets virtuels.
Utiliser le modèle dense exporté depuis Unity
Dans la Unity scene, cliquez sur le node Mega Block et notez le BlockID dans le panel Inspector.

Dans Block de Mega Studio, sélectionnez export.

Modifiez les export options puis exportez.

Dans la figure, 1 correspond au LOD level. Plus le level est bas, plus le model est simple et moins il contient de faces. Si vous avez besoin de la precision la plus élevée, sélectionnez 2 ; si vous pouvez accepter une precision réduite pour diminuer le face count, sélectionnez 1 ou 0.
Dans la figure, 2 correspond à la texture export option. Comme seul le white model est nécessaire pour occlusion, les textures ne sont pas nécessaires.
Crop et reduce le model exporté dans digital content creation software, par exemple Blender, puis enregistrez-le en
Glb.Astuce
L'exemple utilise le Decimate Modifier de Blender.

Après cropping et reduction :

Placez le fichier
Glbutilisé pour l'occlusion dans le répertoireminiprogram/assets/du projet Mini Program et utilisez un chemin relatif, ou montez-le sur un serveur de fichiers HTTPS accessible et utilisez son URL. Lors de l'utilisation d'une URL de serveur, configurez le domaine de téléchargement légal correspondant dans le backend du Mini Program et ajoutez le domaine à la whitelist du Mini Program.Chargez le GLTF utilisé comme occlusion dans le xr-frame Mini Program.
Commencez par load le GLTF model utilisé pour occlusion, puis utilisez
scene.createElement(xrFrameSystem.XRGLTF,options)pour créer le GLTF model.Utilisez
assets.getAsset("material", "easyar-occlusion")pour obtenir le material object.Utilisez
model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {m.setData({ neverCull: true, material: occlusionMaterial });}pour modifier le material du GLTF model.Note
Le loading, registration, deregistration et unloading du material
easyar-occlusionsont contrôlés par 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" //Renseigner ici le Block ID
if (!blockHolder.getBlockById(blockParent.id)) {
// Si aucun nœud Block n’existe, en créer un
blockHolder.holdBlock({
id: blockID
})
}
// Obtenir le nœud Block dans la scène xr-frame
let blockElement = blockHolder.getBlockById(blockParent.id).el;
// Attacher le modèle d’occlusion découpé sous le nœud Block comme nœud enfant
blockElement.addChild(model);
/**
* En raison des différences de comportement des chargeurs GLTF, pour que l’orientation du modèle dans xr-frame corresponde exactement au rendu de Unity
* Il faut parfois faire pivoter le modèle chargé de 180 degrés autour de l’axe Y sur place
*/
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);
//Remarque : le matériau doit être modifié après Transform
if (assetInfo.assetId == 'occlusion1') {
//Obtenir le matériau d’occlusion fourni par le plugin Mega
let occlusionMaterial = scene.assets.getAsset("material", "easyar-occlusion");
//Modifier le matériau d’occlusion
model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {
m.setData({ neverCull: true, material: occlusionMaterial });
});
}
}
```
> [!NOTE]
> Ici, utiliser le Mega Block dense model après cropping comme occlusion ne nécessite pas d'annotation synchronization pour la spatial position. En effet, dans digital content creation software comme Blender, le model peut être réduit et découpé sans modifier la coordinate system definition.
>
> Si vous devez placer précisément votre propre GLTF model comme occlusion, consultez [Comment placer un occlusion model aligné avec l'espace](./sample.md#wechat-mega-sample-precise-occulusion-model).
L'effet final sur appareil réel est présenté dans la vidéo en haut de cet article.
Effet occlusion attendu
L'effet d'occlusion sur un xr-frame Mini Program est principalement affecté par les points suivants :
- La précision de localization tracking itself
- La précision du placement du model
- La précision du model lui-même, s'il ne s'agit pas de simple geometry
Un décalage de plusieurs centimètres pendant localization drift est normal.
Un occlusion model avec trop de faces peut facilement affecter performance. Il est recommandé de l'utiliser uniquement dans les zones nécessaires et d'utiliser autant que possible simple geometry comme occlusion.