【问题标题】:Rotate SCNNode to where user taps将 SCNNode 旋转到用户点击的位置
【发布时间】:2017-05-01 05:43:22
【问题描述】:

我希望 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)
    }
}

【问题讨论】:

    标签: ios swift scenekit


    【解决方案1】:

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

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

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

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

    这可以通过您的 SCNView 的 unprojectPoint: 方法来完成。 您必须向它传递一个 SCNVector3 参数,该参数保存屏幕点击的 X 和 Y 坐标,它的 Z 分量介于 0.0 和 1.0 之间,表示要在场景 3D 空间中投影的 2D 点的深度(在近和相机的远剪裁平面)。我猜你这里需要它接近 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;
    

    【讨论】:

      猜你喜欢
      • 2016-09-26
      • 2015-03-12
      • 1970-01-01
      • 2018-01-20
      • 1970-01-01
      • 2012-05-14
      • 2016-03-18
      • 2019-11-06
      • 1970-01-01
      相关资源
      最近更新 更多