在ARKit 3中从3D骨架获取骨骼旋转

时间:2019-09-23 06:00:50

标签: swift arkit ios13 realitykit

我试图让骨骼旋转与他们的父母有关,但最终我得到了怪异的角度。

我已经尝试了一切,矩阵乘法,偏移量,轴交换,没有运气。

guard let bodyAnchor = anchor as? ARBodyAnchor else { continue }

let skeleton = bodyAnchor.skeleton
let jointTransforms = skeleton.jointLocalTransforms

for (i, jointTransform) in jointTransforms.enumerated() {

    //RETRIEVE ANGLES HERE
}

//RETRIEVE ANGLES HERE中,我尝试了不同的方法:

let n = SCNNode()
n.transform = SCNMatrix4(jointTransform)
print(n.eulerAngles)

在这次尝试中,我将 jointTransformation 设置为SCNNode.transform,以便可以检索 eulerAngles 以使其易于阅读,并尝试了解正在发生的事情。

我开始工作一些关节,但是我认为这纯粹是巧合或运气,因为其余的骨头旋转得很奇怪。

在其他尝试中,我使用 jointModelTransforms (模型,而不是Local)来获取它们,因此所有变换都相对于骨架的根骨骼。

使用这种方法,我可以像这样进行矩阵乘法:

LocalMatrix = Inverse(JointModelMatrix) * (ParentJointModelMatrix)

要获得相对于其父对象的旋转,但在相同情况下,一些骨骼可以旋转,而其他骨骼则怪异地旋转。我敢打赌,纯属巧合。

为什么要使骨骼旋转?

我正在尝试使用手机构建MoCap应用程序,并将旋转传递给Blender,并尝试从中构建.BVH文件,以便可以在Blender上使用它们。

这是我自己的装备:

我以前使用Kinect做到了这一点,但我已经尝试了好几天在ARKit 3上做到这一点,但没有运气:(

2 个答案:

答案 0 :(得分:0)

只是一个猜测……这能起到作用吗?

  let skeleton = bodyAnchor.skeleton
  let jointTransforms = skeleton.jointLocalTransforms

  for (i, jointTransform) in jointTransforms.enumerated() {
    print(Transform(matrix: jointTransform).rotation)
  }

答案 1 :(得分:0)

使用simd_quatf(from:to:)和正确的输入即可。在开始对向量进行归一化之前,我一直在处理怪异的角度:

guard let bodyAnchor = anchor as? ARBodyAnchor else { continue }

let skeleton = bodyAnchor.skeleton
let jointTransforms = skeleton.jointLocalTransforms

for (i, jointTransform) in jointTransforms.enumerated() {
    // First i filter out the root (Hip) joint because it doesn't have a parent
    let parentIndex = skeleton.definition.parentIndices[i]
    guard parentIndex >= 0 else { continue } // root joint has parent index of -1

    //RETRIEVE ANGLES HERE
    let jointVectorFromParent = simd_make_float3(jointTransform.columns.3)
    let referenceVector: SIMD3<Float>
    if skeleton.definition.parentIndices[parentIndex] >= 0 {
         referenceVector = simd_make_float3(jointTransforms[parentIndex].columns.3)
    } else {
         // The parent joint is the Hip joint which should have
         // a vector of 0 going to itself
         // It's impossible to calculate an angle from a vector of length 0,
         // So we're using a vector that's just pointing up
         referenceVector = SIMD3<Float>(x: 0, y: 1, z: 0)
    }
    // Normalizing is important because simd_quatf gives weird results otherwise
    let jointNormalized = normalize(jointVectorFromParent)
    let referenceNormalized = normalize(referenceVector)
    let orientation = simd_quatf(from: referenceNormalized, to: jointNormalized)
    print("angle of joint \(i) = \(orientation.angle)")
}

但要记住的一件事: ARKit3仅跟踪某些关节(AFAIK在ARSkeleton.JointName中命名为关节)。其他关节是从使用标准骨架的关节中推断出来的。这意味着,例如,您为肘部获得的角度将不是被跟踪的人肘部在那里的确切角度。