2

我开始使用 ARKit,并且我有一个用例,我想知道从已知位置到另一个位置的运动。

所以我想知道是否有可能(就像每个跟踪解决方案一样)在 ARKit 中设置一个已知的位置和方向作为跟踪的起点?

问候

4

1 回答 1

4

至少有六种方法可以让您为模型设置起点。但是在你的 ARScene 中完全不使用ARAnchors被认为是糟糕的 AR 体验(尽管 Apple 的增强现实应用程序模板在代码中没有任何 ARAnchors)。

第一种方法

这是 Apple 工程师Augmented Reality app在 Xcode 中的模板中向我们建议的方法。这种方法不使用锚定,因此您需要做的就是将模型放置在空中,其坐标类似于(x: 0, y: 0, z: -0.5),或者换句话说,您的模型将距离相机 50 厘米。

override func viewDidLoad() {
    super.viewDidLoad()
    
    sceneView.scene = SCNScene(named: "art.scnassets/ship.scn")!
    let model = sceneView.scene.rootNode.childNode(withName: "ship", 
                                                recursively: true)
    model?.position.z = -0.5
    sceneView.session.run(ARWorldTrackingConfiguration())
}


第二种方法

第二种方法与第一种方法几乎相同,除了它使用 ARKit 的锚点:

guard let sceneView = self.view as? ARSCNView 
else { return }

if let currentFrame = sceneView.session.currentFrame {
        
    var translation = matrix_identity_float4x4
    translation.columns.3.z = -0.5
    let transform = simd_mul(currentFrame.camera.transform, translation)
        
    let anchor = ARAnchor(transform: transform)
    sceneView.session.add(anchor: anchor)
}


第三种方法

您还可以使用第三种方法创建使用 ARAnchor 固定的预定义模型的位置,您还需要导入 RealityKit 模块:

func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
            
    let model = ModelEntity(mesh: MeshResource.generateSphere(radius: 1.0))

    // ARKit's anchor
    let anchor = ARAnchor(transform: simd_float4x4(diagonal: [1,1,1]))
    
    // RealityKit's anchor based on position of ARAnchor
    let anchorEntity = AnchorEntity(anchor: anchor)

    anchorEntity.addChild(model)
    arView.scene.anchors.append(anchorEntity)
}


第四种方法

如果您打开了平面检测功能,您可以使用光线投射或命中测试方法。作为目标对象,您可以使用一个小球体(位于0, 0, 0),该球体将进行射线投射。

let query = arView.raycastQuery(from: screenCenter,
                            allowing: .estimatedPlane,
                           alignment: .any)

let raycast = session.trackedRaycast(query) { results in

    if let result = results.first {
        object.transform = result.transform
    } 
}


第五种方法

这种方法专注于保存和共享 ARKit 的worldMaps

func writeWorldMap(_ worldMap: ARWorldMap, to url: URL) throws {

    let data = try NSKeyedArchiver.archivedData(withRootObject: worldMap, 
                                         requiringSecureCoding: true)
    try data.write(to: url)
}

func loadWorldMap(from url: URL) throws -> ARWorldMap {

    let mapData = try Data(contentsOf: url)
    guard let worldMap = try NSKeyedUnarchiver.unarchivedObject(ofClass: ARWorldMap.self, 
                                                                   from: mapData) 
    else { 
        throw ARError(.invalidWorldMap) 
    }
    return worldMap
}


第六种方法

在 ARKit 4.0 中,借助 MapKit 模块实现了新的ARGeoTrackingConfiguration。所以现在您可以使用预定义的 GPS 数据。

func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
   
    for geoAnchor in anchors.compactMap({ $0 as? ARGeoAnchor }) {

        arView.scene.addAnchor(Entity.placemarkEntity(for: geoAnchor)
    }
}
于 2019-07-05T19:44:24.170 回答