在 ARKit 中进行动画时如何获取 3D 对象的当前位置?

Posted

技术标签:

【中文标题】在 ARKit 中进行动画时如何获取 3D 对象的当前位置?【英文标题】:How to get current position of 3D object while animation is going on in ARKit? 【发布时间】:2020-03-23 22:26:15 【问题描述】:

在图像标记检测中,我只想使用ARKit 在该标记边界内播放行走的人的动画。为此,我想找出该 3D 对象在标记上行走时的位置。动画使用外部 3D 创作工具创建并保存在.scnassets 中作为.dae 文件。我使用以下代码添加了节点并开始动画:

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


     if let imageAnchor = anchor as? ARImageAnchor   
          DispatchQueue.main.async  
              //let translation = imageAnchor.transform.columns.3     
                let idleScene = SCNScene(named: "art.scnassets/WalkAround/WalkAround.dae")!  

             // This node will be parent of all the animation models  
                let node1 = SCNNode()  

                // Add all the child nodes to the parent node  
                for child in idleScene.rootNode.childNodes   
                     node1.addChildNode(child)  
                  

               node1.scale = SCNVector3(0.2, 0.2, 0.2)  
               let physicalSize = imageAnchor.referenceImage.physicalSize  
               let size = CGSize(width: 500, height: 500)  

               let skScene = SKScene(size: size)  
               skScene.backgroundColor = .white  

               let plane = SCNPlane(width: self.referenceImage!.physicalSize.width, height: self.referenceImage!.physicalSize.height)  

               let material = SCNMaterial()  
               material.lightingModel = SCNMaterial.LightingModel.constant  
               material.isDoubleSided = true  
               material.diffuse.contents = skScene  
               plane.materials = [material]  
               let rectNode = SCNNode(geometry: plane)  
               rectNode.eulerAngles.x = -.pi / 2  

               node.addChildNode(rectNode)  
               node.addChildNode(node1)  

               self.loadAnimation(withKey: "walking", sceneName: "art.scnassets/WalkAround/SambaArmtr", animationIdentifier: "SambaArmtr-1")  
           
      
  
func loadAnimation(withKey: String, sceneName:String, animationIdentifier:String)   
    let sceneURL = Bundle.main.url(forResource: sceneName, withExtension: "dae")  
    let sceneSource = SCNSceneSource(url: sceneURL!, options: nil)  

    if let animationObject = sceneSource?.entryWithIdentifier(animationIdentifier, withClass: CAAnimation.self)   
        // The animation will only play once  
        animationObject.repeatCount = 1  
      

我尝试在以下两种方法中使用node.presentation.position 来获取对象的当前位置。

func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)          
// Or
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor)

如果动画开始后我不再移动设备,那么这些方法将不会被调用,直到我获得相同的节点位置。这就是为什么我没有得到我错的地方。或者有什么方法可以在 ARKit 中进行动画时获取对象的当前位置?

【问题讨论】:

我不太明白这个问题,请改写问题。这似乎不太可能奏效,因为 node 变量被重新声明并且从未添加到场景中。 【参考方案1】:

我不知道有什么方法可以在嵌入式动画中获取当前帧。话虽如此,模型中嵌入的动画使用 CoreAnimation 来运行动画。您可以使用CAAimationDelegate 来监听动画的开始/结束事件并运行计时器。计时器将为您提供动画在哪一帧上的最佳估计。

参考资料: SceneKit 动画内容文档:https://developer.apple.com/documentation/scenekit/animation/animating_scenekit_content

CAAnimationDelegate 文档:https://developer.apple.com/documentation/quartzcore/caanimationdelegate

【讨论】:

以上是关于在 ARKit 中进行动画时如何获取 3D 对象的当前位置?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ARkIt2 中将图像包裹在 3d 对象上?

按钮旋转 3D 对象 ARKit 2

ios - ARKit 3D模型素材

您如何在 Google 表格中进行动态/依赖下拉菜单?

3d 模型 SceneKit/ARKit 的哪种格式文件更好用

iOS-ARKit扫描和检测3D对象-Scanning and Detecting 3D Objects