CRM MO
CRM MO

Reputation: 57

How to scale and move all nodes at once? ARKit Swift

I got these functions that scale and move the 3D object displayed on the screen when tapping on it. The problem consists that if I move or scale the node (3D object) it will only make bigger or smaller one part of the node and I want to scale everything.

I know one solution is to join the 3D object in Blender as one but, later on, I want to add specific animation to specific nodes and that's why I don't want to join them.

Here are the code that I'm using for scaling and moving the objects:

@objc func panned(recognizer :UIPanGestureRecognizer)
{
    //This function is for scaling
    if recognizer.state == .changed
    {
        guard let sceneView = recognizer.view as? ARSCNView
    else
    {
        return
    }

    let touch = recognizer.location(in: sceneView)
    let translation = recognizer.translation(in: sceneView)

    let hitTestResults = self.sceneView.hitTest(touch, options: nil)

        if let hitTest = hitTestResults.first
        {
            let planeNode = hitTest.node

            self.newAngleY = Float(translation.x) * (Float) (Double.pi)/180
            self.newAngleY += self.currentAngleY
            planeNode.eulerAngles.y = self.newAngleY
        }
        else if recognizer.state == .ended
        {
            self.currentAngleY = self.newAngleY
        } 
    }

}

And this one:

@objc func pinched(recognizer :UIPinchGestureRecognizer)
{
    if recognizer.state == .changed
    {
        guard let sceneView = recognizer.view as? ARSCNView
            else
            {
                return
            }
    }

    let touch = recognizer.location(in: sceneView)

    let hitTestResults = self.sceneView.hitTest(touch, options: nil)

    if let hitTest = hitTestResults.first
    {

        let planeNode = hitTest.node

        let pinchScaleX = Float(recognizer.scale) * planeNode.scale.x
        let pinchScaleY = Float(recognizer.scale) * planeNode.scale.y
        let pinchScaleZ = Float(recognizer.scale) * planeNode.scale.z

        planeNode.scale = SCNVector3(pinchScaleX, pinchScaleY, pinchScaleZ)

        recognizer.scale = 1 
    }
}

I don't know if this helps, but here is an image of the nodes: Image of the nodes

Thanks in advance!

Upvotes: 2

Views: 1027

Answers (1)

Hermes
Hermes

Reputation: 2898

In order to achieve the "grouping" you are looking for you have to create an empty scene node that will be the root to all other nodes.

let myRootNode : SCNNode = SCNNode()
sceneView.scene.rootNode.addChildNode(myRootNode)

Next append all new nodes in the scene to myRootNode so all your models are parented to the same node.

let newChildNode : SCNNode = SCNNode()
myRootNode.addChildNode(newChildNode)

Then you can apply translations to the myRootNode to move it along with all child nodes. Also the child nodes remain separate models that can be moved (translated/rotated) individually or as a single group.

Within your hit test you should be scaling and rotating the myRootNode instead of the individual model.

Upvotes: 1

Related Questions