iosswiftuigesturerecognizerscenekituipinchgesturerecognizer

SceneKit camera node resets on pinch gesture


I am trying to achieve a zoom on a pinch gesture however every time I pinch a second time, the model resets itself.

func zoom(scale: Double){

    self.cameraNode.camera!.xFov = scale
    self.cameraNode.camera!.yFov = scale

}

func handlePinch(gestureRecognize: UIPinchGestureRecognizer) {

    if gestureRecognize.numberOfTouches() == 2 {

                let zoom = gestureRecognize.scale
                if (gestureRecognize.state == UIGestureRecognizerState.Began){
                    startScale = lastScale
                    bimScene.zoom(startScale)
                }
                if (gestureRecognize.state == UIGestureRecognizerState.Changed){
                    startScale = Double(100/zoom)
                    bimScene.zoom(startScale)
                }
                if (gestureRecognize.state == UIGestureRecognizerState.Ended){
                    lastScale = startScale
                }

    }
}

I am still new to scenekit, so i find this strange. Can somebody explain the reason for this?


Solution

  • You're close, the logic is a little off.

    The began case is fine, you need to 'remember' the scale at which the pinch was started and this is likely the scale that was set last time you zoomed.

    Your changed case has two issues.

    The ended case just needs to set the scale value so we can remember what to start with next pinch. In this case it may be a bit redundant and you may get away with startScale = startScale * zoom and simply have nothing in the began case.

    Haven't tested the below, but hopefully it gives you some ideas. The value you pass into the zoom func is actually a field of view angle, so I've renamed this to differentiate it from the various scales. FOV will be between 30-60deg or so, whereas the scales are more like to be in the range 0.1 - 10 (very roughly).

    func handlePinch(gestureRecognize: UIPinchGestureRecognizer) {
    
        if gestureRecognize.numberOfTouches() == 2 {
    
            let zoom = gestureRecognize.scale
            if (gestureRecognize.state == UIGestureRecognizerState.Began){
                startScale = lastScale
            } else if (gestureRecognize.state == UIGestureRecognizerState.Changed){
                let fov = Double(100/(startScale * zoom))
                bimScene.zoom(fov)
            } else {
                lastScale = startScale * zoom
            }
        }
    }