I have a scene setup with SCNCamera that rotates around an object.
What would be the best way to limit the extents of rotation the camera can achieve around the object?
Example: instead of being able to rotate around a whole sphere, how would I limit rotation to a single hemisphere?
My first attempt was to see if there was any clamps for .allowsCameraControl. Could not find anything.
I then tried adapting c# Unity : mouse orbit script, no luck.
Some pointers on how to approach or solve this would great.
Boilerplate Arcball thanks to this answer.
var lastWidthRatio: Float = 0
var lastHeightRatio: Float = 0
let camera = SCNCamera()
let cameraNode = SCNNode()
let cameraOrbit = SCNNode()
override func viewDidLoad() {
super.viewDidLoad()
// create a new scene
let scene = SCNScene(named: "art.scnassets/ship.scn")!
// create and add a camera to the scene
camera.usesOrthographicProjection = true
camera.orthographicScale = 9
camera.zNear = 0
camera.zFar = 100
cameraNode.position = SCNVector3(x: 0, y: 0, z: 50)
cameraNode.camera = camera
cameraOrbit.addChildNode(cameraNode)
scene.rootNode.addChildNode(cameraOrbit)
// retrieve the ship node
let ship = scene.rootNode.childNodeWithName("ship", recursively: true)!
// retrieve the SCNView
let scnView = self.view as! SCNView
// set the scene to the view
scnView.scene = scene
// add a tap gesture recognizer
let gesture = UIPanGestureRecognizer(target: self, action: "panDetected:");
scnView.addGestureRecognizer(gesture);
}
func panDetected(sender: UIPanGestureRecognizer) {
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
print(Float(-2 * M_PI) * widthRatio)
if (sender.state == .Ended) {
lastWidthRatio = widthRatio % 1
lastHeightRatio = heightRatio % 1
}
}
widthRatio % 1
). The widthRatio will vary from -1 to 1, but when a user rotates past the limit, the value might change from -0.9 to, say, -1.2. The modulus gets applied, resulting in a value of 0.2, causing an abrupt jump to the other side of the sphere. One way around that would be to add 2 if the value falls below -1, and subtract 2 if the end of the rotation is above 1. Using that method, moving from the -0.9 position to -1.2 would result in a value of 0.8, which I believe is the desired result. – Dave Ruske