Table of Contents

Xr-frame ランタイムで AR シーンにおける 3D コンテンツをロードする方法

この文書は、xr-frame のリソースローディングとノードマウンティングの分離メカニズムを詳細に説明します。スクリプトによる動的な実装を通じて、3D コンテンツをブロックノード下に柔軟にマウントし、AR を実現します。

公式資料

公式資料には、ランタイムで 3D コンテンツをロードする方法が十分に説明されています。この文書では、AR シーンで一般的に使用されるコンテンツとロード方法について簡潔に説明します。

リソースのローディング vs ノードのマウンティング

xr-frame では、3D モデルを表示するプロセスは 2 つの段階に分かれます:

  1. リソースのローディング:モデルファイル(例:.glb)をネットワークまたはローカルからダウンロードし、メモリに解析することを指します。この時点でモデルは準備完了ですが、シーン内では不可視です。

  2. ノードのマウンティング:シーンツリー内にノードを作成し、ロード済みのリソースをそのノードに関連付けることを指します。この時点でモデルがレンダリングキャンバスに正式に表示されます。

コードで動的に 3D コンテンツをロードする方法

  1. リソースのローディング

    xr-frame シーンのリソース管理システムを使用して、loadAsset を手動で呼び出し、リソースをロードします。

    パラメータの type はリソースタイプ、assetId はロード後のリソース ID、src はリソースの URL(通常はリソースホスティングサーバーのアドレス)を指します。

    assetId は後続のマウンティングやリソース解放のために記録する必要があります。

    try {
        await scene.assets.loadAsset({type: 'gltf', assetId: 'panda', src: 'url/EasyARPanda.glb'});
    } catch (err) {
        console.error(`Failed to load assets: ${err.message}`);
    }
    
  2. ノードのマウンティング

    element.addChild() を使用して、ロード済みモデルを ShadowRoot 下に配置します。

    const root = scene.getElementById("shadow-root");
    let panda = scene.createElement(xrFrameSystem.XRGLTF,
        {
            "model": "panda",
            "anim-autoplay": ""
        }
    );
    root.addChild(panda);
    

    ShadowRoot 要素は、xr-frame が動的なノードの作成と削除を防止するために特別に設計されたルートノードです。詳細は Shadowノード を参照してください。

    プラグインオブジェクトが提供する createXRNodeFromNodeAnnotation メソッドを使用すると、EMA データに基づいてブロックの子ノードを作成でき、3D コンテンツが正しい空間位置に表示されることを保証します。

    const nodeAnnotation = annotation as easyar.ema.v0_5.Node;
    const xrNode: xrfs.XRNode = easyarPlugin.createXRNodeFromNodeAnnotation(nodeAnnotation, blockHolder);
    let panda = scene.createElement(xrFrameSystem.XRGLTF,
        {
            "model": "panda",
            "anim-autoplay": ""
        }
    );
    xrNode.addChild(panda);
    

ブロック下で注釈を使用せずに直接コンテンツをマウントする方法

[!警告] この方法を使用する前提条件は、LocalTransform の値が xr-frame 座標系で期待されるレンダリング効果を実現できることを検証済みであることです。

それ以外の場合は、Unity エディタの注釈機能を使用 して実装してください。

getBlockById(id) を使用してシーンツリー上のブロックノードオブジェクトを取得します。対応するブロックノードが存在しない場合、そのブロックの位置特定がまだ成功していないことを示します(初めてブロックの位置特定に成功したときにノードが自動的に作成されます)。holdBlock(blockInfo, blockTransformInput) を使用してそのブロックのノードを作成するか、位置特定コールバックでブロックの位置特定が成功したことを確認してからコンテンツをマウントできます。

[!ヒント] Unity エディタのシーンツリーで ブロックノード を選択し、Inspector パネルに表示される ID を記録します

UnityエディタのBlockID

クラウド位置特定ライブラリページでも Block ID を確認できます

位置特定ライブラリのBlockID

const blockID = "aaaa1234-bbbb-cccc-dddd-eeeeee123456"
if (!blockHolder.getBlockById(blockParent.id)) {
    // 存在するブロックノードがない場合、作成する
    blockHolder.holdBlock({
        id: blockID
    })
}
let blockElement = blockHolder.getBlockById(blockParent.id).el;

モデルノードを指定されたブロック下にマウントし、position.setArray()quaternion.set()、および scale.setArray() を使用してモデルノードの LocalTransform を修正します。

export interface LocalTransform {
    /** @description 位置 */
    position: xrfs.Vector3;
    /** @description 回転 */
    rotation: xrfs.Quaternion;
    /** @description スケール */
    scale: xrfs.Vector3;
}

// ブロック下での既知の LocalTransform を想定
const targetTransform: LocalTransform;

blockElement.addChild(modelNode);
let modelTransform = modelNode.getComponent(xrFrameSystem.Transform);
    modelTransform.position.setArray([
        targetTransform.position.x,
        targetTransform.position.y,
        targetTransform.position.z
    ]);
    let annoRotation = new xrFrameSystem.Quaternion().setValue(
        targetTransform.rotation.x,
        targetTransform.rotation.y,
        targetTransform.rotation.z,
        targetTransform.rotation.w
    );
    modelTransform.quaternion.set(annoRotation);
    modelTransform.scale.setArray([
        targetTransform.scale.x,
        targetTransform.scale.y,
        targetTransform.scale.z
    ]);

xr-frame がサポートするリソースタイプ

  • Texture テクスチャと画像
  • CubeTexture キューブテクスチャ
  • VideoTexture ビデオテクスチャ
  • EnvData 環境
  • GLTF モデル
  • Keyframe キーフレームアニメーション
  • Atlas アトラス

各リソースのロード方法の詳細は、WeChat公式ドキュメント および xr-frame 公式サンプル を参照してください

[!注意] サポートされる GLTF 形式および拡張機能については、xr-frame 公式 GLTF 使用説明 を参照