2017-07-10 34 views
7

嘿,我试图找出如何保持代替简单的节点是我走在它周围ARKit如何保持ARKit SCNNode到位

代码:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) { 

    if let planeAnchor = anchor as? ARPlaneAnchor { 

    if planeDetected == false { // Bool only allows 1 plane to be added 
      planeDetected = true 
     self.addPlane(node: node, anchor: planeAnchor) 
    } 

    } 
} 

这增加了SCNNode

func addPlane(node: SCNNode, anchor: ARPlaneAnchor) { 

    // We add the anchor plane here 

    let showDebugVisuals = Bool() 
    let plane = Plane(anchor, showDebugVisuals) 
    planes[anchor] = plane 
    node.addChildNode(plane) 



    // We add our custom SCNNode here 

    let scene = SCNScene(named: "art.scnassets/PlayerModel.scn")! 
    let Body = scene.rootNode.childNode(withName: "Body", recursively: true)! 

    Body.position = SCNVector3.positionFromTransform(anchor.transform) 
    Body.movabilityHint = .movable 
    wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform) 

    wrapperNode.addChildNode(Body) 

    scnView.scene.rootNode.addChildNode(wrapperNode) 

伊夫尝试添加一个平面/锚节点,并把“身体”节点在,但它依然继续。我想也许它与更新功能有关。

func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { 
} 

或者最有可能的位置设置

wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform) 

Iv'e通过互联网上的每个源/项目文件/视频看了看,没有人有一个简单的解决这个简单的问题。

+0

有没有简单的解决方案。您应该使用表面检测来获得更好的结果,但对象仍然会稍微移动一点。 –

+0

好的,谢谢你确认这不是一个简单的解决方案。 – Hunter

回答

16

在这里可能会发生两种“四处移动”。


一个是ARKit不断完善的设备在真实世界中的位置如何映射到抽象协调你把虚拟内容空间的估计。例如,假设你把虚拟物体在(0, 0, -0.5) ,然后将您的设备向左移动10厘米。只有ARKit精确跟踪移动,虚拟对象才会锚定在物理空间中。但视觉 - 惯性测距不是一门精确的科学,所以ARKit可能认为你向左移动了10.5厘米 - 在这种情况下,你的虚拟物体似乎会向右滑动5毫米,即使它位置在ARKit/SceneKit坐标空间中。

除了希望苹果使设备具有更好的传感器,更好的相机或更好的CPU/GPU并改善世界跟踪科学之外,您无法真正做到这一点。 (在适当的时候,这可能是一个安全的赌注,尽管这可能不符合你当前的项目提供帮助。)


既然你还面临着飞机的检测,还有另一种皱纹。 ARKit不断改进对检测到的飞机位置的估计。所以,即使飞机的实际位置不变,它在ARKit/SceneKit坐标空间中的位置也是如此。

这种运动通常是一件好事 - 如果您希望虚拟物体出现在真实世界的表面上,您需要确定该表面的位置。当平面检测更加确定表面的位置时,您会看到一些移动,但是在短时间后,当您将摄像机移动到计划锚定的虚拟对象时,您应该看到的移动更少,而不是那些在世界上浮动的虚拟对象空间。


在你的代码,但是,你不就是坐飞机检测的优势,使您的自定义内容(从“PlayerModel.scn”)坚持以面锚点:

wrapperNode.position = SCNVector3.positionFromTransform(anchor.transform) 
wrapperNode.addChildNode(Body) 
scnView.scene.rootNode.addChildNode(wrapperNode) 

此代码使用初始的平面锚的位置在世界空间位置wrapperNode(因为你使它成为根节点的孩子)。如果您将wrapperNode作为平面主播节点的子节点(您在renderer(_:didAdd:for:)中收到的节点),则它会保持与平面相连,因为ARKit会优化其对平面位置的估计。最初你会有更多的动作,但随着飞机探测“稳定下来”,你的虚拟物体将“滑落”得更少。 (当你使节点成为飞机的一个孩子时,你不需要设置它的位置 - 零位表示它在飞机的正确位置。在任何情况下,你只需要相对于这架飞机 - 即上/下/沿它多远。)

+0

谢谢你很好的答案! – Hunter

+0

Apple Dev在这个项目中提供了更多的细节示例 https://github.com/gao0122/ARKit-Example-by-Apple 它可以解释一切正确和简单。 – mychar

相关问题