Ashman Malik
Ashman Malik

Reputation: 267

Smooth Pinch Gesture for SceneKit IOS

I am working on the Pinch Gesture for a 3D Model in Arkit, I am having an issue, When i scale the Model it lags and doesn't give me the smooth response. It's working fine but i need to make it smoother.

 @objc func scalePiece(gestureRecognizer : UIPinchGestureRecognizer) {   guard gestureRecognizer.view != nil else { return }

        if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {

            let scale = Float(gestureRecognizer.scale)

            let newscalex = scale / currentscalex
            let newscaley = scale / currentscaley
            let newscalez = scale / currentscalez

            self.drone.scale = SCNVector3(newscalex, newscaley, newscalez)

        }}

Any tips would be appreciated.

Upvotes: 0

Views: 1315

Answers (2)

Xartec
Xartec

Reputation: 2415

Replace the / by * both for all three axis and reset the scale of gesture recognizer. In other words multiply with the scale instead of dividing the scale.

To prevent it from scaling exponentially, reset the gestureRecognizer.scale after you read it, to 1.0. For example:

  if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {
            let scale = Float(gestureRecognizer.scale)

            let newscalex = scale * self.drone.scale.x
            let newscaley = scale * self.drone.scale.y
            let newscalez = scale * self.drone.scale.z

            self.drone.scale = SCNVector3(newscalex, newscaley, newscalez)
            gestureRecognizer.scale = 1.0
   }

Resetting the gestureRecognizer is basically an alternative approach to storing the original scale in state began and applying the scale factor from the recognizer to that one before assigning it to the current. This situation is described specifically in the docs: https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/handling_uikit_gestures/handling_pinch_gestures in the Important note.

Upvotes: 1

Alok Subedi
Alok Subedi

Reputation: 1611

You may have some logic behind currentscale and calculated newscale, but simply gestureRecognizer.scale gives smooth scaling. I think you get jerky scaling because you set scale directly. Use SCNAction.scale

let action = SCNAction.scale(by: gestureRecognizer.scale, duration: 0.1)
lv.runAction(action)
gestureRecognizer.scale = 1

instead of

self.drone.scale = SCNVector3(newscalex, newscaley, newscalez)

And if you have different scale value for x,y,z then use customAction

let action = SCNAction.customAction(duration: 0.1) { (yourNode, elapsedTime) in
    let percentage = elapsedTime / 0.1
    let newscalex = scale / currentscalex * percentage
    let newscaley = scale / currentscaley * percentage
    let newscalez = scale / currentscalez * percentage
    yourNode.scale = SCNVector3(newscalex, newscaley, newscalez)
}

Upvotes: 3

Related Questions