简体   繁体   中英

How to set the orientation transformation of a SCNNode based on the target position change when using SCNIKConstraint?

I'm creating a human skeleton 3D animation using SceneKit . Here is the diagram explaining my node relationship:

节点关系

I set the Spine node as the root node of all the nodes above it. I'm creating an animation for the movement of the arms using data retrieved from motion capture using the device's camera. For now, I set the Neck as the root chain node for creating an SCNIKConstraint to move the position of the hand node. My code looks pretty much like this:

// The nodes to create an arm
var spineNode: SCNNode!
var neckNode: SCNNode!
var shoulderNode: SCNNode!
var elbowNode: SCNNode!
var handNode: SCNNode!

// Setting the initial positions
spineNode.position = setSpinePosition()
neckNode.position = setNeckPosition()
// and so on for the other nodes...

// Setting the constraint to the hand node
let handIkConstraint: SCNIKConstraint = .inverseKinematicsConstraint(chainRootNode: neckNode)
handNode.constraints = [handIkConstraint]

And for position change, since I'm using data retrieved from motion capture from a video, I set the position based on a new data like this:

func changeFrame(data: HumanKeypointData) {
    spineNode.position = getNewPosition(data.spinePosition)
    handIkConstraint.targetPosition = data.handPosition
}

It works mostly fine, the Hand node moves as expected and so does it's parent. But the shoulder node doesn't move as expected. It rotates based on the hand movement/position change, but it stays in its place. It looks like this (the black boxes are the shoulder nodes, as you can see it's fixed in its place while it rotates based on the hand node/blue box):

肩节点不动

But I want to achieve something like this (the shoulder nodes/black box moves based on the target position change of the hand nodes using the SCNIKConstraint ):

肩膀动了

Now to also move the shoulder nodes I just set the position on the new data as I did with the spine node. But just in case the data is not accurate, I want to make it automatically moves based on the IK constraint target position. I'm wondering if is there any way to achieve this? If you need more information please let me know, thank you.

Skeleton and its IK system

I think that the best solution in your case would be to use SCNSkinner . Using the skinner object, you can initialize the character's skeleton with inverse transform, and implement in the bound skin not only the Parent-Child dependency, but also such an important parameter as bone weight .

See Rigging a Model for Motion Capture article for more information on character rigging.

Necessary IK tools, missing in SceneKit

However, all of the aforementioned is a very laborious process in SceneKit. The most efficient way is to animate a character using IK/FK in Autodesk Maya, and then export that character with the baked animation in .dae or .usdz format. Maya app has a full arsenal of animation tools and animatable properties for fine-tuning Inverse Kinematics, including IK solvers (Single Chain, Rotate Plane, Spline, Human IK, Multi-chain, etc), effector pinning, IK/FK switching and blending, Pole Vector constraints, MEL and Python scripting. All those features are simply unavailable in SceneKit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM