swift 如何将世界原点自动设置为地板上的新点并将3D模型系在那里

14ifxucb  于 2023-05-16  发布在  Swift
关注(0)|答案(1)|浏览(71)

我想自动执行以下操作:

  • (1)异步加载3D模型,例如50厘米高的花瓶
  • (2)检测地板上从世界原点(设备的初始位置)垂直向下的点P,并将P设置为新的世界原点
  • (3)将(1)中的3D模型放置在(2)中采集的P处。

所以,实际上,如果我站在一边,我会看到一个花瓶站在我所在的地方。
在执行(3)之前,我需要等待(1)和(2),并且我想自动执行所有这些操作,这让我非常困惑。
我该如何处理这个问题?
我尝试生成一个AnchorEntity,如下所示:

let floorAnchorEntity = AnchorEntity(plane: [.horizontal],
                            classification: [.floor],
                             minimumBounds: [0.5, 0.5])
floorAnchorEntity.name = "floor anchor entity"
arView.scene.addAnchor(floorAnchorEntity)

并“同步”加载模型并将其绑定到锚实体:

do {
    let modelEntity = try Entity.load(named: modelName)
    floorAnchorEntity.addChild(modelEntity)
} catch {
    assertionFailure("could not load assets.")
}

我期待着看到地板上的模型,但我没有看到屏幕上的任何东西。另外,锚实体的“isActive”标志为“false”。

vaqhlq81

vaqhlq811#

设置新的世界原点

下面的方法可以帮助您异步加载Reality Composer场景,提取模型,然后创建并跟踪水平面锚(使用系留模型),最后在合并订阅者的帮助下设置新的World Origin。
但是,如果你的跟踪不好,锚的姿势和全新的世界原点之间会有一些差异。因此,在4秒之后,我们校正模型的变换。

import RealityKit
import UIKit
import Combine

class ViewController: UIViewController {        
    @IBOutlet var arView = ARView(frame: .zero)
    var subs: [Cancellable] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()            
        arView.debugOptions = [.showWorldOrigin]

        Experience.loadBoxAsync { result in
            switch result {
                case let .success(scene):
                    guard let model = scene.steelBox else { return }

                    let anchor = AnchorEntity(.plane(.horizontal,
                                     classification: .floor,
                                      minimumBounds: [0.5, 0.5]))
                    anchor.addChild(model)
       
                    var sub = arView.scene.subscribe(to: SceneEvents.DidAddEntity.self) { _ in
                        self.arView.session.setWorldOrigin(relativeTransform: 
                                            model.transformMatrix(relativeTo: nil))
                    }
                    if subs.count == 0 { subs.append(sub) }            
                    arView.scene.anchors.append(anchor)
        
                    DispatchQueue.main.asyncAfter(deadline: .now() + 4.0) {
                        print(model.position(relativeTo: nil))  // 1
                        model.setTransformMatrix(matrix_identity_float4x4, relativeTo: nil) 
                        print(model.position(relativeTo: nil))  // 2
                    }
                case let .failure(error):
                    print("Failed to asynchronously load scene due to \(error)")
            }
        }    
    }
}
// 1st print result:       SIMD3<Float>(-0.011, 0.018, -0.005)

// 2nd print result:       SIMD3<Float>(0.0, 0.0, 0.0)

附注
欲了解更多信息,请阅读此帖子。

相关问题