SCNCamera limit arcball rotation

前端 未结 2 1538
天涯浪人
天涯浪人 2020-12-09 13:08

I have a scene setup with SCNCamera that rotates around an object.

What would be the best way to limit the extents of rotation the camera can achieve around the obj

2条回答
  •  生来不讨喜
    2020-12-09 13:42

    Maybe this could be useful for readers.

        class GameViewController: UIViewController {
    
        var cameraOrbit = SCNNode()
        let cameraNode = SCNNode()
        let camera = SCNCamera()
    
    
        //HANDLE PAN CAMERA
        var lastWidthRatio: Float = 0
        var lastHeightRatio: Float = 0.2
        var WidthRatio: Float = 0
        var HeightRatio: Float = 0.2
        var fingersNeededToPan = 1
        var maxWidthRatioRight: Float = 0.2
        var maxWidthRatioLeft: Float = -0.2
        var maxHeightRatioXDown: Float = 0.02
        var maxHeightRatioXUp: Float = 0.4
    
        //HANDLE PINCH CAMERA
        var pinchAttenuation = 20.0  //1.0: very fast ---- 100.0 very slow
        var lastFingersNumber = 0
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // create a new scene
            let scene = SCNScene(named: "art.scnassets/ship.scn")!
    
            // create and add a light to the scene
            let lightNode = SCNNode()
            lightNode.light = SCNLight()
            lightNode.light!.type = SCNLightTypeOmni
            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 = SCNLightTypeAmbient
            ambientLightNode.light!.color = UIColor.darkGrayColor()
            scene.rootNode.addChildNode(ambientLightNode)
    
        //Create a camera like Rickster said
            camera.usesOrthographicProjection = true
            camera.orthographicScale = 9
            camera.zNear = 1
            camera.zFar = 100
    
            cameraNode.position = SCNVector3(x: 0, y: 0, z: 50)
            cameraNode.camera = camera
            cameraOrbit = SCNNode()
            cameraOrbit.addChildNode(cameraNode)
            scene.rootNode.addChildNode(cameraOrbit)
    
            //initial camera setup
            self.cameraOrbit.eulerAngles.y = Float(-2 * M_PI) * lastWidthRatio
            self.cameraOrbit.eulerAngles.x = Float(-M_PI) * lastHeightRatio
    
            // retrieve the SCNView
            let scnView = self.view as! SCNView
    
            // set the scene to the view
            scnView.scene = scene
    
            //allows the user to manipulate the camera
            scnView.allowsCameraControl = false  //not needed
    
            // add a tap gesture recognizer
            let panGesture = UIPanGestureRecognizer(target: self, action: "handlePan:")
            scnView.addGestureRecognizer(panGesture)
    
            // add a pinch gesture recognizer
            let pinchGesture = UIPinchGestureRecognizer(target: self, action: "handlePinch:")
            scnView.addGestureRecognizer(pinchGesture)
        }
    
        func handlePan(gestureRecognize: UIPanGestureRecognizer) {
    
            let numberOfTouches = gestureRecognize.numberOfTouches()
    
            let translation = gestureRecognize.translationInView(gestureRecognize.view!)
    
            if (numberOfTouches==fingersNeededToPan) {
    
               widthRatio = Float(translation.x) / Float(gestureRecognize.view!.frame.size.width) + lastWidthRatio
               heightRatio = Float(translation.y) / Float(gestureRecognize.view!.frame.size.height) + lastHeightRatio
    
                //  HEIGHT constraints
                if (heightRatio >= maxHeightRatioXUp ) {
                    heightRatio = maxHeightRatioXUp
                }
                if (heightRatio <= maxHeightRatioXDown ) {
                    heightRatio = maxHeightRatioXDown
                }
    
    
                //  WIDTH constraints
                if(widthRatio >= maxWidthRatioRight) {
                    widthRatio = maxWidthRatioRight
                }
                if(widthRatio <= maxWidthRatioLeft) {
                    widthRatio = maxWidthRatioLeft
                }
    
                self.cameraOrbit.eulerAngles.y = Float(-2 * M_PI) * widthRatio
                self.cameraOrbit.eulerAngles.x = Float(-M_PI) * heightRatio
    
                print("Height: \(round(heightRatio*100))")
                print("Width: \(round(widthRatio*100))")
    
    
                //for final check on fingers number
                lastFingersNumber = fingersNeededToPan
            }
    
            lastFingersNumber = (numberOfTouches>0 ? numberOfTouches : lastFingersNumber)
    
            if (gestureRecognize.state == .Ended && lastFingersNumber==fingersNeededToPan) {
                lastWidthRatio = widthRatio
                lastHeightRatio = heightRatio
                print("Pan with \(lastFingersNumber) finger\(lastFingersNumber>1 ? "s" : "")")
            }
        }
    
        func handlePinch(gestureRecognize: UIPinchGestureRecognizer) {
            let pinchVelocity = Double.init(gestureRecognize.velocity)
            //print("PinchVelocity \(pinchVelocity)")
    
            camera.orthographicScale -= (pinchVelocity/pinchAttenuation)
    
            if camera.orthographicScale <= 0.5 {
                camera.orthographicScale = 0.5
            }
    
            if camera.orthographicScale >= 10.0 {
                camera.orthographicScale = 10.0
            }
    
        }
    

提交回复
热议问题