首页 > 解决方案 > RealityKit - 图像识别和处理许多场景

问题描述

我使用 RealityKit 模板文件创建了一个应用程序。RealityComposer 内部有多个场景,所有场景都使用激活一些动画的图像识别。

在 Xcode 中,我必须将所有场景加载为锚点并将这些锚点附加到arView.scene.anchors数组中。这个问题很明显,因为我一个接一个地呈现物理 2D 图像,我得到多个锚点堆叠在一起,这是不可取的。我在arView.scene.anchors.removeAll()加载新锚之前就知道了,但我的问题是:

如何检查某个图像何时出现因此删除现有锚并加载正确的锚?我试图在 ARKit 中寻找类似的东西,didUpdate但我在 RealityKit 中看不到任何类似的东西。

非常感谢

标签: swiftaugmented-realityarkitrealitykitreality-composer

解决方案


前言

RealityKitAnchorEntity(.image)来自 RC,与 ARKit 的ARImageTrackingConfig匹配。当 iOS 设备识别参考图像时,它会创建图像锚点(符合ARTrackable协议),用于绑定相应的 3D 模型。而且,正如您所理解的,您一次只能显示一张参考图像(在您的特定情况下,当您同时提供两张或多张图像时,AR 应用程序无法正常运行)。


代码片段显示了if condition逻辑的样子:

import SwiftUI
import RealityKit

struct ContentView : View {
    var body: some View {            
        return ARViewContainer().edgesIgnoringSafeArea(.all)
    }
}

struct ARViewContainer: UIViewRepresentable {

    func makeUIView(context: Context) -> ARView {    
        let arView = ARView(frame: .zero)

        let id02Scene = try! Experience.loadID2()            
        print(id02Scene)     // prints scene hierarchy
        
        let anchor = id02Scene.children[0]
        print(anchor.components[AnchoringComponent] as Any)
        
        if anchor.components[AnchoringComponent] == AnchoringComponent(
                      .image(group: "Experience.reality", 
                              name: "assets/MainID_4b51de84.jpeg")) {
            
            arView.scene.anchors.removeAll()
            print("LOAD SCENE")
            arView.scene.anchors.append(id02Scene)
        }
        return arView
    }
 
    func updateUIView(_ uiView: ARView, context: Context) { }
}

ID2在控制台中打印的场景层次结构:

在此处输入图像描述

附言

您应该实现 SwiftUICoordinator类(在此处阅读),并在 Coordinator 内部使用 ARSessionDelegate 的session(_:didUpdate:)实例方法以 60 fps 更新锚属性。

您也可以使用以下逻辑 - 如果场景 1 的锚点处于活动状态或场景 3 的锚点处于活动状态,则只需从集合中删除所有锚点并加载场景 2。

var arView = ARView(frame: .zero)

let id01Scene = try! Experience.loadID1()
let id02Scene = try! Experience.loadID2()
let id03Scene = try! Experience.loadID3()

func makeUIView(context: Context) -> ARView {    
    arView.session.delegate = context.coordinator

    arView.scene.anchors.append(id01Scene)
    arView.scene.anchors.append(id02Scene)
    arView.scene.anchors.append(id03Scene)
    return arView
}

...

func session(_ session: ARSession, didUpdate frame: ARFrame) {
    if arView.scene.anchors[0].isActive || arView.scene.anchors[2].isActive {
        arView.scene.anchors.removeAll()
        arView.scene.anchors.append(id02Scene)
        print("Load Scene Two")
    }
}

推荐阅读