在XZ平面上拖动对象

我正在开发一个增强现实应用程序,我希望能够在空间中拖动一个对象。 我在SO中找到的解决方案的问题,即使用projectPoint / unprojectPoint建议的解决方案,是它们产生沿XY平面的移动。

我试图使用屏幕上的手指移动作为节点的xz坐标的偏移量。 问题是要考虑很多东西(摄像机的位置,节点的位置,节点的旋转等)。

有更简单的方法吗?

首先你需要创建地板或非常大的平面几米(我有10个)低于原点。 这可以确保您的hittest始终返回值。 然后使用平移手势:

 //store previous coordinates from hittest to compare with current ones var PCoordx: Float = 0.0 var PCoordz: Float = 0.0 @objc func move(_ gestureRecognizer: UIPanGestureRecognizer){ if gestureRecognizer.state == .began{ let hitNode = sceneView.hitTest(gestureRecognizer.location(in: sceneView), options: nil) PCoordx = (hitNode.first?.worldCoordinates.x)! PCoordz = (hitNode.first?.worldCoordinates.z)! } // when you start to pan in screen with your finger // hittest gives new coordinates of touched location in sceneView // coord-pcoord gives distance to move or distance paned in sceneview if gestureRecognizer.state == .changed { let hitNode = sceneView.hitTest(gestureRecognizer.location(in: sceneView), options: nil) if let coordx = hitNode.first?.worldCoordinates.x{ if let coordz = hitNode.first?.worldCoordinates.z{ let action = SCNAction.moveBy(x: CGFloat(coordx-PCoordx), y: 0, z: CGFloat(coordz-PCoordz), duration: 0.1) node.runAction(action) PCoordx = coordx PCoordz = coordz } } gestureRecognizer.setTranslation(CGPoint.zero, in: sceneView) } if gestureRecognizer.state == .ended{ PCoordx = 0 PCoordz = 0 } } 

在我的情况下,只有一个节点,所以我没有检查是否所需的节点被录音。 如果您有许多节点,您可以随时检查它。

如果我理解正确,我会使用添加到ARSCNView的UIPanGestureRecognizer来完成此操作。

在我的情况下,我想检查pan是否在给定的虚拟对象上启动并跟踪它是什么,因为我可以有多个,但如果你只有一个对象,则可能不需要targetNode变量。 我使用700常量来划分我通过反复试验得到它使翻译更顺畅,你可能需要根据你的情况改变它。

向上移动手指,将物体远离相机移动并向下移动物体使其移近。 手指的水平移动使物体左/右移动。

 @objc func onTranslate(_ sender: UIPanGestureRecognizer) { let position = sender.location(in: scnView) let state = sender.state if (state == .failed || state == .cancelled) { return } if (state == .began) { // Check pan began on a virtual object if let objectNode = virtualObject(at: position).node { targetNode = objectNode latestTranslatePos = position } } else if let _ = targetNode { // Translate virtual object let deltaX = Float(position.x - latestTranslatePos!.x)/700 let deltaY = Float(position.y - latestTranslatePos!.y)/700 targetNode!.localTranslate(by: SCNVector3Make(deltaX, 0.0, deltaY)) latestTranslatePos = position if (state == .ended) { targetNode = nil } }