private void PreviewButtonAction() { creator.gameObjectTransform.position = pos; creator.gameObjectTransform.rotation = rot; sliderTime = 0f; sliderTimeBuffor = sliderTime; if (graph == null) { graph = new PreparingDataPlayableGraph(); graph.Initialize(creator.gameObjectTransform.gameObject); } else if (!graph.IsValid()) { graph.Initialize(creator.gameObjectTransform.gameObject); } graph.ClearMainMixerInput(); switch (selectedCreator) { case 1: BlendTreeInfo blendTree = creator.blendTrees[creator.selectedBlendTree]; if (blendTree.IsValid()) { blendTree.CreateGraphFor( creator.gameObjectTransform.gameObject, graph ); isSequencePlaying = false; maxSliderTime = blendTree.GetLength(); } break; case 2: AnimationsSequence seq = creator.sequences[creator.selectedSequence]; if (seq.IsValid()) { seq.CreateAnimationsInTime(0f, graph); isSequencePlaying = true; maxSliderTime = seq.length; } break; } }
private void InitializePlayableGraph() { if (creator.gameObjectTransform == null) { return; } if (graph != null) { if (graph.IsValid()) { graph.Destroy(); } } graph = new PreparingDataPlayableGraph(); graph.Initialize(creator.gameObjectTransform.gameObject); }
private void OnPreviewBTN() { previewBTNClick = true; animationState = AnimationState.Stoped; float deltaTime = -currentAnimaionTime; if (playableGraph != null && playableGraph.IsValid()) { playableGraph.ClearMainMixerInput(); playableGraph.Destroy(); } playableGraph = new PreparingDataPlayableGraph(); playableGraph.Initialize(gameObject); playableGraph.CreateAnimationDataPlayables(editedData); currentAnimaionTime = 0f; }
public static void CalculateImpactPoints( MotionMatchingData data, MotionMatchingContact[] contactPoints, PreparingDataPlayableGraph playableGraph, GameObject gameObject ) { // Normalizacja kierunków kontaktów for (int i = 0; i < data.contactPoints.Count; i++) { MotionMatchingContact cp = data.contactPoints[i]; cp.contactNormal = math.normalize(cp.contactNormal); data.contactPoints[i] = cp; } // Pobrani początkowych wartości game objectu Vector3 startPos = gameObject.transform.position; Quaternion startRot = gameObject.transform.rotation; float deltaTime = data.frameTime; Matrix4x4 frameMatrix; NeedValueToCalculateData[] recordedData = new NeedValueToCalculateData[data.numberOfFrames]; Vector3[] cpPos = new Vector3[contactPoints.Length]; Vector3[] cpNormals = new Vector3[contactPoints.Length]; Vector3[] cpForwards = new Vector3[contactPoints.Length]; if (playableGraph != null) { playableGraph.Destroy(); } playableGraph = new PreparingDataPlayableGraph(); playableGraph.Initialize(gameObject); playableGraph.CreateAnimationDataPlayables(data); // RecordingData float currentTime = 0f; float currentDeltaTime = deltaTime; int contactPointIndex = 0; for (int i = 0; i < data.numberOfFrames; i++) { recordedData[i] = new NeedValueToCalculateData( gameObject.transform.position, gameObject.transform.forward, gameObject.transform.rotation ); currentTime += deltaTime; if (contactPointIndex < contactPoints.Length && currentTime >= contactPoints[contactPointIndex].startTime) { float buforDeltaTime = currentTime - contactPoints[contactPointIndex].startTime; currentDeltaTime = deltaTime - buforDeltaTime; playableGraph.EvaluateMotionMatchgData(data, currentDeltaTime); cpPos[contactPointIndex] = gameObject.transform.TransformPoint(contactPoints[contactPointIndex].position); cpNormals[contactPointIndex] = gameObject.transform.TransformDirection(contactPoints[contactPointIndex].contactNormal); cpForwards[contactPointIndex] = gameObject.transform.forward; contactPointIndex++; playableGraph.EvaluateMotionMatchgData(data, buforDeltaTime); currentDeltaTime = deltaTime; } else { playableGraph.EvaluateMotionMatchgData(data, currentDeltaTime); } } // calcualationData for (int i = 0; i < data.numberOfFrames; i++) { frameMatrix = Matrix4x4.TRS( recordedData[i].position, recordedData[i].rotation, Vector3.one ); FrameData currentFrame = data.frames[i]; for (int impactIndex = 0; impactIndex < data.contactPoints.Count; impactIndex++) { if (data.contactPoints[impactIndex].IsContactInTime(currentFrame.localTime)) { currentFrame.contactPoints = new FrameContact[1]; Vector3 pos = frameMatrix.inverse.MultiplyPoint3x4(cpPos[impactIndex]); Vector3 norDir = frameMatrix.inverse.MultiplyVector(cpNormals[impactIndex]); Vector3 forw = frameMatrix.inverse.MultiplyVector(cpForwards[impactIndex]); FrameContact cp = new FrameContact( pos, norDir //forw ); currentFrame.contactPoints[0] = cp; break; } else { currentFrame.contactPoints = new FrameContact[0]; } } if (data.contactPoints.Count == 0) { currentFrame.contactPoints = new FrameContact[0]; } data.frames[i] = currentFrame; } gameObject.transform.position = startPos; gameObject.transform.rotation = startRot; //if (data.contactPoints.Count >= 2) //{ // Vector3 firstPoint = data.GetContactPoint(0, data.contactPoints[0].startTime).position; // Vector3 secondPoint = data.GetContactPoint(1, data.contactPoints[0].startTime).position; // Vector3 dir = secondPoint - firstPoint; // dir.y = 0; // data.fromFirstToSecondContactRot = Quaternion.FromToRotation(dir, Vector3.forward); //} //else //{ // data.fromFirstToSecondContactRot = Quaternion.identity; //} playableGraph.ClearMainMixerInput(); playableGraph.Destroy(); }
public static void CalculateContactPoints( MotionMatchingData data, MotionMatchingContact[] contactPoints, PreparingDataPlayableGraph playableGraph, GameObject gameObject ) { for (int i = 0; i < data.contactPoints.Count; i++) { MotionMatchingContact cp = data.contactPoints[i]; cp.contactNormal = math.normalize(cp.contactNormal); data.contactPoints[i] = cp; } Vector3 startPos = gameObject.transform.position; Quaternion startRot = gameObject.transform.rotation; float deltaTime = data.frameTime; Matrix4x4 frameMatrix; NeedValueToCalculateData[] recordedData = new NeedValueToCalculateData[data.numberOfFrames]; Vector3[] cpPos = new Vector3[contactPoints.Length]; Vector3[] cpNormals = new Vector3[contactPoints.Length]; Vector3[] cpForwards = new Vector3[contactPoints.Length]; if (playableGraph != null) { playableGraph.Destroy(); } playableGraph = new PreparingDataPlayableGraph(); playableGraph.Initialize(gameObject); playableGraph.CreateAnimationDataPlayables(data); // RecordingData float currentTime = 0f; float currentDeltaTime = deltaTime; int contactPointIndex = 0; for (int i = 0; i < data.numberOfFrames; i++) { recordedData[i] = new NeedValueToCalculateData( gameObject.transform.position, gameObject.transform.forward, gameObject.transform.rotation ); currentTime += deltaTime; if (contactPointIndex < contactPoints.Length && currentTime >= contactPoints[contactPointIndex].startTime) { float buforDeltaTime = currentTime - contactPoints[contactPointIndex].startTime; currentDeltaTime = deltaTime - buforDeltaTime; playableGraph.EvaluateMotionMatchgData(data, currentDeltaTime); cpPos[contactPointIndex] = gameObject.transform.TransformPoint(contactPoints[contactPointIndex].position); cpNormals[contactPointIndex] = gameObject.transform.TransformDirection(contactPoints[contactPointIndex].contactNormal); cpForwards[contactPointIndex] = gameObject.transform.forward; contactPointIndex++; playableGraph.EvaluateMotionMatchgData(data, buforDeltaTime); currentDeltaTime = deltaTime; } else { playableGraph.EvaluateMotionMatchgData(data, currentDeltaTime); } } // calcualationData for (int i = 0; i < data.numberOfFrames; i++) { frameMatrix = Matrix4x4.TRS( recordedData[i].position, recordedData[i].rotation, Vector3.one ); FrameData currentFrame = data.frames[i]; currentFrame.contactPoints = new FrameContact[cpPos.Length]; for (int j = 0; j < cpPos.Length; j++) { Vector3 pos = frameMatrix.inverse.MultiplyPoint3x4(cpPos[j]); Vector3 norDir = frameMatrix.inverse.MultiplyVector(cpNormals[j]); Vector3 forw = frameMatrix.inverse.MultiplyVector(cpForwards[j]); FrameContact cp = new FrameContact( pos, norDir //forw ); currentFrame.contactPoints[j] = cp; } data.frames[i] = currentFrame; } gameObject.transform.position = startPos; gameObject.transform.rotation = startRot; if (data.contactPoints.Count >= 2) { for (int i = 0; i < contactPoints.Length - 1; i++) { Vector3 firstPoint = data.GetContactPointInTime(i, data.contactPoints[i].startTime).position; Vector3 secondPoint = data.GetContactPointInTime(i + 1, data.contactPoints[i].startTime).position; Vector3 dir = secondPoint - firstPoint; dir.y = 0; MotionMatchingContact c = data.contactPoints[i]; c.rotationFromForwardToNextContactDir = Quaternion.FromToRotation(dir, Vector3.forward); data.contactPoints[i] = c; } } if (data.contactPoints.Count >= 2) { Vector3 firstPoint = data.GetContactPointInTime(0, data.contactPoints[0].startTime).position; Vector3 secondPoint = data.GetContactPointInTime(1, data.contactPoints[0].startTime).position; Vector3 dir = secondPoint - firstPoint; dir.y = 0; data.fromFirstToSecondContactRot = Quaternion.FromToRotation( Vector3.ProjectOnPlane(dir, Vector3.up), Vector3.forward ); } else { data.fromFirstToSecondContactRot = Quaternion.identity; } playableGraph.ClearMainMixerInput(); playableGraph.Destroy(); }
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 CalculateDataButton( bool calculateClips = true, bool calculateBlendTrees = true, bool calculateAnimationSequences = true ) { if (graph != null && graph.IsValid()) { graph.Destroy(); } creator.trajectoryStepTimes.Sort(); string saveFolder; if (creator.saveDataPath == "") { saveFolder = EditorUtility.OpenFolderPanel("Place for save motion matching data", "Assets", ""); creator.saveDataPath = saveFolder != "" ? saveFolder : creator.saveDataPath; } else { saveFolder = EditorUtility.OpenFolderPanel("Place for save motion matching data", creator.saveDataPath, ""); creator.saveDataPath = saveFolder != "" ? saveFolder : creator.saveDataPath; } Vector3 position = creator.gameObjectTransform.position; Quaternion rotation = creator.gameObjectTransform.rotation; if (saveFolder == "") { return; } PreparingDataPlayableGraph calculationGraph = new PreparingDataPlayableGraph(); calculationGraph.Initialize(creator.gameObjectTransform.gameObject); #region Pobranie referencji transformow z maski List <Transform> bonesMask = new List <Transform>(); for (int i = 0; i < creator.avatarMask.transformCount; i++) { if (creator.avatarMask.GetTransformActive(i)) { bonesMask.Add(creator.gameObjectTransform.Find(creator.avatarMask.GetTransformPath(i))); } } for (int i = 0; i < bonesMask.Count; i++) { if (bonesMask[i].name == creator.gameObjectTransform.name) { bonesMask.RemoveAt(i); break; } } #endregion if (calculateClips) { CalculateNormalClips( calculationGraph, saveFolder, bonesMask ); calculationGraph.ClearMainMixerInput(); } if (calculateBlendTrees) { CalculateBlendTrees( calculationGraph, saveFolder, bonesMask ); calculationGraph.ClearMainMixerInput(); } if (calculateAnimationSequences) { CalculateAnimationsSequences( calculationGraph, saveFolder, bonesMask ); calculationGraph.Destroy(); } AssetDatabase.SaveAssets(); creator.gameObjectTransform.position = position; creator.gameObjectTransform.rotation = rotation; }
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; } }