[SWIFT] Use SCNIK Constraint to freely animate the robot's arm

There are several options for animating a 3D model with SceneKit, but if you want to animate the arms and legs of a 3D model at will, the options will be SCNIKConstraint or SCN Animation.

--SCNTransaction: Animate the entire scene all at once using the rotation and movement of nodes. --SCNAction: Animate individual nodes using node rotation and movement --SCNIKConstraint ・ ・ ・ Move like a puppet using connected bones --SCNAnimation ・ ・ ・ Executes preset animation

This article is detailed about the differences between them.

How to perform animation in SceneKit and how to use it properly

SCN Animation can be freely operated if it is defined in advance, but SCNIK Constraint is suitable when you want to interactively operate the speed and movement amount of animation.

So, I will explain how to animate the robot's arm freely with SCNIK Constraint.

What is SCNIKConstraint?

The IK of SCNIKConstraint is called Inverse kinematics.

I will quote this article because it was easy to understand. Inverse Kinematics Implementation Note

IK is an action that makes the connected thing go to a certain point so that the body moves in conjunction with the hand, wrist, arm, and shoulder like when a human reaches for a certain place. say.

SCNIKConstraint is a mechanism that allows you to apply this IK to SceneKit nodes.

reference: Apple Official: SCNIK Constraint

procedure

This time, we will create an animation in which the left arm of the robot moves according to the amount of drag.

** Prepare a 1.3D model **

The 3D model must have bone settings. This time we will use the existing model.

A 3D model of the robot (filename: robot.usdz) is included in Apple's ARKit sample project, so use this.

Capturing Body Motion in 3D

In this article, there was an example of making with a modeling tool.

[SceneKit] How to use SCNIK Constraint

** 2. Create a Game project from Xcode project creation **

** 3. Drag and drop the usdz file into your project **

See this article for how to load a 3D model in usdz format into SceneKit.

Load 3D model in usdz format into SceneKit and animate it

** 4. Detect when the screen is dragged **

Register UIPanGestureRecognizer with viewDidLoad.

GameViewController.swift


let tapGesture = UIPanGestureRecognizer(target: self, action: #selector(handleDrag(_:)))
scnView.addGestureRecognizer(tapGesture)

** 5. Determine the two joints that will be the starting point and the ending point **

While checking the bone information of the model with Xcode, determine the two joints that will be the starting point and the ending point (the part that actually moves). This time, I moved the left hand as the starting point and the left hand as the ending point.

image.png

If you don't choose the two joints properly, they will either not move or behave strangely.

For example, if I chose two points, the waist and the left hand, it would look like John Travolta of Saturday Night Fever.

** 6. Make the robot's arm move when dragged **

Obtains the amount of drag movement and determines the destination of the robot's arm based on it.

GameViewController.swift


@objc
func handleDrag(_ gestureRecognize: UIPanGestureRecognizer) {
    //Get the starting point of the animation (here, the shoulder of the left arm)
    guard let root = scene.rootNode.childNode(withName: "left_shoulder_1_joint", recursively: true) else { return }
    //Get the place to actually move (here, the left arm hand)
    guard let target = scene.rootNode.childNode(withName: "left_hand_joint", recursively: true) else { return }

    //Specify the starting point and the location to move to SCNIKConstraint
    let ik:SCNIKConstraint = SCNIKConstraint.inverseKinematicsConstraint(chainRootNode: root)
    target.constraints = [ik]

    //Determine the amount of movement of the robot's arm from the amount of movement of the drag
    let move = gestureRecognize.translation(in: view)
    let targetPosition = SCNVector3(target.position.x + Float(move.x * 0.1), target.position.y + Float(move.y * 0.1 * -1), target.position.z)

    //Move the arm
    ik.targetPosition = targetPosition
}

finish

20201003qiita用.gif

We provide information on iOS application development. Please follow us on Twitter as well. https://twitter.com/jugemjugemjugem

Recommended Posts

Use SCNIK Constraint to freely animate the robot's arm
How to use the link_to method
How to use the include? method
How to use the form_with method
How to use the wrapper class
[Java] How to use the File class
[Java] How to use the hasNext function
[Java] How to use the HashMap class
[Rails] How to use the map method
Studying how to use the constructor (java)
[Processing × Java] How to use the loop
[Processing × Java] How to use the class
[Processing × Java] How to use the function
[Java] How to use the Calendar class
How to use the camera module OV7725 (ESP32-WROVER-B)
[Java] How to use Thread.sleep to pause the program
When you want to use the method outside
Output of how to use the slice method
How to use the replace () method (Java Silver)
[Ruby basics] How to use the slice method