| 84 | } |
| 85 | |
| 86 | void Ragdoll::OnFixedUpdate() |
| 87 | { |
| 88 | if (!_animatedModel || !_animatedModel->SkinnedModel) |
| 89 | return; |
| 90 | PROFILE_CPU(); |
| 91 | |
| 92 | // Synchronize non-simulated bones |
| 93 | for (auto child : Children) |
| 94 | { |
| 95 | auto rigidBody = Cast<RigidBody>(child); |
| 96 | if (!rigidBody || !rigidBody->IsActiveInHierarchy()) |
| 97 | continue; |
| 98 | Transform localOffset; |
| 99 | int32 nodeIndex; |
| 100 | const float weight = InitBone(rigidBody, nodeIndex, localOffset); |
| 101 | if (nodeIndex != -1 && weight < ANIM_GRAPH_BLEND_THRESHOLD) |
| 102 | { |
| 103 | // Bone is animation driven |
| 104 | auto& node = _animatedModel->GraphInstance.NodesPose[nodeIndex]; |
| 105 | Transform nodeT; |
| 106 | node.Decompose(nodeT); |
| 107 | rigidBody->SetLocalTransform(nodeT.LocalToWorld(localOffset)); |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | // Synchronize simulated bones with skeleton if Anim Graph is disabled |
| 112 | if (!_animatedModel->AnimationGraph || _animatedModel->UpdateMode == AnimatedModel::AnimationUpdateMode::Never) |
| 113 | { |
| 114 | // Get current pose |
| 115 | Array<Matrix> currentPose; |
| 116 | _animatedModel->GetCurrentPose(currentPose); |
| 117 | |
| 118 | // Convert pose into local-bone pose |
| 119 | auto& skeleton = _animatedModel->SkinnedModel->Skeleton; |
| 120 | AnimGraphImpulse localPose; |
| 121 | localPose.Nodes.Resize(skeleton.Nodes.Count()); |
| 122 | for (int32 nodeIndex = 0; nodeIndex < skeleton.Nodes.Count(); nodeIndex++) |
| 123 | { |
| 124 | Transform t; |
| 125 | currentPose[nodeIndex].Decompose(t); |
| 126 | const int32 parentIndex = skeleton.Nodes[nodeIndex].ParentIndex; |
| 127 | if (parentIndex != -1) |
| 128 | { |
| 129 | Transform parent; |
| 130 | currentPose[parentIndex].Decompose(parent); |
| 131 | t = parent.WorldToLocal(t); |
| 132 | } |
| 133 | localPose.Nodes[nodeIndex] = t; |
| 134 | } |
| 135 | |
| 136 | // Override simulated bones in local pose |
| 137 | OnAnimationUpdating(&localPose); |
| 138 | |
| 139 | // Convert into skeleton pose |
| 140 | for (int32 nodeIndex = 0; nodeIndex < skeleton.Nodes.Count(); nodeIndex++) |
| 141 | { |
| 142 | const int32 parentIndex = skeleton.Nodes[nodeIndex].ParentIndex; |
| 143 | if (parentIndex != -1) |
no test coverage detected