| 50 | } |
| 51 | |
| 52 | float Ragdoll::InitBone(RigidBody* rigidBody, int32& nodeIndex, Transform& localOffset) |
| 53 | { |
| 54 | // Bones with 0 weight are non-simulated (kinematic) |
| 55 | float weight = BonesWeight; |
| 56 | BonesWeights.TryGet(rigidBody->GetName(), weight); |
| 57 | rigidBody->SetIsKinematic(weight < ANIM_GRAPH_BLEND_THRESHOLD); |
| 58 | nodeIndex = _animatedModel->SkinnedModel->FindNode(rigidBody->GetName()); |
| 59 | if (nodeIndex != -1 && !_bonesOffsets.TryGet(rigidBody, localOffset)) |
| 60 | { |
| 61 | // Calculate the skeleton node local position of the bone |
| 62 | auto& node = _animatedModel->GraphInstance.NodesPose[nodeIndex]; |
| 63 | Transform nodeT; |
| 64 | node.Decompose(nodeT); |
| 65 | localOffset = nodeT.WorldToLocal(rigidBody->GetLocalTransform()); |
| 66 | _bonesOffsets[rigidBody] = localOffset; |
| 67 | |
| 68 | // Initialize body |
| 69 | rigidBody->SetSolverIterationCounts(PositionSolverIterations, VelocitySolverIterations); |
| 70 | rigidBody->SetMaxDepenetrationVelocity(MaxDepenetrationVelocity); |
| 71 | |
| 72 | #if USE_EDITOR |
| 73 | for (auto child : rigidBody->Children) |
| 74 | { |
| 75 | auto joint = Cast<Joint>(child); |
| 76 | if (joint && joint->Target == nullptr && joint->IsActiveInHierarchy()) |
| 77 | { |
| 78 | LOG(Warning, "Ragdol joint '{0}' has missing target", joint->GetNamePath()); |
| 79 | } |
| 80 | } |
| 81 | #endif |
| 82 | } |
| 83 | return weight; |
| 84 | } |
| 85 | |
| 86 | void Ragdoll::OnFixedUpdate() |
| 87 | { |
nothing calls this directly
no test coverage detected