如何在使用SCNIKConstraint时根据目标位置更改来设置SCNNode的方向变换?

huangapple go评论58阅读模式
英文:

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

问题

我正在使用SceneKit创建一个人体骨骼的3D动画。这里是解释我的节点关系的图表:

如何在使用SCNIKConstraint时根据目标位置更改来设置SCNNode的方向变换?

我将脊柱节点设置为其上所有节点的根节点。我正在使用从设备摄像头捕获的运动捕捉数据创建手臂的动画。目前,我将颈部节点设置为创建SCNIKConstraint以移动手部节点位置的根链节点。我的代码基本如下所示:

// 创建手臂的节点
var spineNode: SCNNode!
var neckNode: SCNNode!
var shoulderNode: SCNNode!
var elbowNode: SCNNode!
var handNode: SCNNode!

// 设置初始位置
spineNode.position = setSpinePosition()
neckNode.position = setNeckPosition()
// 对其他节点依此类推...

// 设置手部节点的约束
let handIkConstraint: SCNIKConstraint = .inverseKinematicsConstraint(chainRootNode: neckNode)
handNode.constraints = [handIkConstraint]

对于位置变化,因为我使用了从视频中获取的运动捕捉数据,我根据新数据设置位置,就像这样:

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

它基本上运行正常,手部节点按预期移动,其父节点也是如此。但是肩部节点的移动不如预期。它根据手的运动/位置变化而旋转,但保持在原地。效果如下(黑色框是肩部节点,如您所见,它保持在原地,但根据手节点/蓝色框的位置旋转):

如何在使用SCNIKConstraint时根据目标位置更改来设置SCNNode的方向变换?

但我想实现类似于这样的效果(肩部节点/黑色框根据SCNIKConstraint的目标位置变化而移动):

如何在使用SCNIKConstraint时根据目标位置更改来设置SCNNode的方向变换?

现在,为了移动肩部节点,我只是像对脊柱节点一样在新数据上设置位置。但为了以防数据不准确,我希望可以根据IK约束的目标位置自动移动它。我想知道是否有实现这一目标的方法?如果需要更多信息,请告诉我,谢谢。

英文:

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

如何在使用SCNIKConstraint时根据目标位置更改来设置SCNNode的方向变换?

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):

如何在使用SCNIKConstraint时根据目标位置更改来设置SCNNode的方向变换?

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):

如何在使用SCNIKConstraint时根据目标位置更改来设置SCNNode的方向变换?

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.

答案1

得分: 1

Skeleton and its IK system

我认为在你的情况下,最好的解决方案是使用 SCNSkinner。使用 skinner 对象,你可以初始化角色的骨架,并在绑定的皮肤中实现不仅父子依赖关系,还包括如 骨骼权重 这样重要的参数。

请查看 Rigging a Model for Motion Capture 文章,了解有关角色绑定的更多信息。

在SceneKit中缺少的必要IK工具

然而,在SceneKit中,所有上述操作都是非常繁琐的。最高效的方法是在Autodesk Maya中使用IK/FK来动画化角色,然后以 .dae.usdz 格式导出具有 烘焙动画 的角色。Maya应用程序具有丰富的动画工具和可动画化属性,用于微调逆向运动学,包括 IK解算器(单链、旋转平面、样条、人体IK、多链等),效果器固定、IK/FK切换和混合、极点矢量约束、MEL和Python脚本编写。所有这些功能在SceneKit中都无法使用。

英文:

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.

huangapple
  • 本文由 发表于 2023年5月29日 20:58:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76357592.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定