S.M_Emamian
S.M_Emamian

Reputation: 17393

How to rotate or scale 3D model scn file in AR kit

this class render my SCN file as well.

import UIKit
import ARKit

class SimpleViewController: UIViewController {

    @IBOutlet var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()        
        sceneView.scene = SCNScene(named: "duck.scn", inDirectory: "models.scnassets/furniture")!
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        sceneView.session.run(ARWorldTrackingConfiguration())
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        sceneView.session.pause()
    }
}

but I know how can I rotate or scale my object (duck.scn) file. I would like to user can do interaction with my object.

Upvotes: 2

Views: 3394

Answers (1)

PongBongoSaurus
PongBongoSaurus

Reputation: 7385

If you want to scale an SCNNode you can do something like this:

/// Scales An SCNNode
///
/// - Parameter gesture: UIPinchGestureRecognizer
@objc func scaleObject(gesture: UIPinchGestureRecognizer) {

    guard let nodeToScale = currentNode else { return }
    if gesture.state == .changed {

        let pinchScaleX: CGFloat = gesture.scale * CGFloat((nodeToScale.scale.x))
        let pinchScaleY: CGFloat = gesture.scale * CGFloat((nodeToScale.scale.y))
        let pinchScaleZ: CGFloat = gesture.scale * CGFloat((nodeToScale.scale.z))
        nodeToScale.scale = SCNVector3Make(Float(pinchScaleX), Float(pinchScaleY), Float(pinchScaleZ))
        gesture.scale = 1

    }
    if gesture.state == .ended { }

}

Whereby current node refers to an SCNNode.

If you want to move an SCNNode you can do something like this:

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    //1. Get The Current Touch Point
    guard let currentTouchPoint = touches.first?.location(in: self.augmentedRealityView),
        //2. Get The Next Feature Point Etc
        let hitTest = augmentedRealityView.hitTest(currentTouchPoint, types: .existingPlane).first else { return }

    //3. Convert To World Coordinates
    let worldTransform = hitTest.worldTransform

    //4. Set The New Position
    let newPosition = SCNVector3(worldTransform.columns.3.x, worldTransform.columns.3.y, worldTransform.columns.3.z)

    //5. Apply To The Node
    currentNode.simdPosition = float3(newPosition.x, newPosition.y, newPosition.z)

}

If you would like to rotate an SCNNode you first should create a variable(s) to store the original angle e.g:

//Store The Rotation Of The CurrentNode
var currentAngleY: Float = 0.0

Then you can do something like this:

/// Rotates An SCNNode Around It's YAxis
///
/// - Parameter gesture: UIRotationGestureRecognizer
@objc func rotateNode(_ gesture: UIRotationGestureRecognizer){

    //1. Get The Current Rotation From The Gesture
    let rotation = Float(gesture.rotation)

    //2. If The Gesture State Has Changed Set The Nodes EulerAngles.y
    if gesture.state == .changed{

        currentNode.eulerAngles.y = currentAngleY + rotation
    }

    //3. If The Gesture Has Ended Store The Last Angle Of The Cube
    if(gesture.state == .ended) {
        currentAngleY = currentNode.eulerAngles.y

    }
}

If you want to interact directly with your SCNScene (although I believe not in ARKit) you can use the following method:

var allowsCameraControl: Bool { get set }

Whereby:

If you set this property to true, SceneKit creates a camera node and handles mouse or touch events to allow the user to pan, zoom, and rotate their view of the scene. (Enabling user camera control does not modify camera objects already existing in the scene graph or the nodes containing them.)

An example would thus be:

 sceneView.scene = SCNScene(named: "duck.scn", inDirectory: "models.scnassets/furniture")!
 sceneView.allowsCameraControl = true;

Upvotes: 9

Related Questions