Table of Contents

如何在 XRFame 小程序运行时修改 AR 场景下的 3D 内容

本文提供了 AR 追踪下的显隐策略控制、运行时 Transform 变换以及 GLTF 材质动态更新的实践指南。

开始之前

如何配置运行时 Block 的可见性控制策略

BlockController 组件的可见性控制策略 visibleStrategy 一共有三种:

策略 说明
VisibleWhileTracked 默认值。仅当 Block 被成功跟踪时显示,丢失跟踪则隐藏。
VisibleAfterFirstTracked 只要 Block 被成功跟踪过一次,之后即便丢失跟踪也保持显示。
None 不由引擎控制显隐,由开发者自行维护。

BlockHolder 调用 holdBlock() 在 ShadowRoot 下创建 Block 节点之后可以修改其可见性策略。

如何查到 BlockID 可以参考不使用标注直接挂载内容

const blockInfo: easyar.BlockInfo = { id: blockId };
blockHolder.holdBlock(blockInfo);
const block = blockHolder.getBlockById(blockInfo.id);

// 修改策略为:一旦跟踪到就永久显示
block.visibleStrategy = BlockVisibleStrategy.VisibleAfterFirstTracked;

默认的 VisibleStrategy 是 VisibleWhileTracked 也就是说当且仅当 Block 处于 MegaTracker 跟踪下,其内容(包括子节点的)显示。

内容编辑和修改方法

  • 修改物体的 Transform

    对于场景中的 Element 需要调用其 getComponent() 方法以获取相应的 Component 才能修改。

    const xrFrameSystem = wx.getXrFrameSystem();
    let transform = model.getComponent(xrFrameSystem.Transform);
    transform.position.setValue(1.0, 0.0, -1.0);
    /** 拷贝原本的四元数 */
    let originalQuaternion = modelTF.quaternion.clone();
    /** 绕Y旋转 180 度 */
    let targetQuaternion = originalQuaternion.multiply(new xrFrameSystem.Quaternion().setValue(0, 1, 0, 0));
    transform.quaternion.setValue(targetQuaternion);
    

    这个例子中,程序获取了 modelxrFrameSystem.Transform,然后对齐位置和旋转角度进行了修改

  • 替换贴图

    替换贴图前需要对贴图资源本身通过使用 xr-frame 场景的资源管理系统调用 loadAsset 手动加载。

    之后获取模型的 GLTF 属性,对其每个 meshmaterial 调用 setTexture() 方法。

    const textureAsset = await scene.assets.loadAsset({
        type: 'texture',
        assetId: `texture01`,
        src: 'some-texture-url.png',
    });
    model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {
        m.material.setTexture('u_baseColorMap', textureAsset.value);
    });
    

    这个例子中,程序先使用场景的资源管理器加载了一个 textureAsset,然后用其替换了 GLTF 模型的贴图。

  • 替换已注册材质

    替换已注册材质需要先使用 xr-frame 场景的资源管理系统调用 getAsset() 获取材质资源。

    之后获取模型的 GLTF 属性,对其每个 mesh 调用 setDatamaterial 属性修改为目标材质。

    let occlusionMaterial = scene.assets.getAsset("material", "easyar-occlusion");
    model.getComponent(xrFrameSystem.GLTF).meshes.forEach((m: any) => {
        m.setData({ material: occlusionMaterial });
    });
    

    这个例子中,程序先使用场景的资源管理器加载了 EasyAR 注册的遮挡材质 easyar-occlusion,然后被设置为 GLTF 模型的材质。