public AnimationPackage(BinaryReader reader) : base(reader) { FileName = reader.ReadString(24); ClipCount = reader.ReadInt32(); Clips = new Clip[ClipCount]; for (int i = 0; i < ClipCount; ++i) { var clip = Clips[i] = new Clip(reader); _namedClips.Add(clip.Name, clip); } }
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 translateAxes = new[] { new { Name = "x", Mask = new UVector3(1f, 0f, 0f) }, new { Name = "y", Mask = new UVector3(0f, 1f, 0f) }, new { Name = "z", Mask = new UVector3(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) { var bFrames = bone.Frames; var frame = frames.GetByBoneId(bone.BoneId); string bonePath = frame.Path; 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(); clip.SetCurve(bonePath, typeof(Transform), "localRotation." + axis.Name, new UnityEngine.AnimationCurve(keys)); } 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 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; }
private Animation(Clip anim, FrameContainer frames) { _clip = Convert(anim, frames, out _rootStart, out _rootEnd); }