ios - 将 SCNNode 旋转到用户点击的位置

标签 ios swift scenekit

我希望 bobNode 查看用户在屏幕上点击的位置。我正在努力旋转 bobNode。我正在记录点击位置,当我点击时它会起作用。我从来没有得到 print("Angle: "+ String(describing: angle))。唯一一次 print("Testing Renderer function") 是在应用程序加载时打印 11 次,之后就不再打印了。我想我只是对旋转 bobNode 的概念感到困惑。如果我做错了,有人可以向我解释如何去做。

代码:

var sceneView: SCNView! // for now
var bobNode: SCNNode!
var lastTouch: CGPoint? = nil

let bobScene = SCNScene(named: "art.scnassets/man.scn")!

func start(){
    let scene = SCNScene()

    sceneView.delegate = self

    bobNode = bobScene.rootNode.childNode(withName: "Player", recursively: true)!

    bobNode.scale = SCNVector3(x: 0.15, y: 0.15, z: 0.15)
    bobNode.eulerAngles = SCNVector3(x: GLKMathDegreesToRadians(75), y: 0.0, z: GLKMathDegreesToRadians(180))//Don't use rotaion THAT shit is retarded

    scene.rootNode.addChildNode(bobNode)

    sceneView.scene = scene

    let camera = SCNCamera()
    let cameraNode = SCNNode()
    cameraNode.camera = camera
    cameraNode.position = SCNVector3(x: bobNode.position.x, y: bobNode.position.y, z: 10.0)

    scene.rootNode.addChildNode(cameraNode)        

}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    handleTouches(touches: touches)
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    handleTouches(touches: touches)
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    handleTouches(touches: touches)
}

private func handleTouches(touches: Set<UITouch>) {
    for touch in touches {
        let touchLocation = touch.location(in: sceneView)
        lastTouch = touchLocation
        print("Touch: " + String(describing: lastTouch))
    }
}

func renderer(_ renderer: SCNSceneRenderer, didSimulatePhysicsAtTime time: TimeInterval) {
    if let _ = bobNode {
        updatePlayer()
    }
}

func updatePlayer() {
    print("Testing Renderer function")
    if let touch = lastTouch {
        let currentPosition = bobNode.position

        let angle = atan2(CGFloat(currentPosition.y) - CGFloat(touch.y), CGFloat(currentPosition.x) - CGFloat(touch.x)) + CGFloat(Double.pi)

        print("Angle: " + String(describing: angle))

        let rotateAction = SCNAction.rotateBy(x: 0.0, y: angle, z: 0.0, duration: 0)

        bobNode.runAction(rotateAction)
    }
}

最佳答案

最简单的解决方案是将 SCNLookAtConstraint 添加到 bobNode

当您创建 SCNLookAtConstraint 时,它需要一个目标 SCNNode 并且 SceneKit 将在每一帧将 bobNode 旋转到给定的目标。

我们称它为 targetNode(大概没有几何体),它位于场景 3D 空间中用户点击位置的正下方。它的位置需要随着用户点击的变化而更新。

当然,用户点击表示为屏幕坐标空间中的 2D 点,需要将其转换为场景的 3D 空间。

这可以通过您的 SCNView 的 unprojectPoint: 方法来完成。 你必须给它传递一个 SCNVector3 参数,它保存着屏幕点击的 X 和 Y 坐标,它的 Z 分量在 0.0 和 1.0 之间,代表 2D 点在场景 3D 空间中投影的深度(在 near 之间)和相机的远剪裁平面)。我猜你需要它接近 0.0。

设置

// Create the look-at constraint
SCNLookAtConstraint lookAtConstr = [SCNLookAtConstraint lookAtConstraintWithTarget:];

// Set to bobNode's .constraints property
bobNode.constraints = @[lookAtConstr];

在每一帧

// tapLocation is the screen tap location from UIEvent
SCNVector3 tapPosition = SCNVector3Make(tapLocation.x, tapLocation.y, 0.0);

// unproject from 2D screen to 3D scene space
SCNVector3 targetNodePosition = [scnView unprojectPoint:tapPosition];

// Update the targetNode position
targetNode.position = targetNodePosition;

关于ios - 将 SCNNode 旋转到用户点击的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43623130/

相关文章:

ios - 如何在 Scenekit 中更新我的逻辑方法

ios - 在 ARKit 框架中设置光照

ios - 基于对多关系另一端的属性,为项目构造核心数据获取的最佳方法

ios - 如何获取我的框架代码的 bundle ?

ios - 如何让iPhone/iPad完全忘记某个应用的媒体授权状态?

objective-c - 适用于 iOS 的全功能文件下载管理器

ios - 在 UIPageViewController 内的 ViewController 内的 ScrollView 中检测 ScrollOffset?

swift - 为什么这个 UIView 会移动?

ios - 我在 Swift 2 中使用 MailCore2 时出错

ios - 如何在没有深度值的情况下使用 SceneKit 的 unprojectPoint 将 2D 点转换为 3D?