Thanks for your response!
The other day, I tried to chain together the translations from each joint transform and noticed using multiple different rigs that the translation sum for a peripheral joint like the wrist still comes out to some number very close to zero.
I will try using matrix multiplication as it is demonstrated in pinEntity and see if I have more success with that. I can write something up for Feedback Assistant as well, as it would be cool to have work out of the box.
I have another question about jointTransforms and AnimationResources if you're up for it:
I am trying to play two separate pose-based joint animations at once and was hoping to restrict each animation to only the joint names and transforms I want animated (in the constructor of FromToByAnimation and then using its fromValue and toValue properties).
Long story short, I notice that when excluding upper body joints from an animation, they still seem to experience scale and rotation animations for the first keyframe or so.
It almost seems like the first joint in the chain that is excluded from the animation experiences a zeroed out Transform and before returning to its base resting transform. Here is a code sample for retrieving joint transforms from a map of joints and orientations:
func transformsForPose(_ pose: Pose, exclude excludedBones: [Bone]) -> [(String, Transform)] {
var updatedTransforms = restPose // initial model.jointTransforms
let excludedBoneNames = excludedBones.map({ $0.rawValue })
for bone in pose.keys {
guard let boneIndex = getBoneIndex(bone), let boneRotation = pose[bone] else {
continue
}
updatedTransforms[boneIndex].rotation = boneRotation
}
return updatedTransforms.indices.compactMap({
let name = model.jointNames[$0]
let transform = updatedTransforms[$0]
let suffix = name.getSuffix(separator: "/").lowercased()
if excludedBoneNames.contains(suffix) {
return nil
} else {
return (name, transform)
}
})
}
And then creating an animation from those joint names and transforms:
static func animationForPoseIndex(_ index: Int,
poses: [Pose], exclude: [Bone],
durations: [TimeInterval],
for characterEntity: CharacterEntity,
named name: String) -> AnimationResource? {
let pose = poses[index]
let fromTransforms = characterEntity.transformsForPose(index > 0 ? poses[index-1] : poses[poses.count-1], exclude: exclude)
let duration = durations[index]
var animation = FromToByAnimation(jointNames: fromTransforms.map({ $0.0 }))
animation.name = name + index.description
animation.fromValue = JointTransforms(fromTransforms.map( {$0.1} ))
let toTransforms = characterEntity.transformsForPose(pose, exclude: exclude)
animation.toValue = JointTransforms(toTransforms.map( {$0.1} ))
animation.bindTarget = .jointTransforms
animation.blendLayer = 100
animation.duration = duration
animation.isRotationAnimated = true
animation.fillMode = .forwards
return try? AnimationResource.generate(with: animation)
}
When I don't exclude any joints (i.e include every joint name and transform) and use a rest pose to fill in the remaining transforms for the joints that won't be active, I don't see the issue. I am wondering if I am missing something obvious or if there is a bug here?