I created an SCNSphere so now it looks like a planet kind of. This is exactly what I want. My next goal is to allow users to rotate the sphere using a pan gesture recognizer. They are allowed to rotate it around the X or Y axis. I was just wondering how I can do that. This is what I have so far.
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
}
Below is what I tried, not sure whether it is accurate with respect to angles but...it sufficed most of my needs....
Sample Github-EarthRotate
We have a ViewController that contains a node
sphereNode
that contains our sphere. To rotate the sphere we could use aUIPanGestureRecognizer
. Since the recognizer reports the total distance our finger has traveled on the screen we cache the last point that was reported to us.We calculate
dx
anddy
with how much pixel our finger has traveled in each direction since we last called the recognizer. With thepixelToAngleConstant
we convert our pixel value in an angle (in randians) to rotate our sphere. Use a bigger constant for a faster rotation.The gesture recognizer returns a
state
that we can use to determine if the gesture has started, ended, or the finger has been moved. When the gesture starts we save the fingers location inpreviousPanPoint
. When our finger moves we call the function above. When the gesture is ended or canceled we clear ourpreviousPanPoint
.How do we rotate our sphere? The functions
rotateUp
androtateRight
just call our more general function,rotate(by: around:)
which accepts not only the angle but also the axis to rotate around.rotateUp
rotates around the x-axis,rotateRight
around the y-axis.The
rotate(by:around:)
is in this case relative simple because we assume that the node is not translated/ we want to rotate around the origin of the nodes local coordinate system. Everything is a little more complicated when we look at a general case but this answer is only a small starting point.We create a rotation matrix from the
angle
and theaxis
and multiply the oldtransform
of our sphere with the calculated one to get the newtransform
.This is the little demo I created:
This approach has two major downsides.
It only rotates around the nodes coordinate origin and only works properly if the node's position is
SCNVector3Zero
It does takes neither the speed of the gesture into account nor does the sphere continue to rotate when the gesture stops. An effect similar to a table view where you can flip your finger and the table view scrolls fast and then slows down can't be easily achieved with this approach. One solution would be to use the physics system for that.