From ef497b1f6d7ed1276ef1f6c53d670196c7e86cdf Mon Sep 17 00:00:00 2001 From: dexy Date: Fri, 8 Nov 2019 02:00:16 +1100 Subject: [PATCH] Animation playback improvements --- CodeWalker.Core/GameFiles/Resources/Clip.cs | 35 +++++++++---- Rendering/Renderable.cs | 55 +++++++++++++-------- 2 files changed, 60 insertions(+), 30 deletions(-) diff --git a/CodeWalker.Core/GameFiles/Resources/Clip.cs b/CodeWalker.Core/GameFiles/Resources/Clip.cs index 0c2b81f..7971312 100644 --- a/CodeWalker.Core/GameFiles/Resources/Clip.cs +++ b/CodeWalker.Core/GameFiles/Resources/Clip.cs @@ -1368,9 +1368,9 @@ namespace CodeWalker.GameFiles // structure data public ulong AnimationPointer { get; set; } - public float Unknown_58h { get; set; } - public float Unknown_5Ch { get; set; } - public float Unknown_60h { get; set; } + public float StartTime { get; set; } //start time + public float EndTime { get; set; } //end time + public float Rate { get; set; } //1.0 rate..? public uint Unknown_64h { get; set; } // 0x00000000 public uint Unknown_68h { get; set; } // 0x00000000 public uint Unknown_6Ch { get; set; } // 0x00000000 @@ -1382,9 +1382,9 @@ namespace CodeWalker.GameFiles { base.Read(reader, parameters); this.AnimationPointer = reader.ReadUInt64(); - this.Unknown_58h = reader.ReadSingle(); - this.Unknown_5Ch = reader.ReadSingle(); - this.Unknown_60h = reader.ReadSingle(); + this.StartTime = reader.ReadSingle(); + this.EndTime = reader.ReadSingle(); + this.Rate = reader.ReadSingle(); this.Unknown_64h = reader.ReadUInt32(); this.Unknown_68h = reader.ReadUInt32(); this.Unknown_6Ch = reader.ReadUInt32(); @@ -1401,9 +1401,9 @@ namespace CodeWalker.GameFiles this.AnimationPointer = (ulong)(this.Animation != null ? this.Animation.FilePosition : 0); writer.Write(this.AnimationPointer); - writer.Write(this.Unknown_58h); - writer.Write(this.Unknown_5Ch); - writer.Write(this.Unknown_60h); + writer.Write(this.StartTime); + writer.Write(this.EndTime); + writer.Write(this.Rate); writer.Write(this.Unknown_64h); writer.Write(this.Unknown_68h); writer.Write(this.Unknown_6Ch); @@ -1416,6 +1416,14 @@ namespace CodeWalker.GameFiles if (Animation != null) list.Add(Animation); return list.ToArray(); } + + public float GetPlaybackTime(double currentTime) + { + double scaledTime = currentTime * Rate; + double duration = EndTime - StartTime; + double curpos = scaledTime % duration; + return StartTime + (float)curpos; + } } [TypeConverter(typeof(ExpandableObjectConverter))] public class ClipAnimationList : ClipBase { @@ -1532,6 +1540,15 @@ namespace CodeWalker.GameFiles if (Animation != null) list.Add(Animation); return list.ToArray(); } + + + public float GetPlaybackTime(double currentTime) + { + double scaledTime = currentTime * Rate; + double duration = EndTime - StartTime; + double curpos = scaledTime % duration; + return StartTime + (float)curpos; + } } diff --git a/Rendering/Renderable.cs b/Rendering/Renderable.cs index 87999de..af29172 100644 --- a/Rendering/Renderable.cs +++ b/Rendering/Renderable.cs @@ -403,37 +403,33 @@ namespace CodeWalker.Rendering } } - } private void UpdateAnim(ClipMapEntry cme) { + if (cme.Next != null) + { + UpdateAnim(cme.Next); + } + var clipanim = cme.Clip as ClipAnimation; var anim = clipanim?.Animation; if (anim != null) { - UpdateAnim(anim); + UpdateAnim(anim, clipanim.GetPlaybackTime(CurrentAnimTime)); } var clipanimlist = cme.Clip as ClipAnimationList; if (clipanimlist?.Animations != null) { - if (clipanimlist.Animations.Count > 0) + foreach (var canim in clipanimlist.Animations) { - UpdateAnim(clipanimlist.Animations[0].Animation); + if (canim?.Animation == null) continue; + UpdateAnim(canim.Animation, canim.GetPlaybackTime(CurrentAnimTime)); } - - - ////needs more work to synchronise these... seems to be multi layers, but timings are different - ////sort of represents animations LODs, higher detail stuff like fingers and feet movements in the layers - //foreach (var canim in clipanimlist.Animations) - //{ - // if (canim?.Animation == null) continue; - // UpdateAnim(canim.Animation); - // //break; - //} } + } - private void UpdateAnim(Animation anim) + private void UpdateAnim(Animation anim, float t) { if (anim == null) { return; } @@ -449,7 +445,7 @@ namespace CodeWalker.Rendering var frames = anim.Frames; var nframes = (ignoreLastFrame) ? (frames - 1) : frames; - var curPos = ((CurrentAnimTime % duration) / duration) * nframes; + var curPos = (t/duration) * nframes; var frame0 = ((ushort)curPos) % frames; var frame1 = (frame0 + 1) % frames; var falpha = (float)(curPos - Math.Floor(curPos)); @@ -543,13 +539,30 @@ namespace CodeWalker.Rendering } private void UpdateAnimUV(ClipMapEntry cme, RenderableGeometry rgeom = null) { - if (cme.Next != null) //is this a "chain" of clips to play..? + if (cme.Next != null) { - //cme = cme.Next; + UpdateAnimUV(cme.Next, rgeom); } - var clipanim = cme.Clip as ClipAnimation;//maybe ClipAnimationList? - var anim = clipanim?.Animation; + var clipanim = cme.Clip as ClipAnimation; + if (clipanim?.Animation != null) + { + UpdateAnimUV(clipanim.Animation, clipanim.GetPlaybackTime(CurrentAnimTime), rgeom); + } + + var clipanimlist = cme.Clip as ClipAnimationList; + if (clipanimlist?.Animations != null) + { + foreach (var canim in clipanimlist.Animations) + { + if (canim?.Animation == null) continue; + UpdateAnimUV(canim.Animation, canim.GetPlaybackTime(CurrentAnimTime), rgeom); + } + } + + } + private void UpdateAnimUV(Animation anim, float t, RenderableGeometry rgeom = null) + { if (anim == null) { return; } if (anim.BoneIds?.data_items == null) @@ -564,7 +577,7 @@ namespace CodeWalker.Rendering var frames = anim.Frames; var nframes = (ignoreLastFrame) ? (frames - 1) : frames; - var curPos = ((CurrentAnimTime % duration) / duration) * nframes; + var curPos = (t / duration) * nframes; var frame0 = ((ushort)curPos) % frames; var frame1 = (frame0 + 1) % frames; var falpha = (float)(curPos - Math.Floor(curPos));