Skin mesh now using correct bone transforms

This commit is contained in:
dexy
2019-11-03 22:43:39 +11:00
Unverified
parent 9f84ba8ad0
commit 6be0d5cb30
9 changed files with 342 additions and 84 deletions
+37 -31
View File
@@ -78,7 +78,7 @@ namespace CodeWalker.Rendering
public Dictionary<ushort, RenderableModel> ModelBoneLinks;
public Matrix3_s[] BoneTransforms;
public List<Bone> Bones;
public override void Init(DrawableBase drawable)
{
@@ -238,6 +238,7 @@ namespace CodeWalker.Rendering
HasSkeleton = hasskeleton;
HasTransforms = hastransforms;
Bones = skeleton?.Bones?.Data;
//calculate transforms for the models if there are any. (TODO: move this to a method for re-use...)
@@ -249,7 +250,7 @@ namespace CodeWalker.Rendering
if (hastransforms)
{
int boneidx = (int)((model.SkeletonBinding >> 24) & 0xFF);
int boneidx = model.BoneIndex;
Matrix trans = (boneidx < modeltransforms.Length) ? modeltransforms[boneidx] : Matrix.Identity;
Bone bone = (hasbones && (boneidx < bones.Count)) ? bones[boneidx] : null;
@@ -289,7 +290,7 @@ namespace CodeWalker.Rendering
}
}
if (((model.SkeletonBinding >> 8) & 0xFF) > 0) //skin mesh?
if (model.IsSkinMesh)
{
model.Transform = Matrix.Identity;
}
@@ -304,22 +305,7 @@ namespace CodeWalker.Rendering
//populate the bonetransforms array
Matrix[] bonetrans = (fragtransforms != null) ? fragtransforms : (modeltransforms != null) ? modeltransforms : null;
if (bonetrans != null)
{
BoneTransforms = new Matrix3_s[bonetrans.Length];
for (int i = 0; i < bonetrans.Length; i++)
{
Matrix b = bonetrans[i];
Matrix3_s bt = new Matrix3_s();
bt.Row1 = b.Row1;
bt.Row2 = b.Row2;
bt.Row3 = b.Row3;
BoneTransforms[i] = bt;
}
}
UpdateBoneTransforms();
}
@@ -373,6 +359,27 @@ namespace CodeWalker.Rendering
private void UpdateBoneTransforms()
{
if (Bones == null) return;
if ((BoneTransforms == null) || (BoneTransforms.Length != Bones.Count))
{
BoneTransforms = new Matrix3_s[Bones.Count];
}
for (int i = 0; i < Bones.Count; i++)
{
var bone = Bones[i];
Matrix b = bone.SkinTransform;
Matrix3_s bt = new Matrix3_s();
bt.Row1 = b.Column1;
bt.Row2 = b.Column2;
bt.Row3 = b.Column3;
BoneTransforms[i] = bt;
}
}
public void UpdateAnims(double realTime)
{
if (CurrentAnimTime == realTime) return;//already updated this!
@@ -469,25 +476,17 @@ namespace CodeWalker.Rendering
for (int i = 0; i < bones.Count; i++)
{
var bone = bones[i];
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;
}
bone.AnimTransform = Matrix.AffineTransformation(1.0f, ori, pos);
bone.UpdateAnimTransform();
//update model's transform from animated bone
RenderableModel bmodel = null;
ModelBoneLinks?.TryGetValue(bone.Id, out bmodel);
if (bmodel == null)
{ continue; }
if (((bmodel.SkeletonBinding >> 8) & 0xFF) > 0) //skin mesh? //TODO: see eg. p_oil_pjack_03_s
if (bmodel.IsSkinMesh) //don't transform model for skin mesh
{ continue; }
bmodel.Transform = bone.AnimTransform;
@@ -495,6 +494,8 @@ namespace CodeWalker.Rendering
}
UpdateBoneTransforms();
}
private void UpdateAnimUV(ClipMapEntry cme, RenderableGeometry rgeom = null)
{
@@ -591,11 +592,16 @@ namespace CodeWalker.Rendering
public bool UseTransform;
public Matrix Transform;
public int BoneIndex = 0;
public bool IsSkinMesh = false;
public void Init(DrawableModel dmodel)
{
SkeletonBinding = dmodel.SkeletonBinding;//4th byte is bone index, 2nd byte for skin meshes
RenderMaskFlags = dmodel.RenderMaskFlags; //only the first byte seems be related to this
IsSkinMesh = ((SkeletonBinding >> 8) & 0xFF) > 0;
BoneIndex = (int)((SkeletonBinding >> 24) & 0xFF);
DrawableModel = dmodel;
long geomcount = dmodel.Geometries.data_items.Length;
+37 -15
View File
@@ -1102,12 +1102,15 @@ namespace CodeWalker.Rendering
skeletonLineVerts.Clear();
const uint cred = 4278190335;// (uint)new Color4(1.0f, 0.0f, 0.0f, 1.0f).ToRgba();
const uint cgrn = 4278255360;// (uint)new Color4(0.0f, 1.0f, 0.0f, 1.0f).ToRgba();
const uint cblu = 4294901760;// (uint)new Color4(0.0f, 0.0f, 1.0f, 1.0f).ToRgba();
VertexTypePC v1 = new VertexTypePC();
VertexTypePC v2 = new VertexTypePC();
v1.Colour = cgrn;
v2.Colour = cblu;
VertexTypePC vr = new VertexTypePC();
VertexTypePC vg = new VertexTypePC();
VertexTypePC vb = new VertexTypePC();
vr.Colour = cred;
vg.Colour = cgrn;
vb.Colour = cblu;
foreach (var item in renderskeletonlist)
{
@@ -1127,7 +1130,6 @@ namespace CodeWalker.Rendering
var pind = pinds[i];
var bone = bones[i];
var pbone = bone.Parent;
if (pbone == null) continue; //nothing to draw for the root bone
if (xforms != null)//how to use xforms? bind pose?
{
@@ -1142,24 +1144,44 @@ namespace CodeWalker.Rendering
//draw line from bone's position to parent position...
Vector3 lbeg = Vector3.Zero;
Vector3 lend = bone.AnimTranslation;// bone.Rotation.Multiply();
while (pbone != null)
{
lbeg = pbone.AnimRotation.Multiply(lbeg) + pbone.AnimTranslation;
lend = pbone.AnimRotation.Multiply(lend) + pbone.AnimTranslation;
pbone = pbone.Parent;
}
float starsize = (bone.AnimTransform.TranslationVector-camera.Position).Length() * 0.011f;
Vector3[] starverts0 = { Vector3.UnitX * starsize, Vector3.UnitY * starsize, Vector3.UnitZ * starsize };
Vector3[] starverts1 = { Vector3.UnitX * -starsize, Vector3.UnitY * -starsize, Vector3.UnitZ * -starsize };
for (int j = 0; j < 3; j++) starverts0[j] = bone.AnimTransform.MultiplyW(starverts0[j]);
for (int j = 0; j < 3; j++) starverts1[j] = bone.AnimTransform.MultiplyW(starverts1[j]);
if (pbone != null)
{
lbeg = pbone.AnimTransform.MultiplyW(lbeg);
lend = pbone.AnimTransform.MultiplyW(lend);
}
if (entity != null)
{
lbeg = entity.Position + entity.Orientation.Multiply(lbeg * entity.Scale);
lend = entity.Position + entity.Orientation.Multiply(lend * entity.Scale);
for (int j = 0; j < 3; j++) starverts0[j] = entity.Position + entity.Orientation.Multiply(starverts0[j] * entity.Scale);
for (int j = 0; j < 3; j++) starverts1[j] = entity.Position + entity.Orientation.Multiply(starverts1[j] * entity.Scale);
}
v1.Position = lbeg;
v2.Position = lend;
skeletonLineVerts.Add(v1);
skeletonLineVerts.Add(v2);
vr.Position = starverts0[0]; skeletonLineVerts.Add(vr);
vr.Position = starverts1[0]; skeletonLineVerts.Add(vr);
vg.Position = starverts0[1]; skeletonLineVerts.Add(vg);
vg.Position = starverts1[1]; skeletonLineVerts.Add(vg);
vb.Position = starverts0[2]; skeletonLineVerts.Add(vb);
vb.Position = starverts1[2]; skeletonLineVerts.Add(vb);
if (pbone != null) //don't draw the origin to root bone line
{
vg.Position = lbeg;
vb.Position = lend;
skeletonLineVerts.Add(vg);
skeletonLineVerts.Add(vb);
}
}
+24 -7
View File
@@ -173,7 +173,8 @@ namespace CodeWalker.Rendering
public ShaderParamNames RenderTextureSampler = ShaderParamNames.DiffuseSampler;
public bool SpecularEnable = true;
Matrix3_s[] defaultBoneMatrices;
bool defaultBoneMatricesBound = false;
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
@@ -276,11 +277,13 @@ namespace CodeWalker.Rendering
layouts.Add(VertexType.PBBNCTT, new InputLayout(device, vspbbncttbytes, VertexTypePBBNCTT.GetLayout()));
layouts.Add(VertexType.PBBNCTTT, new InputLayout(device, vspbbnctttbytes, VertexTypePBBNCTTT.GetLayout()));
layouts.Add(VertexType.PBBNCCT, new InputLayout(device, vspbbncctbytes, VertexTypePBBNCCT.GetLayout()));
layouts.Add(VertexType.PBBNCCTT, new InputLayout(device, vspbbncctbytes, VertexTypePBBNCCTT.GetLayout()));//TODO
layouts.Add(VertexType.PBBNCCTX, new InputLayout(device, vspbbncctxbytes, VertexTypePBBNCCTX.GetLayout()));
layouts.Add(VertexType.PBBNCTTX, new InputLayout(device, vspbbncttxbytes, VertexTypePBBNCTTX.GetLayout()));
layouts.Add(VertexType.PBBNCTTTX, new InputLayout(device, vspbbncttxbytes, VertexTypePBBNCTTTX.GetLayout()));//TODO
layouts.Add(VertexType.PBBNCCTTX, new InputLayout(device, vspbbncctxbytes, VertexTypePBBNCCTTX.GetLayout()));//TODO
//PBBCCT todo
//PBBNC todo
@@ -343,6 +346,14 @@ namespace CodeWalker.Rendering
sphere = new UnitSphere(device, vsspherebytes, 4);
capsule = new UnitCapsule(device, vscapsulebytes, 4);
cylinder = new UnitCylinder(device, vscylinderbytes, 8);
defaultBoneMatrices = new Matrix3_s[255];
for (int i = 0; i < 255; i++)
{
defaultBoneMatrices[i].Row1 = Vector4.UnitX;
defaultBoneMatrices[i].Row2 = Vector4.UnitY;
defaultBoneMatrices[i].Row3 = Vector4.UnitZ;
}
}
private void InitInstGlobalVars()
@@ -446,6 +457,9 @@ namespace CodeWalker.Rendering
case VertexType.PBBNCCT:
vs = basicvspbbncct;
break;
case VertexType.PBBNCCTT://todo
vs = basicvspbbncct;
break;
case VertexType.PBBNCTX:
vs = basicvspbbnctx;
break;
@@ -557,12 +571,15 @@ namespace CodeWalker.Rendering
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
if (((model.SkeletonBinding >> 8) & 0xFF) > 0)
if (model.Owner.BoneTransforms != null)
{
if (model.Owner.BoneTransforms != null)
{
SetBoneMatrices(context, model.Owner.BoneTransforms);
}
SetBoneMatrices(context, model.Owner.BoneTransforms);
defaultBoneMatricesBound = false;
}
else if (!defaultBoneMatricesBound)
{
SetBoneMatrices(context, defaultBoneMatrices);
defaultBoneMatricesBound = true;
}
if (!model.UseTransform) return;
+71 -10
View File
@@ -57,12 +57,14 @@ namespace CodeWalker.Rendering
bool disposed = false;
VertexShader shadowvs;
VertexShader shadowvs_skin;
PixelShader shadowps;
GpuVarsBuffer<ShadowShaderVSSceneVars> VSSceneVars;
GpuVarsBuffer<ShadowShaderVSEntityVars> VSEntityVars;
GpuVarsBuffer<ShadowShaderVSModelVars> VSModelVars;
GpuVarsBuffer<ShadowShaderGeomVars> GeomVars;
GpuABuffer<Matrix3_s> BoneMatrices;
SamplerState texsampler;
SamplerState texsamplerc;
@@ -70,15 +72,20 @@ namespace CodeWalker.Rendering
public Vector4 WindVector { get; set; }
Matrix3_s[] defaultBoneMatrices;
bool defaultBoneMatricesBound = false;
private Dictionary<VertexType, InputLayout> layouts = new Dictionary<VertexType, InputLayout>();
public ShadowShader(Device device)
{
byte[] vsbytes = File.ReadAllBytes("Shaders\\ShadowVS.cso");
byte[] vssbytes = File.ReadAllBytes("Shaders\\ShadowVS_Skin.cso");
byte[] psbytes = File.ReadAllBytes("Shaders\\ShadowPS.cso");
shadowvs = new VertexShader(device, vsbytes);
shadowvs_skin = new VertexShader(device, vssbytes);
shadowps = new PixelShader(device, psbytes);
@@ -86,6 +93,7 @@ namespace CodeWalker.Rendering
VSEntityVars = new GpuVarsBuffer<ShadowShaderVSEntityVars>(device);
VSModelVars = new GpuVarsBuffer<ShadowShaderVSModelVars>(device);
GeomVars = new GpuVarsBuffer<ShadowShaderGeomVars>(device);
BoneMatrices = new GpuABuffer<Matrix3_s>(device, 255);
//supported layouts - requires Position, Normal, Colour, Texcoord
@@ -93,8 +101,6 @@ namespace CodeWalker.Rendering
layouts.Add(VertexType.DefaultEx, new InputLayout(device, vsbytes, VertexTypeDefaultEx.GetLayout()));
layouts.Add(VertexType.PNCCT, new InputLayout(device, vsbytes, VertexTypePNCCT.GetLayout()));
layouts.Add(VertexType.PNCCTTTT, new InputLayout(device, vsbytes, VertexTypePNCCTTTT.GetLayout()));
layouts.Add(VertexType.PBBNCCTTX, new InputLayout(device, vsbytes, VertexTypePBBNCCTTX.GetLayout()));
layouts.Add(VertexType.PBBNCCT, new InputLayout(device, vsbytes, VertexTypePBBNCCT.GetLayout()));
layouts.Add(VertexType.PNCTTTX, new InputLayout(device, vsbytes, VertexTypePNCTTTX.GetLayout()));
layouts.Add(VertexType.PNCTTTX_2, new InputLayout(device, vsbytes, VertexTypePNCTTTX_2.GetLayout()));
layouts.Add(VertexType.PNCTTTX_3, new InputLayout(device, vsbytes, VertexTypePNCTTTX_3.GetLayout()));
@@ -103,19 +109,25 @@ namespace CodeWalker.Rendering
layouts.Add(VertexType.PNCCTTX, new InputLayout(device, vsbytes, VertexTypePNCCTTX.GetLayout()));
layouts.Add(VertexType.PNCCTTX_2, new InputLayout(device, vsbytes, VertexTypePNCCTTX_2.GetLayout()));
layouts.Add(VertexType.PNCCTTTX, new InputLayout(device, vsbytes, VertexTypePNCCTTTX.GetLayout()));
layouts.Add(VertexType.PBBNCCTX, new InputLayout(device, vsbytes, VertexTypePBBNCCTX.GetLayout()));
layouts.Add(VertexType.PBBNCTX, new InputLayout(device, vsbytes, VertexTypePBBNCTX.GetLayout()));
layouts.Add(VertexType.PBBNCT, new InputLayout(device, vsbytes, VertexTypePBBNCT.GetLayout()));
layouts.Add(VertexType.PNCCTT, new InputLayout(device, vsbytes, VertexTypePNCCTT.GetLayout()));
layouts.Add(VertexType.PNCCTX, new InputLayout(device, vsbytes, VertexTypePNCCTX.GetLayout()));
layouts.Add(VertexType.PNCH2, new InputLayout(device, vsbytes, VertexTypePNCH2.GetLayout()));
layouts.Add(VertexType.PCCH2H4, new InputLayout(device, vsbytes, VertexTypePCCH2H4.GetLayout()));
layouts.Add(VertexType.PBBNCTT, new InputLayout(device, vsbytes, VertexTypePBBNCTT.GetLayout()));
layouts.Add(VertexType.PBBNCTTX, new InputLayout(device, vsbytes, VertexTypePBBNCTTX.GetLayout()));
layouts.Add(VertexType.PBBNCTTT, new InputLayout(device, vsbytes, VertexTypePBBNCTTT.GetLayout()));
layouts.Add(VertexType.PNCTT, new InputLayout(device, vsbytes, VertexTypePNCTT.GetLayout()));
layouts.Add(VertexType.PNCTTT, new InputLayout(device, vsbytes, VertexTypePNCTTT.GetLayout()));
layouts.Add(VertexType.PBBNCTTTX, new InputLayout(device, vsbytes, VertexTypePBBNCTTTX.GetLayout()));
layouts.Add(VertexType.PBBNCT, new InputLayout(device, vssbytes, VertexTypePBBNCT.GetLayout()));
layouts.Add(VertexType.PBBNCTX, new InputLayout(device, vssbytes, VertexTypePBBNCTX.GetLayout()));
layouts.Add(VertexType.PBBNCTT, new InputLayout(device, vssbytes, VertexTypePBBNCTT.GetLayout()));
layouts.Add(VertexType.PBBNCTTT, new InputLayout(device, vssbytes, VertexTypePBBNCTTT.GetLayout()));
layouts.Add(VertexType.PBBNCCT, new InputLayout(device, vssbytes, VertexTypePBBNCCT.GetLayout()));
layouts.Add(VertexType.PBBNCCTT, new InputLayout(device, vssbytes, VertexTypePBBNCCTT.GetLayout()));//TODO
layouts.Add(VertexType.PBBNCCTX, new InputLayout(device, vssbytes, VertexTypePBBNCCTX.GetLayout()));
layouts.Add(VertexType.PBBNCTTX, new InputLayout(device, vssbytes, VertexTypePBBNCTTX.GetLayout()));
layouts.Add(VertexType.PBBNCTTTX, new InputLayout(device, vssbytes, VertexTypePBBNCTTTX.GetLayout()));//TODO
layouts.Add(VertexType.PBBNCCTTX, new InputLayout(device, vssbytes, VertexTypePBBNCCTTX.GetLayout()));//TODO
//PBBCCT todo
//PBBNC todo
@@ -146,13 +158,22 @@ namespace CodeWalker.Rendering
MipLodBias = 0,
});
defaultBoneMatrices = new Matrix3_s[255];
for (int i = 0; i < 255; i++)
{
defaultBoneMatrices[i].Row1 = Vector4.UnitX;
defaultBoneMatrices[i].Row2 = Vector4.UnitY;
defaultBoneMatrices[i].Row3 = Vector4.UnitZ;
}
}
public override void SetShader(DeviceContext context)
{
context.VertexShader.Set(shadowvs);
context.PixelShader.Set(shadowps);
}
@@ -161,6 +182,26 @@ namespace CodeWalker.Rendering
InputLayout l;
if (layouts.TryGetValue(type, out l))
{
VertexShader vs = shadowvs;
switch (type)
{
case VertexType.PBBNCT:
case VertexType.PBBNCTX:
case VertexType.PBBNCTT:
case VertexType.PBBNCTTT:
case VertexType.PBBNCCT:
case VertexType.PBBNCCTT:
case VertexType.PBBNCCTX:
case VertexType.PBBNCTTX:
case VertexType.PBBNCTTTX:
case VertexType.PBBNCCTTX:
vs = shadowvs_skin;
break;
}
context.VertexShader.Set(vs);
context.InputAssembler.InputLayout = l;
return true;
}
@@ -192,6 +233,17 @@ namespace CodeWalker.Rendering
public override void SetModelVars(DeviceContext context, RenderableModel model)
{
if (model.Owner.BoneTransforms != null)
{
SetBoneMatrices(context, model.Owner.BoneTransforms);
defaultBoneMatricesBound = false;
}
else if (!defaultBoneMatricesBound)
{
SetBoneMatrices(context, defaultBoneMatrices);
defaultBoneMatricesBound = true;
}
if (!model.UseTransform) return;
VSModelVars.Vars.Transform = Matrix.Transpose(model.Transform);
VSModelVars.Update(context);
@@ -306,6 +358,13 @@ namespace CodeWalker.Rendering
}
}
public void SetBoneMatrices(DeviceContext context, Matrix3_s[] matrices)
{
BoneMatrices.Update(context, matrices);
BoneMatrices.SetVSCBuffer(context, 7);
}
public override void UnbindResources(DeviceContext context)
{
context.VertexShader.SetConstantBuffer(0, null);
@@ -341,10 +400,12 @@ namespace CodeWalker.Rendering
VSEntityVars.Dispose();
VSModelVars.Dispose();
GeomVars.Dispose();
BoneMatrices.Dispose();
shadowps.Dispose();
shadowvs.Dispose();
shadowvs_skin.Dispose();
disposed = true;
}