Hello all,
I have a pretty simple scene set up at the moment displaying a single centered molecule (molNode). I have been attempting to make use of SCNCameraController to avoid reimplementing arcball camera control. Unfortunately, I'm running into some very strange behaviors with the below settings on iOS, which do not seem to be present on macOS.
I do not have a scene file, molNode is generated from a macromolecular information file. It consists, roughly, of a few hundred spheres and some cylinders. I have also included a snippet in which I perform a small hack to attach a light to the "free camera" node which SceneKit manages. At the first user interaction with the scene, SceneKit hijacks the only camera in the scene and attaches it to this node, so I use this observation to keep my directional light attached to the camera. This observation is handled every time one performs a double-tap to reset the viewport, as well as on the first user interaction. I doubt that it is related.
// molNode is set up...
// Camera and Lighting
let camera = SCNCamera()
camera.usesOrthographicProjection = true
camera.orthographicScale = 30
let cameraNode = SCNNode()
cameraNode.camera = camera // this camera will be removed from this node by SceneKit automatically.
scene.rootNode.addChildNode(cameraNode)
cameraNode.position = SCNVector3(x: 0, y: 0, z: 30)
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = .ambient
ambientLightNode.light!.color = UIColor(red: 0.14, green: 0.14, blue: 0.14, alpha: 1.0)
scene.rootNode.addChildNode(ambientLightNode)
let cameraLightNode = SCNNode()
cameraLightNode.light = SCNLight()
cameraLightNode.light!.type = .directional // defaults to (0, 0, -1), which matches the camera.
cameraLightNode.light!.intensity = 800
scene.rootNode.addChildNode(cameraLightNode)
// Scene View Setup
let scnView = self.view as! SCNView
scnView.preferredFramesPerSecond = 60
scnView.scene = scene
scnView.allowsCameraControl = true
scnView.defaultCameraController.interactionMode = .orbitArcball
scnView.defaultCameraController.target = molNode.position
scnView.defaultCameraController.inertiaEnabled = true
self.povObservation = scnView.defaultCameraController.observe(\.pointOfView, options: [.new]) { (cameraController, change) in
if let pointOfView = cameraController.pointOfView {
// Whenever SceneKit creates a new pointOfView node and attaches the camera to it,
// recover the camera light and attach it as well.
cameraLightNode.removeFromParentNode()
pointOfView.addChildNode(cameraLightNode)
}
}1. The first problem is that y-axis camera control is inverted. Drawing an arc vertically results in the opposite of expected rotation for the "pinch and drag the surface of the sphere" idiom of arcball control. This does not occur on macOS with mouse control. There, dragging the scene rotates as one would expect. This occurs in both arcball interaction modes. It does not occur in .orbitTurntable or .orbitAngleMapping... however turntable is not appropriate for my use case, and angleMapping does not handle rotations for diagonal drag/swipes intuitively (it results in rotations along multiple degrees of freedom).
2. The second, even more confounding issue, has to do with inertia. While "drag" control is inverted, inertia is not. This produces some extremely jarring results, namely that a drag will move in one direction, but when released, the model continues moving inertially in the direction opposite to the drag. "Flicking" gestures therefore result in the kind of movement you would expect, while dragging does not. Even moreso than #1, this simply seems wrong and entirely unintuitive.
I am somewhat apprehensive that this is an error/bug in SceneKit. If one watches the WWDC 2017 video (604) in which SCNCameraController is introduced, the demonstration of arcball control there works the way one would expect, e.g. without the inverted vertical orbiting. Presumably this is because the demo was on macOS.
I have been attempting to find means to remedy these issues (without implementing my own arcball camera control), but have so far come up short.
Thank you all in advance for any help you may be able to provide.
-
—
Varaha
Add a CommentDid you manage to solve this?