Table of Contents

Utilisation du plug-in mega pour réaliser l'occlusion

L'occlusion est une technologie clé pour améliorer l'immersion de la fusion réalité-virtuelle en RA. Cet article vous guidera sur la façon de réaliser des effets d'occlusion dans l'environnement xr-frame en utilisant la localisation cloud et l'annotation EasyAR.

Avant de commencer

Méthodes de mise en œuvre de l'occlusion

  • Modélisation hors ligne : Utiliser l'éditeur Unity pour créer des géométries correspondant 1:1 aux entités du monde réel (comme les murs, piliers, gros équipements) dans le système de coordonnées Block ; ou obtenir des modèles optimisés en découpant et réduisant la complexité du modèle dense Block.

  • Alignement en temps réel : Pendant l'exécution dans xr-frame, aligner le système de coordonnées Block avec l'espace physique via la localisation cloud, et charger les géométries correspondantes.

  • Remplacement de matériau : Attribuer à ces géométries un matériau d'occlusion spécial.

  • Effet visuel : Lors du rendu d'autres objets virtuels par le GPU, les pixels occultés sont automatiquement éliminés en raison de l'échec du test de profondeur, forçant ainsi les objets virtuels à respecter la logique d'occlusion de l'espace physique réel.

Comment configurer l'occlusion avec des géométries simples

  1. Positionner précisément les annotations de cube en référence au modèle dense et aux panoramas. Après placement, les annotations doivent ressembler à un "mur" ou une "colonne".

    Annotation comme occlusion

  2. Modifier le nom de l'annotation (ex. occlusion_wall), noter son ID, télécharger l'annotation.

  3. Dans l'application mini-programme xr-frame, utiliser sa géométrie intégrée pour charger les annotations comme occlusion.

    Dans le callback du chargement EMA, utiliser scene.createElement(xrFrameSystem.XRMesh,{}) pour créer une géométrie simple et lui attribuer le matériau easyar-occulusion.

    Note

    Le chargement, l'enregistrement, le désenregistrement et le déchargement du matériau easyar-occulusion sont contrôlés par la session AR.

handleEmaResult(ema: easyar.ema.v0_5.Ema) {
    let blockHolder: easyar.BlockHolder = session.blockHolder;
    ema.blocks.forEach(emaBlock => {
        const blockInfo: easyar.BlockInfo = {
            id: emaBlock.id
        };
        // Si le nœud Block n'existe pas, créer le nœud 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) {
            // Partie GLTF
        } else {
            model = scene.createElement(
                xrFrameSystem.XRMesh,
                {
                    // Utiliser le matériel d'occlusion enregistré par le plugin
                    material: "easyar-occlusion",
                    // Utiliser la géométrie intégrée de xr-frame, "cube" peut être utilisé directement ici
                    geometry: geometryStr,
                    name: emaName,
                    "receive-shadow": "false",
                    "cast-shadow": "false"
                    // Ne pas modifier 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 l'occlusion, ce panda peut danser caché derrière le mur.

Comment configurer l'occlusion avec des géométries complexes

Convient pour les équipements non standard, bâtiments irréguliers ou scénarios nécessitant une occlusion de haute précision.

Vous pouvez utiliser le modèle dense Block, le découper et réduire sa complexité pour obtenir un modèle blanc nécessaire à l'occlusion.

  1. Cliquer sur le nœud Mega Block dans la scène Unity, noter le BlockID dans le panneau Inspector

    Noter le BlockID

  2. Dans Block de Mega Studio, choisir d'exporter.

    Choisir d'exporter

  3. Modifier les options d'exportation puis exporter.

    Options d'exportation

    Le point 1 correspond au niveau de LOD. Plus le niveau est bas, plus le modèle est simple avec moins de faces. Pour la plus haute précision, choisir 2. Pour réduire la complexité au détriment de la précision, choisir 1 ou 0.

    Le point 2 concerne l'export des textures. Comme nous n'avons besoin que d'un modèle blanc pour l'occlusion, les textures sont inutiles.

  4. Découper et réduire la complexité du modèle exporté dans un logiciel de création de contenu numérique (ex. Blender), puis l'enregistrer en Glb.

    Astuce

    L'exemple utilise le modifier Decimate de Blender.

    Avant découpe

    Après découpe et réduction :

    Après découpe

  5. Héberger le fichier Glb d'occlusion sur un serveur de fichiers pour obtenir une URL de chargement.

  6. Charger le modèle GLTF comme occlusion dans l'application mini-programme xr-frame.

    D'abord charger le modèle GLTF d'occlusion, puis utiliser scene.createElement(xrFrameSystem.XRGLTF,options) pour créer le modèle GLTF.

    Utiliser assets.getAsset("material", "easyar-occlusion") pour obtenir l'objet matériau.

    Utiliser model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {m.setData({ neverCull: true, material: occlusionMaterial });} pour modifier le matériau du modèle GLTF.

    Note

    Le chargement, l'enregistrement, le désenregistrement et le déchargement du matériau easyar-occulusion sont contrôlés par la session AR.

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" //Ici, vous devez remplir le Block ID
    if (!blockHolder.getBlockById(blockParent.id)) {
        // S'il n'existe pas de nœud Block, 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;
    // Monter le modèle d'occlusion découpé sous le nœud Block en tant qu'enfant
    blockElement.addChild(model);
    /**
     * En raison des différences de comportement des chargeurs GLTF, pour garantir que l'orientation du modèle sur xr-frame corresponde exactement au résultat de rendu d'Unity
    * il est parfois nécessaire de faire pivoter le modèle chargé de 180 degrés autour de l'axe 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);
    //Notez que vous devez modifier le matériau après avoir modifié le Transform
    if (assetInfo.assetId == 'occlusion1') {
        //Obtenir le matériau d'occlusion fourni par le plug-in 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]
> L'utilisation du modèle dense Mega Block découpé comme occlusion ne nécessite pas d'annotation pour synchroniser la position spatiale, car dans les logiciels de création (ex. Blender), on peut réduire la complexité et découper le modèle sans altérer le système de coordonnées.
>
> Pour positionner précisément un modèle GLTF d'occlusion personnalisé aligné spatialement, voir [Comment positionner un modèle d'occlusion aligné spatialement](./sample.md#wechat-mega-sample-precise-occulusion-model)

L'effet final en situation réelle est visible dans la vidéo en haut de l'article.

Résultat attendu de l'occlusion

L'efficacité de l'occlusion dans les mini-programmes xr-frame dépend principalement de :

  • La précision intrinsèque du suivi de localisation
  • La précision du positionnement du modèle
  • La précision du modèle lui-même (s'il ne s'agit pas d'une géométrie simple)

Un décalage de quelques centimètres dû à la dérive de localisation est normal.

Les modèles d'occlusion avec trop de faces impactent les performances. Il est recommandé de les utiliser uniquement dans les zones nécessaires et de privilégier des géométries simples.

Prochaines étapes

Sujets connexes