2016-05-16 15 views
2

私はSceneKitを使用しており、ユーザーはパンジェスチャーを使用して球の中で見ているものを回転させることができます。これはうまく働いていますが、私は球体をパンのジェスチャーの方向に少し回転させて、少し反応が速くなるようにしたいと思います。SceneKit - パンジェスチャーを介して回転した球にドリフトを追加する

ここでのシーンのために私の設定です:

// Create scene 
    let scene = SCNScene() 

    sceneView.scene = scene 

    let panRecognizer = UIPanGestureRecognizer(target: self, 
               action: #selector(ViewController.handlePanGesture(_:))) 

    sceneView.addGestureRecognizer(panRecognizer) 

    //Create sphere 
    let sphere = SCNSphere(radius: 50.0) 

    // sphere setup 

    sphereNode = SCNNode(geometry: sphere) 

    sphereNode!.position = SCNVector3Make(0,0,0) 
    scene.rootNode.addChildNode(sphereNode!) 

    // Create camera 
    let camera = SCNCamera() 

    // camera setup 

    cameraNode = SCNNode() 

    cameraNode!.camera = camera 
    cameraNode!.position = SCNVector3Make(0, 0, 0) 

    cameraOrbit = SCNNode() 

    cameraOrbit!.addChildNode(cameraNode!) 
    scene.rootNode.addChildNode(cameraOrbit!) 

    let lookAtConstraint = SCNLookAtConstraint(target: sphereNode!) 
    lookAtConstraint.gimbalLockEnabled = true 
    cameraNode!.constraints = [lookAtConstraint] 

    sceneView.pointOfView = cameraNode 

そして、ここでは、(SCNCamera limit arcball rotationの礼儀)パンジェスチャーが現在の処理方法である。

let translation = sender.translationInView(sender.view!) 
    let widthRatio = Float(translation.x)/Float(sender.view!.frame.size.width) + lastWidthRatio 
    let heightRatio = Float(translation.y)/Float(sender.view!.frame.size.height) + lastHeightRatio 

    self.cameraOrbit?.eulerAngles.y = Float(-2 * M_PI) * widthRatio 
    self.cameraOrbit?.eulerAngles.x = Float(-M_PI) * heightRatio 

    if (sender.state == .Ended) { 
     lastWidthRatio = widthRatio 
     lastHeightRatio = heightRatio 
    } 

私が開始する場所がわからないんだけど僅かながら回転運動を継続する。たぶん、physicsBodyを追加し、力をかけることがありますか? eulerAnglesの変化をアニメーション化していますか?

答えて

4

これまでのように私が扱った方法は、ジェスチャーハンドラをジェスチャ状態の開始、変更、終了のセクションに分割することです。ローテーションがうまくいく場合は、if (sender.state == .Ended)ステートメントの最後にコードを追加するだけです。もしsender.velocityInView(sender.view!)を使用してビュー内のパンの速度を見つけ、次いでEaseOutタイミングモードでノードを回転させるSCNActionを追加し、前のように水平成分を見つけることができるlastHeightRatio = heightRatio

ビューの速度(ポイント単位)を回転させたい角度(ラジアン単位)に変換するには、乗数が必要になることがあります。 10ポイントの速度は比較的小さく、非常に速い回転をもたらす。

タッチが残りの回転を停止させたい場合は、ジェスチャが再び開始されるときに、ノードからすべてのアクションを削除する必要があります。

一部sampelコードは次のようになります。

if (sender.state == .Ended) { 
    lastWidthRatio = widthRatio 
    lastHeightRatio = heightRatio 

    // Find velocity 
    let velocity = sender.velocityInView(sender.view!) 

    // Create Action for whichever axis is the correct one to rotate about. 
    // The 0.00001 is just a factor to provide the rotation speed to pan 
    // speed ratio you'd like. Play with this number and the duration to get the result you want 
    let rotate = SCNAction.rotateByX(velocity.x * 0.00001, y: 0, z: 0, duration: 2.0) 

    // Run the action on the camera orbit node (if I understand your setup correctly) 
    cameraOrbit.runAction(rotate) 
} 

これは、あなたが始めるのに十分でなければなりません。

+0

私も同様のことをしました - ありがとう!私の問題は、球の最後の休止位置がその値が最後に設定された時間よりもさらに回転しているので、 'lastRatio'値がオフになっていることです。したがって、ユーザが次のパンジェスチャを行うために行くと、ドリフトが開始される前の位置にカメラが「ジャンプ」し、「ユーラーアングル」がリセットされる。もしあなたがそれについて考えているなら、私はすべて耳です。 –

+0

ええ、アクションが完了したときにlastRatioの値を再び更新する 'runAction'に補完ハンドラを追加してみてください。 –

+0

@AndyHeard私はそれを試みましたが、それは動作していないと私は本当に理由を理解していません。私のコードスニペット '' 'lastWidthRatio + =(((-velocity.x * 0.001)* 2)/ sender.view.frame.size.width);' '' –

関連する問題