After coding in the SceneKit lab, I was able to produce a scene that displays a sphere that rotates over time. The Apple Engineer suggested that I use the new scene view snapshot() method in order to export the scene as an image. However, the image appears to render before the sphereNode.runAction(SCNAction.rotate()) method completed despite it having a duration of 0.0. I believe this is because that method is an animation method.
After testing, I have found that the use of the sphereNode.rotate() method does work with the snapshot. However, that method uses quaternions rather than the angles I was working with before.
I am having a hard time understanding how to convert from my original angles to the new quaternions to achieve the same result.
As of now, I am using
If somebody could explain how to either continue rotating with an angle while working with the snapshot method or how to convert from my current rotation to the quaternion method, I would greatly appreciate the help. Below is the full code for my scene.
After testing, I have found that the use of the sphereNode.rotate() method does work with the snapshot. However, that method uses quaternions rather than the angles I was working with before.
I am having a hard time understanding how to convert from my original angles to the new quaternions to achieve the same result.
As of now, I am using
Code Block swift sphereNode.rotation = SCNVector4(x: 0.0, y: 1.0, z: 0.0, w: 0.0) sphereNode.runAction(SCNAction.rotate(by: 1.1*CGFloat(Double.pi), around: SCNVector3(x: 0.0, y: 1.0, z: 0.0), duration: 0.0))
If somebody could explain how to either continue rotating with an angle while working with the snapshot method or how to convert from my current rotation to the quaternion method, I would greatly appreciate the help. Below is the full code for my scene.
Code Block swift var sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: 500, height: 500)) extension SCNMaterial { convenience init(color: UIColor) { ... } convenience init(image: UIImage) { ... } } func addBloom() -> [CIFilter]? { ... return [bloomFilter] } func sceneSetup(completion: () -> ()) { let scene = SCNScene() sceneView.backgroundColor = UIColor(red: 0.09, green: 0.09, blue: 0.09, alpha: 1.00) let sphere = SCNSphere(radius: 1) sphere.segmentCount = 100 let mat = SCNMaterial(image: UIImage(named: "desaturated.png")!) sphere.materials = [mat] sphere.firstMaterial?.diffuse.wrapS = SCNWrapMode.clamp sphere.firstMaterial?.diffuse.wrapT = SCNWrapMode.clamp let sphereNode = SCNNode(geometry: sphere) sphereNode.filters = addBloom() scene.rootNode.addChildNode(sphereNode) sceneView.scene = scene let ambientLightNode = SCNNode() ambientLightNode.light = SCNLight() ambientLightNode.light!.type = SCNLight.LightType.ambient ambientLightNode.light!.color = UIColor(white: 0.8, alpha: 1.0) scene.rootNode.addChildNode(ambientLightNode) let omniLightNode = SCNNode() omniLightNode.light = SCNLight() omniLightNode.light!.type = SCNLight.LightType.omni omniLightNode.light!.color = UIColor(white: 0.99, alpha: 1.0) omniLightNode.position = SCNVector3Make(0, 0, 50) scene.rootNode.addChildNode(omniLightNode) sphereNode.rotation = SCNVector4(x: 0.0, y: 1.0, z: 0.0, w: 0.0) sphereNode.runAction(SCNAction.rotate(by: 1.1*CGFloat(Double.pi), around: SCNVector3(x: 0.0, y: 1.0, z: 0.0), duration: 0.0)) completion() }
After reading through conversions between Euler angles and unit quaternions, I was able to write a function that converted my desired Euler xyz angles to a quaternion. This way, the snapshot function captures the rotation. Below is my method written in Swift to perform the conversion.
Implementation
Code Block swift func angleConversion(x: Float, y: Float, z: Float, w: Float) -> (Float, Float, Float, Float) { let c1 = cos( x / 2 ) let c2 = cos( y / 2 ) let c3 = cos( z / 2 ) let s1 = sin( x / 2 ) let s2 = sin( y / 2 ) let s3 = sin( z / 2 ) let xF = s1 * c2 * c3 + c1 * s2 * s3 let yF = c1 * s2 * c3 - s1 * c2 * s3 let zF = c1 * c2 * s3 + s1 * s2 * c3 let wF = c1 * c2 * c3 - s1 * s2 * s3 return (xF, yF, zF, wF) }
Implementation
Code Block swift let (x, y, z, w) = angleConversion(x: 0, y: 1.1*Float(Double.pi), z: 0, w: 0) sphereNode.localRotate(by: SCNQuaternion(x, y, z, w))