The first behavior that you describe will be most easily achieved by tying the gaze restriction and the distance limit aimed at the plane.
let lookAtConstraint = SCNLookAtConstraint(target: aircraft) let distanceConstraint = SCNDistanceConstraint(target: aircraft) distanceConstraint.minimumDistance = 10 // set to whatever minimum distance between the camera and aircraft you'd like distanceConstraint.maximumDistance = 10 // set to whatever maximum distance between the camera and aircraft you'd like camera.constraints = [lookAtConstraint, distanceConstraint]
For iOS 10 and earlier, you can implement distance limitation using SCNTransformConstraint . Here is a basic (albeit slightly ugly) implementation that uses linear interpolation to update node position.
func normalize(_ value: Float, in range: ClosedRange<Float>) -> Float { return (value - range.lowerBound) / (range.upperBound - range.lowerBound) } func interpolate(from start: Float, to end: Float, alpha: Float) -> Float { return (1 - alpha) * start + alpha * end } let target = airplane let minimumDistance: Float = 10 let maximumDistance: Float = 15 let distanceConstraint = SCNTransformConstraint(inWorldSpace: false) { (node, transform) -> SCNMatrix4 in let distance = abs(sqrt(pow(target.position.x - node.position.x, 2) + pow(target.position.y - node.position.y, 2) + pow(target.position.z - node.position.z, 2))) let normalizedDistance: Float switch distance { case ...minimumDistance: normalizedDistance = self.normalize(minimumDistance, in: 0 ... distance) case maximumDistance...: normalizedDistance = self.normalize(maximumDistance, in: 0 ... distance) default: return transform } node.position.x = self.interpolate(from: target.position.x, to: node.position.x, alpha: normalizedDistance) node.position.y = self.interpolate(from: target.position.y, to: node.position.y, alpha: normalizedDistance) node.position.z = self.interpolate(from: target.position.z, to: node.position.z, alpha: normalizedDistance) return transform }
The second behavior can be implemented by defining the bounding box of your plane and all its path segments in the local coordinate space of the camera, and then updating the distance of the camera from the center of this bounding box to crop all of these nodes into the viewport. frameNodes(_:) , a convenient method that implements this functionality, was introduced in iOS 11 and defined in SCNCameraController . I would recommend using it if possible, if you do not want to immerse yourself in trigonometry yourself. You can use the default camera controller to view the scene or create a temporary instance, depending on the needs of your application.
source share