2017-08-24 103 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

由於sceneview包含一個球。所以我只想把這個手勢應用到球/球體 – user8426652

+0

這是一個錯誤的想法。 –

回答

2

我們有,裏面有包含我們的球節點sphereNode一個視圖控制器。 要旋轉球體,我們可以使用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圍繞y軸旋轉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

這是我創造了這個小演示:

Demo


這種方法有兩個主要缺點。

  1. 它只節點周圍旋轉座標原點,只工作,如果正常節點的位置是SCNVector3Zero

  2. 它確實需要手勢既不速度考慮在內,也沒有球繼續旋轉時,手勢停止。 使用此方法無法輕鬆實現類似於表格視圖的效果,您可以輕輕地翻動手指,並且表格視圖快速滾動然後放慢。 解決方案之一就是使用物理系統。

相關問題