iosswiftuiscenekit3d-modelling

Default Position of a SCNCamera in an SCNScene


I think I don't fully understand how a SCNCamera is supposed to work.

So I've got the following code:

import SwiftUI
import SceneKit

struct ContentView: View {
    let scene = SCNScene(named: "Earth.usdz")
    var cameraNode: SCNNode? {
        let cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 2)
        return cameraNode
    }
    var body: some View {
        VStack {
            SceneView(
                scene: scene,
                pointOfView: cameraNode,
                options: [
                    .allowsCameraControl,
                    .autoenablesDefaultLighting
                ]
            )
            .frame(width: UIScreen.main.bounds.width , height: UIScreen.main.bounds.height/2)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

And removing or adding pointOfView: cameraNode results in:

Without

enter image description here

With

enter image description here

I'm assuming there is some default camera position (and maybe other properties?)? How do I see what those are? How do I un-invert the globe?

I'd like to more or less mimic what I get without setting the pointOfView and from there rotate the globe programmatically.

Thanks all!


Solution

  • If you create a camera class, turn off allowsCameraControl, and take out the PointOfView deal, then your lookAtConstraint points at the Earth node and you can play with the distance just by setting .position for either. Here is an example to get you focused on Earth - strafe just gives you an idea what you can do with a camera node. Rotating the Earth does not impact the camera node. You can do any rotation you want there and the camera will still point to the Earth.

    class Camera
    {
        var cameraEye = SCNNode()
        var cameraFocus = SCNNode()
            
        var centerX: Int = 100
        var strafeDelta: Float = 0.8
        var zoomLevel: Int = 35
        var zoomLevelMax: Int = 35              // Max number of zoom levels
        
        //********************************************************************
        init()
        {
            cameraEye.name = "Camera Eye"
            cameraFocus.name = "Camera Focus"
            
            cameraFocus.isHidden = true
            cameraFocus.position  =  SCNVector3(x: 0, y: 0, z: 0)
            
            cameraEye.camera = SCNCamera()
            cameraEye.constraints = []
            cameraEye.position = SCNVector3(x: 0, y: 15, z: 0.1)
            
            let vConstraint = SCNLookAtConstraint(target: cameraFocus)
            vConstraint.isGimbalLockEnabled = true
            cameraEye.constraints = [vConstraint]
        }
        //********************************************************************
        func reset()
        {
            centerX = 100
            cameraFocus.position  =  SCNVector3(x: 0, y: 0, z: 0)
            cameraEye.constraints = []
            cameraEye.position = SCNVector3(x: 0, y: 32, z: 0.1)
            cameraFocus.position = SCNVector3Make(0, 0, 0)
            
            let vConstraint = SCNLookAtConstraint(target: cameraFocus)
            vConstraint.isGimbalLockEnabled = true
            cameraEye.constraints = [vConstraint]
        }
        //********************************************************************
        func strafeRight()
        {
            if(centerX + 1 < 112)
            {
                centerX += 1
                cameraEye.position.x += strafeDelta
                cameraFocus.position.x += strafeDelta
            }
        }
        //********************************************************************
        func strafeLeft()
        {
            if(centerX - 1 > 90)
            {
                centerX -= 1
                cameraEye.position.x -= strafeDelta
                cameraFocus.position.x -= strafeDelta
            }
        }
        //********************************************************************
    }