swift 如何使用UITapGestureRecognizer在SCN视图中移动SCN节点?

pgccezyw  于 2023-02-28  发布在  Swift
关注(0)|答案(2)|浏览(135)

我创建了一个SCNView,并希望使用UITapGestureRecognizer在视图中移动SCNNode;然而,我实现的代码似乎不起作用。节点有时会移动,但它们永远不会移动到正确的位置。有人知道我在这里做错了什么吗?

@objc func handleTapGesture(_ gesture: UITapGestureRecognizer) {
        let location = gesture.location(in: scnView)
        
        guard let result = self.scnView?.hitTest(location, options: nil).first else { return }
        let transform = result.simdModelTransform
        let newPosition = SCNVector3(transform.columns.3.x, node.position.y, transform.columns.3.z)
        
        node.position = newPosition
    }
1dkrff03

1dkrff031#

看起来您对SCNView中hitTest的用法感到困惑。首先,请注意hitTest(_:options:)将在给定场景中搜索与触摸点的光线投射命中对应的对象/节点。这解释了为什么有时您的代码无法工作,因为如果找不到对象,命中测试结果将为空。
要使事情按预期工作,您必须使用以下代码将CGPoint中的点投影到场景中,这也需要您提供深度。

func pointToSCNVector3(view: SCNView, depth: Float, point: CGPoint) -> SCNVector3 {
    let projectedOrigin = view.projectPoint(SCNVector3Make(0, 0, depth))
    let locationWithz   = SCNVector3Make(Float(point.x), Float(point.y), projectedOrigin.z)
    return view.unprojectPoint(locationWithz)
}

然后使用输出设置节点位置

@objc func handleTapGesture(_ gesture: UITapGestureRecognizer) {
        let location = gesture.location(in: scnView)
        node.position = pointToSCNVector3(view: scnView, depth: 50, point: location)
    }
vfh0ocws

vfh0ocws2#

你也可以尝试使用PanGesture。让我给予你同样的示例代码。

let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan(panGesture:)))
view.addGestureRecognizer(panRecognizer)

@objc func handlePan(panGesture: UIPanGestureRecognizer) {

 guard let view = view as? SCNView else { return }
let location = panGesture.location(in: self.view)
 switch panGesture.state {
case .began:
 guard let hitNodeResult = view.hitTest(location, options: nil).first else { return }
panStartZ = CGFloat(view.projectPoint(lastPanLocation!).z)
lastPanLocation = hitNodeResult.worldCoordinates
case .changed:
 let worldTouchPosition = view.unprojectPoint(SCNVector3(location.x, location.y, panStartZ!))
let movementVector = SCNVector3(
 worldTouchPosition.x - lastPanLocation!.x,
worldTouchPosition.y - lastPanLocation!.y,
worldTouchPosition.z - lastPanLocation!.z)
geometryNode.localTranslate(by: movementVector)
self.lastPanLocation = worldTouchPosition
default:
 break
}
}

相关问题