首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >快速-How更新ARAnchor以跟踪摄像机的位置

快速-How更新ARAnchor以跟踪摄像机的位置
EN

Stack Overflow用户
提问于 2020-02-20 19:50:07
回答 1查看 405关注 0票数 1

我跟随这段代码从@rickster 100%工作和真不错。在视频中,他正在动画一个使用SCNNode设置的ARAnchor,从一个位置设置到另一个位置,然后返回。我试图做一些类似的事情,但我希望用ARAnchor设置的节点跟踪/更新它的位置到另一个节点,该节点是相机的子节点。

我在更新func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) { }中的职位时遇到了问题

我尝试将与ARAnchor一起设置的节点动画为跟随另一个节点,但它不起作用,它向后和反向运行:

代码语言:javascript
复制
let animation = CABasicAnimation(keyPath: #keyPath(SCNNode.transform))
animation.fromValue = nodeSetWithARAnchor.transform
animation.toValue = nodeTiedToCamera.transform
animation.duration = 1
nodeSetWithARAnchor.removeAllAnimations()
nodeSetWithARAnchor.addAnimation(animation, forKey: nil)

然后我尝试删除ARAnchor并重置其节点的.worldPostion.simdWorldTransform,但是节点消失了。它在下面的步骤7&8中。

如何使nodeSetWithARAnchor nodeTiedToCamera**?** 更新其ARAnchor和位置以始终遵循

在步骤6中,Update设置了nodeSetWithARAnchor SCVector3nodeTiedToCameradWorld's SCVector3匹配,并将.transform设置为匹配nodeTiedToCameradWorldTransform @rickster的动画代码,因为我不需要删除任何锚点。不过还有另一个问题。当我移动设备时,nodeSetWithARAnchor会响应,但它会向后和反向响应。

当我打开设备时,图像向右转,当我把设备打开时,图像向左转。当我把设备左转时,图像上升,当我右转设备时,图像下降。它跟在我绑在相机上的图像,但它不正确地跟踪它。

代码语言:javascript
复制
let configuration = ARWorldTrackingConfiguration()

var nodeSetWithARAnchor: SCNNode?
var nodeTiedToCamera: SCNNode?
var anchors: [ARAnchor] = []

override func viewDidLoad() {
    super.viewDidLoad()

    configuration.planeDetection = [.horizontal, .vertical]
    configuration.maximumNumberOfTrackedImages = 1

    // 1. once this anchor is set inside renderer(_:didAdd:for:) I initialize the nodeSetWithARAnchor at 30cm behind the device's camera's initial position
    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        var translation = matrix_identity_float4x4
        translation.columns.3.z = -0.3
        let transform = simd_mul(self.sceneView.session.currentFrame!.camera.transform, translation)
        let anchor = ARAnchor(transform: transform)
        self.sceneView.session.add(anchor: anchor)
    }

    // 2. the nodeTiedToCamera will always go where ever the device's camera goes
    let plane = SCNPlane(width: 0.1, height: 0.1)
    nodeTiedToCamera = SCNNode(geometry: plane)
    nodeTiedToCamera!.position = SCNVector3(x: -0.15, y: 0.45, z: -1.25) // I don't want it directly in front of the camera
    nodeTiedToCamera!.geometry?.fisrtMaterial?.diffuse.contents = UIColor.red
    sceneView.pointOfView.addChildNode(nodeTiedToCamera!)
}

// 3. I init the nodeSetWithARAnchor, add it to the sceneView's root node, and keep a copy of it's anchor
func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    DispatchQueue.main.async {

        if self.nodeSetWithARAnchor == nil {
            // create geometry ...
            self.nodeSetWithARAnchor = SCNNode(geometry: geometry)

            node.addChildNode(self.nodeSetWithARAnchor!)
        }

        self.anchors.removeAll()
        self.anchors.append(anchor)
    }
}

func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {

    DispatchQueue.main.async {

        // 4. get the only child that is tied to the camera which is the nodeTiedToCamera
        guard let pointOfView = self.sceneView.pointOfView else { return }
        guard let child = pointOfView.childNodes.first else { return }

        // 5. get it's .worldPosition && it's .simdWorldTransform
        let nodeTiedToCameradWorldPosition = child.worldPosition
        let nodeTiedToCameradWorldTransform = child.worldTransform

        if let nodeSetWithARAnchor = self.nodeSetWithARAnchor, let anchorToRemove = self.anchors.first {

             // 6. set the nodeSetWithARAnchor SCVector3 to match the nodeTiedToCameradWorld's SCVector3 and set its .transform to match the nodeTiedToCameradWorldTransform
             nodeSetWithARAnchor.position = nodeTiedToCameradWorldPosition
             nodeSetWithARAnchor.transform = nodeTiedToCameradWorldTransform

             let animation = CABasicAnimation(keyPath: #keyPath(SCNNode.transform))
             animation.fromValue = nodeSetWithARAnchor.transform
             animation.toValue = nodeTiedToCamera.transform
             animation.duration = 1
             nodeSetWithARAnchor.removeAllAnimations()
             nodeSetWithARAnchor.addAnimation(animation, forKey: nil)

             // 7. remove all ARAnchors
             //self.sceneView.session.remove(anchor: anchorToRemove)
             //self.anchors.removeAll()

             // 8. add a new anchor to the session and set it with the nodeSetWithARAnchor.simdWorldTransform
            //let anchor = ARAnchor(transform: nodeSetWithARAnchor.simdWorldTransform)
            //self.sceneView.session.add(anchor: anchor)
        }
    }
}

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
    guard let node = self.nodeSetWithARAnchor else { return }

    if let pointOfView = sceneView.pointOfView {
        let isVisible = sceneView.isNode(node, insideFrustumOf: pointOfView)
        print("Is node visible: \(isVisible)")
    }
}
EN

回答 1

Stack Overflow用户

发布于 2020-02-21 09:46:07

这是一个整天的事情,但让它发挥作用。我只需在renderer(:willRenderScene:atTime:)中切换大约2行代码,并按照下面的确切顺序运行它们。我不需要删除和添加锚或运行任何动画代码。

代码语言:javascript
复制
func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {
    
    DispatchQueue.main.async { [weak self] in

        guard let safeSelf = self else { return }
        guard let pointOfView = safeSelf.sceneView.pointOfView else { return }
        guard let child = pointOfView.childNodes.first else { return } // child is the nodeTiedToCamera

        if let nodeSetWithARAnchor = safeSelf.nodeSetWithARAnchor {
            
            // *** I just had to switch around these 2 lines of code and run them in this exact order ***
            nodeSetWithARAnchor.transform = child.worldTransform
            nodeSetWithARAnchor.worldPosition = child.worldPosition
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60327523

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档