SceneKit: Camera movement based on CoreMotion

776 Views Asked by At

I'm attempting to emulate ARKit but using the device's front camera instead of the back one (and not restricted to iPhone X). So far I've managed to set up a simple scene with just a 3D model loaded in front of a SCNCamera and thanks to the snippet provided by Travis in this answer managed to orientate the SCNCamera according to the attitude of the device.

However, I still need translate the camera based on the device's movement so that I can visualize the object from different angles and "zoom" to it; and I can't figure out which data should I use. Is it the userAcceleration from the CMDeviceMotion object? I've noticed by logging that even if I keep the device relatively quiet I get some non-zero values for the components of the acceleration. Any hint or lead on how to approach this is truly appreciated.

Here's the basic code I've got so far:

class ViewController: UIViewController {
    @IBOutlet weak var sceneView: SCNView!
    private let cameraNode = SCNNode()
    private var ringNode: SCNNode!
    private let motionManager = CMMotionManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        setupScene()
        setupMotionManager()
    }

    private func setupScene() {
        let objScene = SCNScene(named: "art.scnassets/ring.obj")!
        ringNode = objScene.rootNode.childNode(withName: "ring", recursively: true)
        ringNode.applyUniformScale(0.003)
        ringNode.position = SCNVector3(x: 0, y: 0, z: -5)

        let scene = SCNScene()
        scene.rootNode.addChildNode(ringNode)

        // create and add a camera to the scene
        cameraNode.camera = SCNCamera()
        scene.rootNode.addChildNode(cameraNode)

        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 0)

        // create and add a light to the scene
        let lightNode = SCNNode()
        lightNode.light = SCNLight()
        lightNode.light!.type = .omni
        lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
        scene.rootNode.addChildNode(lightNode)

        // create and add an ambient light to the scene
        let ambientLightNode = SCNNode()
        ambientLightNode.light = SCNLight()
        ambientLightNode.light!.type = .ambient
        ambientLightNode.light!.color = UIColor.darkGray
        scene.rootNode.addChildNode(ambientLightNode)          
        sceneView.scene = scene
    }

    private func setupMotionManager() {
        if motionManager.isDeviceMotionAvailable {
            motionManager.deviceMotionUpdateInterval = 1.0 / 60.0
            motionManager.startDeviceMotionUpdates(to: OperationQueue(), withHandler: { (motion, error) in
                if let motion = motion {
                    self.cameraNode.orientation = motion.gaze(atOrientation: .portrait)
                    let acc = motion.userAcceleration
                    print("Acc: \(accDescription(acc))")
                }
            })
        }
    }
0

There are 0 best solutions below