2017-08-24 6 views
1

SCNSphereを作成したので、惑星のように見えます。これはまさに私が欲しいものです。私の次の目標は、ユーザーがパンジェスチャ認識器を使用して球を回転できるようにすることです。 X軸またはY軸回りに回転させることができます。私はそれをどうやってできるのだろうと思っていただけです。これは私がこれまで持っていたものです。パンジェスチャ認識ツールを使用してSCNSphereを回転させる方法

origin = sceneView.frame.origin 
node.geometry = SCNSphere(radius: 1) 
node.geometry?.firstMaterial?.diffuse.contents = UIImage(named: "world.jpg") 

let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(CategoryViewController.panGlobe(sender:))) 
sceneView.addGestureRecognizer(panGestureRecognizer) 

func panGlobe(sender: UIPanGestureRecognizer) { 
    // What should i put inside this method to allow them to rotate the sphere/ball 
} 
+0

シーンビューにジェスチャを追加したいのはなぜですか? hitTestを検索します。私はそれが簡単ではないとあなたに伝えることができます。 –

+0

シーンビューにボールが含まれているためです。だから私はジェスチャーをボール/球に適用したいだけです – user8426652

+0

それは間違った考えです。 –

答えて

2

私たちの球を含むノードsphereNodeを含むViewControllerがあります。 球を回転するには、UIPanGestureRecognizerを使用します。 認識装置は、指が画面上を移動した合計距離を報告するので、私たちは、報告された最後の点をキャッシュする。

var previousPanPoint: CGPoint? 
let pixelToAngleConstant: Float = .pi/180 
func handlePan(_ newPoint: CGPoint) { 
    if let previousPoint = previousPanPoint { 
     let dx = Float(newPoint.x - previousPoint.x) 
     let dy = Float(newPoint.y - previousPoint.y) 

     rotateUp(by: dy * pixelToAngleConstant) 
     rotateRight(by: dx * pixelToAngleConstant) 
    } 

    previousPanPoint = newPoint 
} 

我々は最後の認識器と呼ばれるので、私たちの指が各方向に移動したどのくらいの画素にdxdyを計算します。 pixelToAngleConstantでは、ピクセル値を角度(randians)で変換して球を回転させます。より速い回転のために大きな定数を使用してください。

ジェスチャ認識プログラムは、ジェスチャが開始、終了、または指が移動されたかどうかを判断するために使用できるstateを返します。 ジェスチャーが始まると、指の位置がpreviousPanPointに保存されます。 指が動くと、上の関数が呼び出されます。 ジェスチャーが終了またはキャンセルされた場合、私たちはpreviousPanPointをクリアします。

@objc func handleGesture(_ gestureRecognizer: UIPanGestureRecognizer) { 
    switch gestureRecognizer.state { 
    case .began: 
     previousPanPoint = gestureRecognizer.location(in: view) 
    case .changed: 
     handlePan(gestureRecognizer.location(in: view)) 
    default: 
     previousPanPoint = nil 
    } 
} 

球体をどのように回転させますか? 関数rotateUprotateRightは、より一般的な関数であるrotate(by: around:)を呼び出すだけで、角度だけでなく回転軸も受け入れます。 rotateUpは、x軸を中心に、rotateRightの周りを回転します。我々は、ノードが翻訳されていない/我々は、ローカル座標系のノードの原点を中心に回転することを前提としているため

func rotateUp(by angle: Float) { 
    let axis = SCNVector3(1, 0, 0) // x-axis 
    rotate(by: angle, around: axis) 
} 

func rotateRight(by angle: Float) { 
    let axis = SCNVector3(0, 1, 0) // y-axis 
    rotate(by: angle, around: axis) 
} 

rotate(by:around:)は、この場合には相対的な単純です。 一般的なケースを見ると、すべてが少し複雑になりますが、この回答はほんのわずかな出発点です。

func rotate(by angle: Float, around axis: SCNVector3) { 
    let transform = SCNMatrix4MakeRotation(angle, axis.x, axis.y, axis.z) 
    sphereNode.transform = SCNMatrix4Mult(sphereNode.transform, transform) 
} 

我々はangleaxisから回転行列を作成し、新しいtransformを取得するために計算されたものと私たちの球の古いtransformを掛けます。このアプローチは、2つの主要な欠点を持っている

Demo


これは私が作成した小さなデモです。

  1. それはそれは考慮にジェスチャーの速さもない取るんや球が時に回転し続けるんだけ座標原点ノードの周りを回転すると、ノードの位置はSCNVector3Zero

  2. ある場合にのみ、正常に動作しますジェスチャーは止まる。 このアプローチでは、指をめくることができ、テーブルビューが速くスクロールして減速するテーブルビューと同様の効果を簡単に達成できません。 解決策の1つは、物理システムを使用することです。

関連する問題