Camera does not follow aircraft in Scenekit

I have a flying plane that I am following, and I also show the path that the plane was following. I draw cylinders as a line to draw a path. Its a kind of line drawing between two points. I have a CameraNode that is set to (0,200,200) initially. At this moment I see a plane. But when I start my flight. He comes out of the screen. I want 2 things:

  • Keep an eye on the plane (the path does not matter).
  • Show all the way, as well as the plane.

I tried to find min ad max x, y and z and average, but it does not work. If you see the gif below, it is too enlarged, and the plane left the screen

Here is how I installed my camera:

- (void)setUpCamera { SCNScene *workingScene = [self getWorkingScene]; _cameraNode = [[SCNNode alloc] init]; _cameraNode.camera = [SCNCamera camera]; _cameraNode.camera.zFar = 500; _cameraNode.position = SCNVector3Make(0, 60, 50); [workingScene.rootNode addChildNode:_cameraNode]; SCNNode *frontCameraNode = [SCNNode node]; frontCameraNode.position = SCNVector3Make(0, 100, 50); frontCameraNode.camera = [SCNCamera camera]; frontCameraNode.camera.xFov = 75; frontCameraNode.camera.zFar = 500; [_assetActivity addChildNode:frontCameraNode]; //_assetActivity is the aircraft node. 

}

Here's how I change the position of a camera that doesn't work:

 - (void)showRealTimeFlightPath { DAL3DPoint *point = [self.aircraftLocation convertCooridnateTo3DPoint]; DAL3DPoint *previousPoint = [self.previousAircraftLocation convertCooridnateTo3DPoint]; self.minCoordinate = [self.minCoordinate findMinPoint:self.minCoordinate currentPoint:point]; self.maxCoordinate = [self.minCoordinate findMaxPoint:self.maxCoordinate currentPoint:point]; DAL3DPoint *averagePoint = [[DAL3DPoint alloc] init]; averagePoint = [averagePoint averageBetweenCoordiantes:self.minCoordinate maxPoint:self.maxCoordinate]; SCNVector3 positions[] = { SCNVector3Make(point.x,point.y,point.z) , SCNVector3Make(previousPoint.x,previousPoint.y,previousPoint.z) }; SCNScene *workingScene = [self getWorkingScene]; DALLineNode *lineNodeA = [[DALLineNode alloc] init]; [lineNodeA init:workingScene.rootNode v1:positions[0] v2:positions[1] radius:0.1 radSegementCount:6 lineColor:[UIColor greenColor]] ; [workingScene.rootNode addChildNode:lineNodeA]; self.previousAircraftLocation = [self.aircraftLocation mutableCopy]; self.cameraNode.position = SCNVector3Make(averagePoint.x, averagePoint.y, z); self.pointOfView = self.cameraNode; 

}

A code with a quick or objective c is welcome.

Thanks!!

+5
source share
1 answer

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.

+2
source

Source: https://habr.com/ru/post/1270456/


All Articles