mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-11-27 01:12:54 +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)
|
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)
|
public override void Read(Sequence blockStream, ref int channelOffset)
|
||||||
@ -769,7 +771,7 @@ namespace CodeWalker.GameFiles
|
|||||||
for (int n = 0; n < 4; n++)
|
for (int n = 0; n < 4; n++)
|
||||||
{
|
{
|
||||||
if ((c + n) >= 4) break;
|
if ((c + n) >= 4) break;
|
||||||
v[c + n] = sv3c.Value[n];
|
v[c + n] = ssqc.Value[n];
|
||||||
}
|
}
|
||||||
c += 4;
|
c += 4;
|
||||||
}
|
}
|
||||||
|
@ -550,6 +550,10 @@ namespace CodeWalker.GameFiles
|
|||||||
private ResourceSystemStructBlock<ushort> Unknown_40h_DataBlock = null;
|
private ResourceSystemStructBlock<ushort> Unknown_40h_DataBlock = null;
|
||||||
|
|
||||||
|
|
||||||
|
public Dictionary<ushort, Bone> BonesMap { get; set; }//for convienience finding bones by tag
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads the data-block from a stream.
|
/// Reads the data-block from a stream.
|
||||||
/// </summary>
|
/// </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>
|
/// <summary>
|
||||||
@ -784,6 +798,13 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
private string_r NameBlock = null;
|
private string_r NameBlock = null;
|
||||||
|
|
||||||
|
|
||||||
|
//used by CW for animating skeletons.
|
||||||
|
public Quaternion AnimRotation;
|
||||||
|
public Vector3 AnimTranslation;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads the data-block from a stream.
|
/// Reads the data-block from a stream.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -819,6 +840,10 @@ namespace CodeWalker.GameFiles
|
|||||||
this.Name = reader.ReadStringAt(//BlockAt<string_r>(
|
this.Name = reader.ReadStringAt(//BlockAt<string_r>(
|
||||||
this.NamePointer // offset
|
this.NamePointer // offset
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
AnimRotation = Rotation;
|
||||||
|
AnimTranslation = Translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -78,6 +78,7 @@ namespace CodeWalker.Rendering
|
|||||||
public ClipMapEntry ClipMapEntryUV0;
|
public ClipMapEntry ClipMapEntryUV0;
|
||||||
public ClipMapEntry ClipMapEntryUV1;
|
public ClipMapEntry ClipMapEntryUV1;
|
||||||
|
|
||||||
|
public Dictionary<ushort, RenderableModel> ModelBoneLinks;
|
||||||
|
|
||||||
|
|
||||||
public override void Init(DrawableBase drawable)
|
public override void Init(DrawableBase drawable)
|
||||||
@ -254,6 +255,17 @@ namespace CodeWalker.Rendering
|
|||||||
Matrix trans = (boneidx < modeltransforms.Length) ? modeltransforms[boneidx] : Matrix.Identity;
|
Matrix trans = (boneidx < modeltransforms.Length) ? modeltransforms[boneidx] : Matrix.Identity;
|
||||||
Bone bone = (hasbones && (boneidx < bones.Count)) ? bones[boneidx] : null;
|
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 ((fragtransforms != null))// && (fragtransformid < fragtransforms.Length))
|
||||||
{
|
{
|
||||||
if (fragtransformid < fragtransforms.Length)
|
if (fragtransformid < fragtransforms.Length)
|
||||||
@ -364,8 +376,92 @@ namespace CodeWalker.Rendering
|
|||||||
var anim = clipanim?.Animation;
|
var anim = clipanim?.Animation;
|
||||||
if (anim == null)
|
if (anim == null)
|
||||||
{ return; }
|
{ 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)
|
private void UpdateAnimUV(ClipMapEntry cme)
|
||||||
{
|
{
|
||||||
@ -384,11 +480,11 @@ namespace CodeWalker.Rendering
|
|||||||
{ return; }
|
{ return; }
|
||||||
|
|
||||||
bool interpolate = true; //how to know? eg. cs4_14_hickbar_anim shouldn't
|
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 duration = anim.Duration;
|
||||||
var frames = anim.Frames;
|
var frames = anim.Frames;
|
||||||
var nframes = (lastFrameSameAsFirst) ? (frames - 1) : frames;
|
var nframes = (ignoreLastFrame) ? (frames - 1) : frames;
|
||||||
|
|
||||||
var curPos = ((CurrentAnimTime % duration) / duration) * nframes;
|
var curPos = ((CurrentAnimTime % duration) / duration) * nframes;
|
||||||
var frame0 = ((ushort)curPos) % frames;
|
var frame0 = ((ushort)curPos) % frames;
|
||||||
|
@ -1141,11 +1141,11 @@ namespace CodeWalker.Rendering
|
|||||||
|
|
||||||
//draw line from bone's position to parent position...
|
//draw line from bone's position to parent position...
|
||||||
Vector3 lbeg = Vector3.Zero;
|
Vector3 lbeg = Vector3.Zero;
|
||||||
Vector3 lend = bone.Translation;// bone.Rotation.Multiply();
|
Vector3 lend = bone.AnimTranslation;// bone.Rotation.Multiply();
|
||||||
while (pbone != null)
|
while (pbone != null)
|
||||||
{
|
{
|
||||||
lbeg = pbone.Rotation.Multiply(lbeg) + pbone.Translation;
|
lbeg = pbone.AnimRotation.Multiply(lbeg) + pbone.AnimTranslation;
|
||||||
lend = pbone.Rotation.Multiply(lend) + pbone.Translation;
|
lend = pbone.AnimRotation.Multiply(lend) + pbone.AnimTranslation;
|
||||||
pbone = pbone.Parent;
|
pbone = pbone.Parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user