mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-11-26 17:02:53 +08:00
Experimental bone animations playing from YCD. Windmills, fans, radars, ufos etc
This commit is contained in:
parent
80b6f3742b
commit
6f0a7d99f9
@ -697,7 +697,9 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
public override float EvaluateFloat(int frame)
|
||||
{
|
||||
return Values[frame];
|
||||
if (frame < Values?.Length) return Values[frame];
|
||||
if (Values?.Length > 0) return Values[0];
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
public override void Read(Sequence blockStream, ref int channelOffset)
|
||||
@ -769,7 +771,7 @@ namespace CodeWalker.GameFiles
|
||||
for (int n = 0; n < 4; n++)
|
||||
{
|
||||
if ((c + n) >= 4) break;
|
||||
v[c + n] = sv3c.Value[n];
|
||||
v[c + n] = ssqc.Value[n];
|
||||
}
|
||||
c += 4;
|
||||
}
|
||||
|
@ -550,6 +550,10 @@ namespace CodeWalker.GameFiles
|
||||
private ResourceSystemStructBlock<ushort> Unknown_40h_DataBlock = null;
|
||||
|
||||
|
||||
public Dictionary<ushort, Bone> BonesMap { get; set; }//for convienience finding bones by tag
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data-block from a stream.
|
||||
/// </summary>
|
||||
@ -611,6 +615,16 @@ namespace CodeWalker.GameFiles
|
||||
}
|
||||
}
|
||||
|
||||
BonesMap = new Dictionary<ushort, Bone>();
|
||||
if (Bones != null)
|
||||
{
|
||||
for (int i = 0; i < Bones.Count; i++)
|
||||
{
|
||||
var bone = Bones[i];
|
||||
BonesMap[bone.Id] = bone;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -784,6 +798,13 @@ namespace CodeWalker.GameFiles
|
||||
|
||||
private string_r NameBlock = null;
|
||||
|
||||
|
||||
//used by CW for animating skeletons.
|
||||
public Quaternion AnimRotation;
|
||||
public Vector3 AnimTranslation;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reads the data-block from a stream.
|
||||
/// </summary>
|
||||
@ -819,6 +840,10 @@ namespace CodeWalker.GameFiles
|
||||
this.Name = reader.ReadStringAt(//BlockAt<string_r>(
|
||||
this.NamePointer // offset
|
||||
);
|
||||
|
||||
|
||||
AnimRotation = Rotation;
|
||||
AnimTranslation = Translation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -78,6 +78,7 @@ namespace CodeWalker.Rendering
|
||||
public ClipMapEntry ClipMapEntryUV0;
|
||||
public ClipMapEntry ClipMapEntryUV1;
|
||||
|
||||
public Dictionary<ushort, RenderableModel> ModelBoneLinks;
|
||||
|
||||
|
||||
public override void Init(DrawableBase drawable)
|
||||
@ -254,6 +255,17 @@ namespace CodeWalker.Rendering
|
||||
Matrix trans = (boneidx < modeltransforms.Length) ? modeltransforms[boneidx] : Matrix.Identity;
|
||||
Bone bone = (hasbones && (boneidx < bones.Count)) ? bones[boneidx] : null;
|
||||
|
||||
if (mi < HDModels.Length) //populate bone links map for hd models
|
||||
{
|
||||
if (bone != null)
|
||||
{
|
||||
if (ModelBoneLinks == null) ModelBoneLinks = new Dictionary<ushort, RenderableModel>();
|
||||
ModelBoneLinks[bone.Id] = model;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ((fragtransforms != null))// && (fragtransformid < fragtransforms.Length))
|
||||
{
|
||||
if (fragtransformid < fragtransforms.Length)
|
||||
@ -364,8 +376,92 @@ namespace CodeWalker.Rendering
|
||||
var anim = clipanim?.Animation;
|
||||
if (anim == null)
|
||||
{ return; }
|
||||
if (anim.BoneIds?.data_items == null)
|
||||
{ return; }
|
||||
if (anim.Sequences?.data_items == null)
|
||||
{ return; }
|
||||
|
||||
bool interpolate = true; //how to know? eg. cs4_14_hickbar_anim shouldn't
|
||||
bool ignoreLastFrame = true;//if last frame is equivalent to the first one, eg rollercoaster small light "globes" don't
|
||||
|
||||
var duration = anim.Duration;
|
||||
var frames = anim.Frames;
|
||||
var nframes = (ignoreLastFrame) ? (frames - 1) : frames;
|
||||
|
||||
var curPos = ((CurrentAnimTime % duration) / duration) * nframes;
|
||||
var frame0 = ((ushort)curPos) % frames;
|
||||
var frame1 = (frame0 + 1) % frames;
|
||||
var falpha = (float)(curPos - Math.Floor(curPos));
|
||||
var ialpha = 1.0f - falpha;
|
||||
|
||||
|
||||
var dwbl = this.Key;
|
||||
var skel = dwbl?.Skeleton;
|
||||
var bones = skel?.Bones;
|
||||
if (bones == null)
|
||||
{ return; }
|
||||
|
||||
for (int i = 0; i < anim.BoneIds.data_items.Length; i++)
|
||||
{
|
||||
var boneiditem = anim.BoneIds.data_items[i];
|
||||
var track = boneiditem.Track;
|
||||
|
||||
Bone bone = null;
|
||||
skel?.BonesMap?.TryGetValue(boneiditem.BoneId, out bone);
|
||||
if (bone == null)
|
||||
{ continue; }
|
||||
|
||||
|
||||
for (int s = 0; s < anim.Sequences.data_items.Length; s++)
|
||||
{
|
||||
var seq = anim.Sequences.data_items[s];
|
||||
var aseq = seq.Sequences[i];
|
||||
switch (track)
|
||||
{
|
||||
case 0: //bone position
|
||||
var v0 = aseq.EvaluateVector(frame0);
|
||||
var v1 = aseq.EvaluateVector(frame1);
|
||||
var v = interpolate ? (v0 * ialpha) + (v1 * falpha) : v0;
|
||||
bone.AnimTranslation = v.XYZ();
|
||||
break;
|
||||
case 1: //bone orientation
|
||||
var q0 = new Quaternion(aseq.EvaluateVector(frame0));
|
||||
var q1 = new Quaternion(aseq.EvaluateVector(frame1));
|
||||
var q = interpolate ? Quaternion.Slerp(q0, q1, falpha) : q0;
|
||||
bone.AnimRotation = q;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < bones.Count; i++)
|
||||
{
|
||||
var bone = bones[i];
|
||||
|
||||
RenderableModel bmodel = null;
|
||||
ModelBoneLinks?.TryGetValue(bone.Id, out bmodel);
|
||||
if (bmodel == null)
|
||||
{ continue; }
|
||||
|
||||
//update model's transform from animated bone
|
||||
|
||||
var pos = bone.AnimTranslation;
|
||||
var ori = bone.AnimRotation;
|
||||
var pbone = bone.Parent;
|
||||
while (pbone != null)
|
||||
{
|
||||
pos = pbone.AnimRotation.Multiply(pos) + pbone.AnimTranslation;
|
||||
ori = pbone.AnimRotation * ori;
|
||||
pbone = pbone.Parent;
|
||||
}
|
||||
|
||||
bmodel.Transform = Matrix.AffineTransformation(1.0f, ori, pos);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//TODO........
|
||||
}
|
||||
private void UpdateAnimUV(ClipMapEntry cme)
|
||||
{
|
||||
@ -384,11 +480,11 @@ namespace CodeWalker.Rendering
|
||||
{ return; }
|
||||
|
||||
bool interpolate = true; //how to know? eg. cs4_14_hickbar_anim shouldn't
|
||||
bool lastFrameSameAsFirst = true;//if last frame is equivalent to the first one, eg rollercoaster small light "globes" don't
|
||||
bool ignoreLastFrame = true;//if last frame is equivalent to the first one, eg rollercoaster small light "globes" don't
|
||||
|
||||
var duration = anim.Duration;
|
||||
var frames = anim.Frames;
|
||||
var nframes = (lastFrameSameAsFirst) ? (frames - 1) : frames;
|
||||
var nframes = (ignoreLastFrame) ? (frames - 1) : frames;
|
||||
|
||||
var curPos = ((CurrentAnimTime % duration) / duration) * nframes;
|
||||
var frame0 = ((ushort)curPos) % frames;
|
||||
|
@ -1141,11 +1141,11 @@ namespace CodeWalker.Rendering
|
||||
|
||||
//draw line from bone's position to parent position...
|
||||
Vector3 lbeg = Vector3.Zero;
|
||||
Vector3 lend = bone.Translation;// bone.Rotation.Multiply();
|
||||
Vector3 lend = bone.AnimTranslation;// bone.Rotation.Multiply();
|
||||
while (pbone != null)
|
||||
{
|
||||
lbeg = pbone.Rotation.Multiply(lbeg) + pbone.Translation;
|
||||
lend = pbone.Rotation.Multiply(lend) + pbone.Translation;
|
||||
lbeg = pbone.AnimRotation.Multiply(lbeg) + pbone.AnimTranslation;
|
||||
lend = pbone.AnimRotation.Multiply(lend) + pbone.AnimTranslation;
|
||||
pbone = pbone.Parent;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user