/// <summary> /// Update this animation controller. /// </summary> /// <param name="animationUpdateData">See commentary in MyAnimationUpdateData</param> public void Update(ref MyAnimationUpdateData animationUpdateData) { if (animationUpdateData.CharacterBones == null) { return; // safety } if (animationUpdateData.Controller == null) { animationUpdateData.Controller = this; } ResultBonesPool.FreeAll(); // free all previous bone allocations, return them to pool // (this is a safe place to do that, nobody should use them by this time) // Set the first layer. if (m_layers.Count > 0) { m_layers[0].Update(ref animationUpdateData); } // Other layers can replace some transforms or add them for (int i = 1; i < m_layers.Count; i++) { var currentLayer = m_layers[i]; MyAnimationUpdateData animationUpdateDataLast = animationUpdateData; animationUpdateData.LayerBoneMask = null; animationUpdateData.BonesResult = null; m_layers[i].Update(ref animationUpdateData); if (animationUpdateData.BonesResult == null) { animationUpdateData = animationUpdateDataLast; // restore backup continue; } int boneCount = animationUpdateData.BonesResult.Count; var bonesLast = animationUpdateDataLast.BonesResult; var bones = animationUpdateData.BonesResult; var bonesBindPose = animationUpdateDataLast.CharacterBones; if (currentLayer.Mode == MyAnimationStateMachine.MyBlendingMode.Replace) { for (int j = 0; j < boneCount; j++) { if (animationUpdateData.LayerBoneMask[j] == false) { bones[j].Translation = bonesLast[j].Translation; bones[j].Rotation = bonesLast[j].Rotation; } } } else if (currentLayer.Mode == MyAnimationStateMachine.MyBlendingMode.Add) { for (int j = 0; j < boneCount; j++) { if (animationUpdateData.LayerBoneMask[j]) { // add result to current Vector3 addTranslation; Quaternion addRotation; bonesBindPose[j].GetCompleteTransform(ref bones[j].Translation, ref bones[j].Rotation, out addTranslation, out addRotation); bones[j].Translation = bonesLast[j].Translation + addTranslation; bones[j].Rotation = bonesLast[j].Rotation * addRotation; // TODO: Check this math :) } else { // unaffected, copy last result (deep copy because we allocate from pool and bone is currenlty class) bones[j].Translation = bonesLast[j].Translation; bones[j].Rotation = bonesLast[j].Rotation; } } } ResultBonesPool.Free(animationUpdateDataLast.BonesResult); } }
/// <summary> /// Update this animation controller. /// </summary> /// <param name="animationUpdateData">See commentary in MyAnimationUpdateData</param> public void Update(ref MyAnimationUpdateData animationUpdateData) { FrameCounter++; if (animationUpdateData.CharacterBones == null || !ResultBonesPool.IsValid()) { return; // safety } if (animationUpdateData.Controller == null) { animationUpdateData.Controller = this; } ResultBonesPool.FreeAll(); // free all previous bone allocations, return them to pool // (this is a safe place to do that, nobody should use them by this time) Variables.SetValue(MyAnimationVariableStorageHints.StrIdRandomStable, MyRandom.Instance.NextFloat()); // Set the first layer. if (m_layers.Count > 0) { ResultBonesPool.SetDefaultPose(null); m_layers[0].Update(ref animationUpdateData); } // Other layers can replace some transforms or add them for (int i = 1; i < m_layers.Count; i++) { var currentLayer = m_layers[i]; MyAnimationUpdateData animationUpdateDataLast = animationUpdateData; animationUpdateData.LayerBoneMask = null; animationUpdateData.BonesResult = null; ResultBonesPool.SetDefaultPose(currentLayer.Mode == MyAnimationStateMachine.MyBlendingMode.Replace ? animationUpdateDataLast.BonesResult : null); m_layers[i].Update(ref animationUpdateData); if (animationUpdateData.BonesResult == null || m_layers[i].CurrentNode == null || // optimization ((MyAnimationStateMachineNode)m_layers[i].CurrentNode).RootAnimationNode == null || // optimization ((MyAnimationStateMachineNode)m_layers[i].CurrentNode).RootAnimationNode is MyAnimationTreeNodeDummy) // optimization { animationUpdateData = animationUpdateDataLast; // restore backup continue; } int boneCount = animationUpdateData.BonesResult.Count; var bonesLast = animationUpdateDataLast.BonesResult; var bones = animationUpdateData.BonesResult; var bonesBindPose = animationUpdateDataLast.CharacterBones; if (currentLayer.Mode == MyAnimationStateMachine.MyBlendingMode.Replace) { for (int j = 0; j < boneCount; j++) { if (animationUpdateData.LayerBoneMask[j] == false) { bones[j].Translation = bonesLast[j].Translation; bones[j].Rotation = bonesLast[j].Rotation; } } } else if (currentLayer.Mode == MyAnimationStateMachine.MyBlendingMode.Add) { for (int j = 0; j < boneCount; j++) { if (animationUpdateData.LayerBoneMask[j]) { // add result to current Vector3 addTranslation; Quaternion addRotation; bonesBindPose[j].GetCompleteTransform(ref bones[j].Translation, ref bones[j].Rotation, out addTranslation, out addRotation); bones[j].Translation = bonesLast[j].Translation + addTranslation; bones[j].Rotation = bonesLast[j].Rotation * addRotation; } else { // unaffected, copy last result (deep copy because we allocate from pool and bone is currenlty class) bones[j].Translation = bonesLast[j].Translation; bones[j].Rotation = bonesLast[j].Rotation; } } } ResultBonesPool.Free(animationUpdateDataLast.BonesResult); } }