Table of Contents

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

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

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

    Annotation as occlusion

  2. Modifiez le nom de l'annotation, par exemple occlusion_wall, notez l'ID et upload l'annotation.

  3. 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 material easyar-occlusion.

    Note

    Le loading, registration, deregistration et unloading du material easyar-occlusion sont 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.

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

    Entrée de téléchargement du fichier de masque

  2. Dans la fenêtre contextuelle, sélectionnez Low precision et cliquez sur Download pour télécharger le fichier glb.

    Télécharger le fichier de masque

  3. Ouvrez le modèle téléchargé dans un logiciel de création de contenu numérique, par exemple Blender.

    Fichier de masque avant découpe

    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.

    Fichier de masque après découpe

  4. Préparez le fichier glb découpé : téléversez-le sur un serveur HTTPS accessible au Mini Program ou placez-le dans miniprogram/assets/ et utilisez un chemin relatif.

  5. Renseignez l'adresse du modèle dans sampleAssets.occlusionMesh.src.

    src: "assets/occlusion_mesh_sd.glb",
    

    Quand le modèle est chargé et la localization réussie, montez-le sous le nœud Block. Aucun réglage manuel de position spatiale n'est nécessaire. Voir charger du contenu 3D au runtime xr-frame.

  6. Exécutez le Mini Program dans la scène réelle du Block, affichez le fichier de masque après localization et vérifiez l'alignement ainsi que l'occlusion des objets virtuels.

Utiliser le modèle dense exporté depuis Unity

  1. Dans la Unity scene, cliquez sur le node Mega Block et notez le BlockID dans le panel Inspector.

    Record BlockID

  2. Dans Block de Mega Studio, sélectionnez export.

    Select export

  3. Modifiez les export options puis exportez.

    Export options

    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.

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

    Before cropping

    Après cropping et reduction :

    After cropping

  5. Montez le fichier Glb utilisé pour occlusion sur un file server afin d'obtenir une url de chargement.

  6. 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-occlusion sont 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.

Étapes suivantes

Rubriques associées