public static MotionMatchingData CalculateAnimationSequenceData( string name, AnimationsSequence seq, GameObject go, PreparingDataPlayableGraph graph, List <Transform> bonesMask, List <Vector2> bonesWeights, int sampling, bool loop, Transform root, List <float> trajectoryStepTimes, bool blendToYourself, bool findInYourself ) { if (!graph.IsValid()) { graph.Initialize(go); } go.transform.position = Vector3.zero; go.transform.rotation = Quaternion.identity; seq.CalculateLength(); #region need floats float frameTime = 1f / (float)sampling; int numberOfFrames = Mathf.FloorToInt(seq.length / frameTime) + 1; #endregion MotionMatchingData data = new MotionMatchingData( seq.clips.ToArray(), seq.neededInfo.ToArray(), sampling, name, loop, seq.length, findInYourself, blendToYourself, AnimationDataType.AnimationSequence ); FrameData frameBuffer; BoneData boneBuffer; PoseData poseBuffor; Trajectory trajectoryBuffor; NeedValueToCalculateData[] previuData = new NeedValueToCalculateData[bonesMask.Count]; NeedValueToCalculateData[] nextData = new NeedValueToCalculateData[bonesMask.Count]; int seqDeltaSampling = 3; //seq.CreatePlayableGraph(playableGraph, go); //seq.Update(-frameTime, playableGraph, seqDeltaSampling); seq.CreateAnimationsInTime(0f, graph); graph.Evaluate(frameTime); seq.Update(graph, frameTime); int frameIndex = 0; for (; frameIndex < numberOfFrames; frameIndex++) { for (int i = 0; i < bonesMask.Count; i++) { previuData[i] = GetValuesFromTransform(bonesMask[i], root); } graph.Evaluate(frameTime); seq.Update(graph, frameTime); //Debug.Log((float)animator.GetMixerInputTime(0) - clip.length); for (int i = 0; i < bonesMask.Count; i++) { nextData[i] = GetValuesFromTransform(bonesMask[i], root); } poseBuffor = new PoseData(bonesMask.Count); for (int i = 0; i < bonesMask.Count; i++) { float2 boneWeight = bonesWeights[i]; float3 velocity = BoneData.CalculateVelocity(previuData[i].position, nextData[i].position, frameTime); float3 localPosition = previuData[i].position; quaternion orientation = previuData[i].rotation; boneBuffer = new BoneData(localPosition, velocity); poseBuffor.SetBone(boneBuffer, i); } trajectoryBuffor = new Trajectory(trajectoryStepTimes.Count); frameBuffer = new FrameData( frameIndex, frameIndex * frameTime, trajectoryBuffor, poseBuffor, new FrameSections(true) ); data.AddFrame(frameBuffer); } float clipGlobalStart; Vector2 clipStartAndStop; float recordingClipTime; if (trajectoryStepTimes[0] < 0) { clipGlobalStart = trajectoryStepTimes[0]; clipStartAndStop = new Vector2(-clipGlobalStart, -clipGlobalStart + seq.length); } else { clipGlobalStart = 0; clipStartAndStop = new Vector2(0, seq.length); } if (trajectoryStepTimes[trajectoryStepTimes.Count - 1] > 0) { recordingClipTime = clipStartAndStop.y + trajectoryStepTimes[trajectoryStepTimes.Count - 1] + 0.1f; } else { recordingClipTime = clipStartAndStop.y + 0.1f; } int samplesPerSecond = 100; float deltaTime = 1f / (float)samplesPerSecond; int dataCount = Mathf.CeilToInt(recordingClipTime / deltaTime); NeedValueToCalculateData[] recordData = new NeedValueToCalculateData[dataCount]; go.transform.position = Vector3.zero; go.transform.rotation = Quaternion.identity; //seq.Update(clipGlobalStart, playableGraph); graph.ClearMainMixerInput(); seq.CreateAnimationsInTime(clipGlobalStart, graph); recordData[0] = new NeedValueToCalculateData( go.transform.position, go.transform.forward, go.transform.rotation ); for (int i = 0; i < dataCount; i++) { graph.Evaluate(deltaTime); seq.Update(graph, deltaTime); recordData[i] = new NeedValueToCalculateData( go.transform.position, go.transform.forward, go.transform.rotation ); } //clearing graph from all animations graph.ClearMainMixerInput(); MotionDataCalculator.CalculateTrajectoryPointsFromRecordData( data, recordData, recordingClipTime, deltaTime, clipStartAndStop, trajectoryStepTimes ); data.usedFrameCount = data.numberOfFrames; data.trajectoryPointsTimes = new List <float>(); for (int i = 0; i < trajectoryStepTimes.Count; i++) { data.trajectoryPointsTimes.Add(trajectoryStepTimes[i]); } return(data); }
public static MotionMatchingData CalculateBlendTreeData( string name, GameObject go, PreparingDataPlayableGraph graph, AnimationClip[] clips, List <Transform> bonesMask, List <Vector2> bonesWeights, Transform root, List <float> trajectoryStepTimes, float[] weightsForClips, int sampling, bool loop, bool blendToYourself, bool findInYourself ) { if (!graph.IsValid()) { graph.Initialize(go); } go.transform.position = Vector3.zero; go.transform.rotation = Quaternion.identity; #region need floats float frameTime = 1f / (float)sampling; int numberOfFrames = Mathf.FloorToInt(clips[0].length / frameTime) + 1; #endregion float weightSum = 0f; for (int i = 0; i < weightsForClips.Length; i++) { weightSum += weightsForClips[i]; } for (int i = 0; i < weightsForClips.Length; i++) { weightsForClips[i] = weightsForClips[i] / weightSum; } MotionMatchingData data = new MotionMatchingData( clips, weightsForClips, sampling, name, loop, clips[0].length, findInYourself, blendToYourself, AnimationDataType.BlendTree ); FrameData frameBuffer; BoneData boneBuffer; PoseData poseBuffor; Trajectory trajectoryBuffor; NeedValueToCalculateData[] previewBoneData = new NeedValueToCalculateData[bonesMask.Count]; NeedValueToCalculateData[] nextBoneData = new NeedValueToCalculateData[bonesMask.Count]; for (int i = 0; i < clips.Length; i++) { graph.AddClipPlayable(clips[i]); graph.SetMixerInputTime(i, 0f); graph.SetMixerInputWeight(i, weightsForClips[i]); } graph.Evaluate(frameTime); int frameIndex = 0; float currentCheckingTime = 0f; // FramesCalculation for (; frameIndex < numberOfFrames; frameIndex++) { for (int i = 0; i < bonesMask.Count; i++) { previewBoneData[i] = GetValuesFromTransform(bonesMask[i], root); } graph.Evaluate(frameTime); currentCheckingTime = frameIndex * frameTime; for (int i = 0; i < bonesMask.Count; i++) { nextBoneData[i] = GetValuesFromTransform(bonesMask[i], root); } poseBuffor = new PoseData(bonesMask.Count); for (int i = 0; i < bonesMask.Count; i++) { float2 boneWeight = bonesWeights[i]; float3 velocity = BoneData.CalculateVelocity(previewBoneData[i].position, nextBoneData[i].position, frameTime); float3 localPosition = previewBoneData[i].position; quaternion orientation = previewBoneData[i].rotation; boneBuffer = new BoneData(localPosition, velocity); poseBuffor.SetBone(boneBuffer, i); } trajectoryBuffor = new Trajectory(trajectoryStepTimes.Count); frameBuffer = new FrameData( frameIndex, currentCheckingTime, trajectoryBuffor, poseBuffor, new FrameSections(true) ); data.AddFrame(frameBuffer); } // Trajectory calculations float clipGlobalStart; Vector2 clipStartAndStop; float recordingClipTime; if (trajectoryStepTimes[0] < 0) { clipGlobalStart = trajectoryStepTimes[0]; clipStartAndStop = new Vector2(-clipGlobalStart, -clipGlobalStart + clips[0].length); } else { clipGlobalStart = 0; clipStartAndStop = new Vector2(0, clips[0].length); } if (trajectoryStepTimes[trajectoryStepTimes.Count - 1] > 0) { recordingClipTime = clipStartAndStop.y + trajectoryStepTimes[trajectoryStepTimes.Count - 1] + 0.1f; } else { recordingClipTime = clipStartAndStop.y + 0.1f; } int samplesPerSecond = 100; float deltaTime = 1f / (float)samplesPerSecond; int dataCount = Mathf.CeilToInt(recordingClipTime / deltaTime); NeedValueToCalculateData[] recordData = new NeedValueToCalculateData[dataCount]; go.transform.position = Vector3.zero; go.transform.rotation = Quaternion.identity; for (int i = 0; i < graph.GetMixerInputCount(); i++) { graph.SetMixerInputTimeInPlace(i, clipGlobalStart); } recordData[0] = new NeedValueToCalculateData( go.transform.position, go.transform.forward, go.transform.rotation ); for (int i = 0; i < dataCount; i++) { graph.Evaluate(deltaTime); recordData[i] = new NeedValueToCalculateData( go.transform.position, go.transform.forward, go.transform.rotation ); } //clearing graph from all animations graph.ClearMainMixerInput(); MotionDataCalculator.CalculateTrajectoryPointsFromRecordData( data, recordData, recordingClipTime, deltaTime, clipStartAndStop, trajectoryStepTimes ); data.usedFrameCount = data.numberOfFrames; data.trajectoryPointsTimes = new List <float>(); for (int i = 0; i < trajectoryStepTimes.Count; i++) { data.trajectoryPointsTimes.Add(trajectoryStepTimes[i]); } return(data); }
private void CalculateAnimationsSequences( PreparingDataPlayableGraph graph, string saveFolder, List <Transform> bonesMask ) { foreach (AnimationsSequence seq in creator.sequences) { if (!seq.IsValid()) { continue; } MotionMatchingData newCreatedAsset = MotionDataCalculator.CalculateAnimationSequenceData( seq.name, seq, creator.gameObjectTransform.gameObject, graph, bonesMask, creator.bonesWeights, creator.posesPerSecond, true, creator.gameObjectTransform, creator.trajectoryStepTimes, seq.blendToYourself, seq.findInYourself ); string path = saveFolder.Substring(Application.dataPath.Length - 6) + "/" + newCreatedAsset.name + ".asset"; MotionMatchingData loadedAsset = (MotionMatchingData)AssetDatabase.LoadAssetAtPath(path, typeof(MotionMatchingData)); float startTime = 0f; float endTime = 0f; float delta = 0.1f; for (int i = 0; i < seq.findPoseInClip.Count; i++) { endTime += (seq.neededInfo[i].y - seq.neededInfo[i].x); if (!seq.findPoseInClip[i]) { float startB = startTime; float endB = endTime; if (i == seq.findPoseInClip.Count - 1) { if (seq.findPoseInClip[0]) { endB = endTime - delta; } if (seq.findPoseInClip[i - 1]) { startB = startTime + delta; } } else if (i == 0) { if (seq.findPoseInClip[i + 1]) { endB = endTime - delta; } if (seq.findPoseInClip[seq.findPoseInClip.Count - 1]) { startB = startTime + delta; } } else { if (seq.findPoseInClip[i + 1]) { endB = endTime - delta; } if (seq.findPoseInClip[i - 1]) { startB = startTime + delta; } } newCreatedAsset.neverChecking.timeIntervals.Add(new Vector2(startB, endB)); } startTime = endTime; } if (loadedAsset == null) { AssetDatabase.CreateAsset(newCreatedAsset, path); //AssetDatabase.SaveAssets(); } else { loadedAsset.UpdateFromOther(newCreatedAsset, newCreatedAsset.name); if (loadedAsset.contactPoints != null) { if (loadedAsset.contactPoints.Count > 0) { MotionDataCalculator.CalculateContactPoints( loadedAsset, loadedAsset.contactPoints.ToArray(), graph, creator.gameObjectTransform.gameObject ); } } EditorUtility.SetDirty(loadedAsset); //AssetDatabase.SaveAssets(); } } Debug.Log("Calculation of sequences completed!"); }
private void CalculateBlendTrees( PreparingDataPlayableGraph graph, string saveFolder, List <Transform> bonesMask ) { foreach (BlendTreeInfo info in creator.blendTrees) { if (!info.IsValid()) { continue; } if (info.useSpaces && info.clips.Count == 2) { for (int spaces = 1; spaces <= info.spaces; spaces++) { float currentFactor = (float)spaces / (info.spaces + 1); float[] clipsWeights = new float[info.clips.Count]; clipsWeights[0] = currentFactor; clipsWeights[1] = 1f - currentFactor; //Debug.Log(clipsWeights[0]); //Debug.Log(clipsWeights[1]); MotionMatchingData dataToSave = MotionDataCalculator.CalculateBlendTreeData( info.name + currentFactor.ToString(), creator.gameObjectTransform.gameObject, graph, info.clips.ToArray(), bonesMask, creator.bonesWeights, creator.gameObjectTransform, creator.trajectoryStepTimes, clipsWeights, creator.posesPerSecond, false, info.blendToYourself, info.findInYourself ); string path = saveFolder.Substring(Application.dataPath.Length - 6) + "/" + dataToSave.name + ".asset"; MotionMatchingData loadedAsset = (MotionMatchingData)AssetDatabase.LoadAssetAtPath(path, typeof(MotionMatchingData)); if (loadedAsset == null) { AssetDatabase.CreateAsset(dataToSave, path); //AssetDatabase.SaveAssets(); } else { loadedAsset.UpdateFromOther(dataToSave, dataToSave.name); if (loadedAsset.contactPoints != null) { if (loadedAsset.contactPoints.Count > 0) { MotionDataCalculator.CalculateContactPoints( loadedAsset, loadedAsset.contactPoints.ToArray(), graph, creator.gameObjectTransform.gameObject ); } } EditorUtility.SetDirty(loadedAsset); //AssetDatabase.SaveAssets(); } } } else { MotionMatchingData dataToSave = MotionDataCalculator.CalculateBlendTreeData( info.name, creator.gameObjectTransform.gameObject, graph, info.clips.ToArray(), bonesMask, creator.bonesWeights, creator.gameObjectTransform, creator.trajectoryStepTimes, info.clipsWeights.ToArray(), creator.posesPerSecond, false, info.blendToYourself, info.findInYourself ); string path = saveFolder.Substring(Application.dataPath.Length - 6) + "/" + dataToSave.name + ".asset"; MotionMatchingData loadedAsset = (MotionMatchingData)AssetDatabase.LoadAssetAtPath(path, typeof(MotionMatchingData)); if (loadedAsset == null) { AssetDatabase.CreateAsset(dataToSave, path); //AssetDatabase.SaveAssets(); } else { loadedAsset.UpdateFromOther(dataToSave, dataToSave.name); EditorUtility.SetDirty(loadedAsset); //AssetDatabase.SaveAssets(); } } } Debug.Log("Calculation of Blend trees completed!"); }
private void CalculateNormalClips( PreparingDataPlayableGraph graph, string saveFolder, List <Transform> bonesMask ) { foreach (AnimationClip clip in creator.clips) { if (clip != null) { MotionMatchingData newCreatedAsset = MotionDataCalculator.CalculateNormalData( creator.gameObjectTransform.gameObject, graph, clip, bonesMask, creator.bonesWeights, creator.posesPerSecond, clip.isLooping, creator.gameObjectTransform, creator.trajectoryStepTimes, creator.blendToYourself, creator.findInYourself ); string path = saveFolder.Substring(Application.dataPath.Length - 6) + "/" + newCreatedAsset.name + ".asset"; MotionMatchingData loadedAsset = (MotionMatchingData)AssetDatabase.LoadAssetAtPath(path, typeof(MotionMatchingData)); if (creator.cutTimeFromStart > 0f) { newCreatedAsset.neverChecking.timeIntervals.Add( new float2( 0f, math.clamp(creator.cutTimeFromStart, 0f, newCreatedAsset.animationLength) )); } if (creator.cutTimeToEnd > 0f) { newCreatedAsset.neverChecking.timeIntervals.Add( new float2( math.clamp(newCreatedAsset.animationLength - creator.cutTimeToEnd, 0f, newCreatedAsset.animationLength), newCreatedAsset.animationLength )); } if (loadedAsset == null) { AssetDatabase.CreateAsset(newCreatedAsset, path); } else { loadedAsset.UpdateFromOther(newCreatedAsset, newCreatedAsset.name); if (loadedAsset.contactPoints != null) { if (loadedAsset.contactPoints.Count > 0) { MotionDataCalculator.CalculateContactPoints( loadedAsset, loadedAsset.contactPoints.ToArray(), graph, creator.gameObjectTransform.gameObject ); } } EditorUtility.SetDirty(loadedAsset); //AssetDatabase.SaveAssets(); } } else { Debug.Log("Element is null"); } } Debug.Log("Calculation of normal clips completed!"); }
private void ContactsButtonOptions() { GUILayout.Space(5); switch (editedData.contactsType) { case ContactStateType.NormalContacts: if (GUILayout.Button("Sort contacts", GUIResources.Button_MD()) && editedData != null) { editedData.contactPoints.Sort(); } if (GUILayout.Button("Calculate Contacts", GUIResources.Button_MD()) && editedData != null && gameObject != null) { if (gameObject == null) { Debug.LogWarning("Game object in MM Data Editor is NULL!"); return; } else { editedData.contactPoints.Sort(); MotionDataCalculator.CalculateContactPoints( editedData, editedData.contactPoints.ToArray(), this.playableGraph, this.gameObject ); playableGraph.Initialize(gameObject); playableGraph.CreateAnimationDataPlayables(editedData, currentAnimaionTime); } } break; case ContactStateType.Impacts: if (GUILayout.Button("Sort impacts", GUIResources.Button_MD()) && editedData != null) { editedData.contactPoints.Sort(); } if (GUILayout.Button("Calculate Impacts", GUIResources.Button_MD()) && editedData != null && gameObject != null) { if (gameObject == null) { Debug.LogWarning("Game object in MM Data Editor is NULL!"); return; } else { editedData.contactPoints.Sort(); MotionDataCalculator.CalculateImpactPoints( editedData, editedData.contactPoints.ToArray(), this.playableGraph, this.gameObject ); playableGraph.Initialize(gameObject); playableGraph.CreateAnimationDataPlayables(editedData, currentAnimaionTime); } } break; } }