//private static Dictionary<UnityEngine.AnimationClip, List<AnimationCurve>> s_curvesPerClip = new Dictionary<AnimationClip, List<AnimationCurve>> (); private static UnityEngine.AnimationClip Convert(Clip animation, FrameContainer frames, out UVector3 rootStart, out UVector3 rootEnd) { var clip = new UnityEngine.AnimationClip(); clip.legacy = true; var rotateAxes = new[] { new { Name = "x", Mask = new UVector4(1f, 0f, 0f, 0f) }, new { Name = "y", Mask = new UVector4(0f, 1f, 0f, 0f) }, new { Name = "z", Mask = new UVector4(0f, 0f, 1f, 0f) }, new { Name = "w", Mask = new UVector4(0f, 0f, 0f, 1f) } }; var root = animation.Bones.FirstOrDefault(x => x.BoneId == 0); if (root != null && root.FrameCount > 0) { rootStart = Types.Convert(root.Frames.First().Translation); rootEnd = Types.Convert(root.Frames.Last().Translation); } else { rootStart = rootEnd = UVector3.zero; } foreach (var bone in animation.Bones) { if (!frames.HasBoneWithId(bone.BoneId)) // what are these used for ? { if (bone.BoneId != -1) { Debug.LogWarning($"Bone with id {bone.BoneId} does not exist"); } continue; } var bFrames = bone.Frames; var frame = frames.GetByBoneId(bone.BoneId); string bonePath = frame.Path; AnimationCurve curve; var axisAngle = bFrames.ToDictionary(x => x, x => { var q = Types.Convert(x.Rotation); float ang; UnityEngine.Vector3 axis; q.ToAngleAxis(out ang, out axis); return(new UVector4(q.x, q.y, q.z, q.w)); }); foreach (var axis in rotateAxes) { var keys = bFrames .Select(x => new Keyframe(x.Time * TimeScale, UVector4.Dot(axisAngle[x], axis.Mask))) .ToArray(); curve = new UnityEngine.AnimationCurve(keys); clip.SetCurve(bonePath, typeof(Transform), "localRotation." + axis.Name, curve); //OnCurveAddedToClip (clip, curve); } var converted = bFrames.Select(x => Types.Convert(x.Translation)).ToArray(); if (!converted.Any(x => !x.Equals(UVector3.zero))) { continue; } var anyVelocities = false; var deltaVals = converted.Select((x, i) => { var prev = Math.Max(0, i - 1); var next = Math.Min(i + 1, converted.Length - 1); var prevTime = bFrames[prev].Time * TimeScale; var nextTime = bFrames[next].Time * TimeScale; return(prevTime == nextTime || !(anyVelocities = true) ? UVector3.zero : (converted[next] - converted[prev]) / (nextTime - prevTime)); }).ToArray(); foreach (var translateAxis in s_translateAxes) { var positions = bFrames .Select((x, i) => new Keyframe(x.Time * TimeScale, UVector3.Dot(frame.transform.localPosition + converted[i], translateAxis.Mask))) .ToArray(); var deltas = bFrames.Select((x, i) => new Keyframe(x.Time * TimeScale, UVector3.Dot(deltaVals[i], translateAxis.Mask))).ToArray(); clip.SetCurve(bonePath, typeof(Transform), "localPosition." + translateAxis.Name, new UnityEngine.AnimationCurve(positions)); if (!anyVelocities) { continue; } clip.SetCurve(bonePath, typeof(BFrame), "LocalVelocity." + translateAxis.Name, new UnityEngine.AnimationCurve(deltas)); } } clip.wrapMode = WrapMode.Loop; clip.EnsureQuaternionContinuity(); return(clip); }