Skip to content

Commit

Permalink
some animations work, others do not, awaiting improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
4sval committed Feb 4, 2023
1 parent bbda1c5 commit f36a7b7
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 79 deletions.
1 change: 1 addition & 0 deletions FModel/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public static class Constants

public const float SCALE_DOWN_RATIO = 0.01F;
public const int SAMPLES_COUNT = 4;
public const int MAX_BONE_UNIFORM = 250;

public const string WHITE = "#DAE5F2";
public const string GRAY = "#BBBBBB";
Expand Down
44 changes: 22 additions & 22 deletions FModel/Resources/default.vert
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,10 @@ layout (location = 9) in mat4 vInstanceMatrix;
layout (location = 13) in vec3 vMorphTargetPos;
layout (location = 14) in vec3 vMorphTargetTangent;

//const int MAX_BONES = 140;

uniform mat4 uView;
uniform mat4 uProjection;
uniform float uMorphTime;
//uniform mat4 uFinalBonesMatrix[MAX_BONES];
uniform mat4 uFinalBonesMatrix[250];

out vec3 fPos;
out vec3 fNormal;
Expand All @@ -32,25 +30,27 @@ void main()
vec4 bindNormal = vec4(vNormal, 1.0);
vec4 bindTangent = vec4(mix(vTangent, vMorphTargetTangent, uMorphTime), 1.0);

// vec4 finalPos = vec4(0.0);
// vec4 finalNormal = vec4(0.0);
// vec4 finalTangent = vec4(0.0);
// vec4 weights = normalize(vBoneWeights);
// for(int i = 0 ; i < 4; i++)
// {
// int boneIndex = int(vBoneIds[i]);
// if(boneIndex < 0) break;
//
// finalPos += uFinalBonesMatrix[boneIndex] * bindPos * weights[i];
// finalNormal += uFinalBonesMatrix[boneIndex] * bindNormal * weights[i];
// finalTangent += uFinalBonesMatrix[boneIndex] * bindTangent * weights[i];
// }

gl_Position = uProjection * uView * vInstanceMatrix * bindPos;

fPos = vec3(vInstanceMatrix * bindPos);
fNormal = vec3(transpose(inverse(vInstanceMatrix)) * bindNormal);
fTangent = vec3(transpose(inverse(vInstanceMatrix)) * bindTangent);
vec4 finalPos = vec4(0.0);
vec4 finalNormal = vec4(0.0);
vec4 finalTangent = vec4(0.0);
for(int i = 0 ; i < 4; i++)
{
int boneIndex = int(vBoneIds[i]);
if(boneIndex < 0) break;

mat4 boneMatrix = uFinalBonesMatrix[boneIndex];
float weight = vBoneWeights[i];

finalPos += boneMatrix * bindPos * weight;
finalNormal += boneMatrix * bindNormal * weight;
finalTangent += boneMatrix * bindTangent * weight;
}

gl_Position = uProjection * uView * vInstanceMatrix * finalPos;

fPos = vec3(vInstanceMatrix * finalPos);
fNormal = vec3(transpose(inverse(vInstanceMatrix)) * finalNormal);
fTangent = vec3(transpose(inverse(vInstanceMatrix)) * finalTangent);
fTexCoords = vTexCoords;
fTexLayer = vTexLayer;
fColor = vColor;
Expand Down
26 changes: 23 additions & 3 deletions FModel/Resources/outline.vert
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,38 @@

layout (location = 1) in vec3 vPos;
layout (location = 2) in vec3 vNormal;
layout (location = 7) in vec4 vBoneIds;
layout (location = 8) in vec4 vBoneWeights;
layout (location = 9) in mat4 vInstanceMatrix;
layout (location = 13) in vec3 vMorphTarget;
layout (location = 13) in vec3 vMorphTargetPos;

uniform mat4 uView;
uniform vec3 uViewPos;
uniform mat4 uProjection;
uniform float uMorphTime;
uniform mat4 uFinalBonesMatrix[250];

void main()
{
vec3 pos = vec3(vInstanceMatrix * vec4(mix(vPos, vMorphTarget, uMorphTime), 1.0));
vec3 nor = mat3(transpose(inverse(vInstanceMatrix))) * vNormal;
vec4 bindPos = vec4(mix(vPos, vMorphTargetPos, uMorphTime), 1.0);
vec4 bindNormal = vec4(vNormal, 1.0);

vec4 finalPos = vec4(0.0);
vec4 finalNormal = vec4(0.0);
for(int i = 0 ; i < 4; i++)
{
int boneIndex = int(vBoneIds[i]);
if(boneIndex < 0) break;

mat4 boneMatrix = uFinalBonesMatrix[boneIndex];
float weight = vBoneWeights[i];

finalPos += boneMatrix * bindPos * weight;
finalNormal += boneMatrix * bindNormal * weight;
}

vec3 pos = vec3(vInstanceMatrix * finalPos);
vec3 nor = vec3(transpose(inverse(vInstanceMatrix)) * finalNormal);

float scaleFactor = distance(pos, uViewPos) * 0.0025;
vec3 scaleVertex = pos + nor * scaleFactor;
Expand Down
33 changes: 21 additions & 12 deletions FModel/Views/Snooper/Models/Animations/Animation.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.Numerics;
using CUE4Parse_Conversion.Animations;
using CUE4Parse.UE4.Objects.Core.Math;

namespace FModel.Views.Snooper.Models.Animations;

Expand All @@ -15,30 +17,37 @@ public Animation(Skeleton skeleton, CAnimSet anim)

var sequence = anim.Sequences[0];
MaxTime = sequence.NumFrames - 1;
BoneTransforms = new Transform[skeleton.BonesTransformByIndex.Count][];
for (var boneIndex = 0; boneIndex < BoneTransforms.Length; boneIndex++)
BoneTransforms = new Transform[skeleton.UnrealSkeleton.ReferenceSkeleton.FinalRefBoneInfo.Length][];
for (var trackIndex = 0; trackIndex < BoneTransforms.Length; trackIndex++)
{
var parentIndex = skeleton.ReferenceSkeleton.FinalRefBoneInfo[boneIndex].ParentIndex;
var bone = skeleton.UnrealSkeleton.ReferenceSkeleton.FinalRefBoneInfo[trackIndex];
if (!skeleton.BonesIndexByLoweredName.TryGetValue(bone.Name.Text.ToLower(), out var boneIndex))
{
BoneTransforms[trackIndex] = new Transform[sequence.NumFrames];
continue;
}
if (!skeleton.BonesTransformByIndex.TryGetValue(boneIndex, out var originalTransform))
throw new ArgumentNullException("no transform for bone " + boneIndex);
throw new ArgumentNullException($"no transform for bone '{boneIndex}'");

var boneOrientation = originalTransform.Rotation;
var bonePosition = originalTransform.Position;
var boneScale = originalTransform.Scale;

BoneTransforms[boneIndex] = new Transform[sequence.NumFrames];
for (var frame = 0; frame < BoneTransforms[boneIndex].Length; frame++)
BoneTransforms[trackIndex] = new Transform[sequence.NumFrames];
for (var frame = 0; frame < BoneTransforms[trackIndex].Length; frame++)
{
sequence.Tracks[boneIndex].GetBonePosition(frame, sequence.NumFrames, false, ref bonePosition, ref boneOrientation);
if (CurrentTime < sequence.Tracks[boneIndex].KeyScale.Length)
boneScale = sequence.Tracks[boneIndex].KeyScale[CurrentTime];
sequence.Tracks[trackIndex].GetBonePosition(frame, sequence.NumFrames, false, ref bonePosition, ref boneOrientation);
if (CurrentTime < sequence.Tracks[trackIndex].KeyScale.Length)
boneScale = sequence.Tracks[trackIndex].KeyScale[CurrentTime];

// revert FixRotationKeys
if (trackIndex > 0) boneOrientation.Conjugate();

boneOrientation.W *= -1;
bonePosition *= Constants.SCALE_DOWN_RATIO;

BoneTransforms[boneIndex][frame] = new Transform
BoneTransforms[trackIndex][frame] = new Transform
{
Relation = parentIndex >= 0 ? BoneTransforms[parentIndex][frame].Matrix : originalTransform.Relation,
Relation = bone.ParentIndex >= 0 ? BoneTransforms[bone.ParentIndex][frame].Matrix : originalTransform.Relation,
Rotation = boneOrientation,
Position = bonePosition,
Scale = boneScale
Expand Down
49 changes: 34 additions & 15 deletions FModel/Views/Snooper/Models/Animations/Skeleton.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ public class Skeleton : IDisposable
{
public readonly USkeleton UnrealSkeleton;
public readonly FReferenceSkeleton ReferenceSkeleton;
public readonly Dictionary<string, int> BonesIndexByName;
public readonly Dictionary<string, int> BonesIndexByLoweredName;
public readonly Dictionary<int, Transform> BonesTransformByIndex;
public readonly Dictionary<int, Matrix4x4> InvertedBonesMatrixByIndex;
public readonly bool IsLoaded;

public Animation Anim;

public Skeleton()
{
BonesIndexByName = new Dictionary<string, int>();
BonesIndexByLoweredName = new Dictionary<string, int>();
BonesTransformByIndex = new Dictionary<int, Transform>();
InvertedBonesMatrixByIndex = new Dictionary<int, Matrix4x4>();
}

public Skeleton(FPackageIndex package, FReferenceSkeleton referenceSkeleton, Transform transform) : this()
Expand All @@ -30,15 +32,10 @@ public Skeleton(FPackageIndex package, FReferenceSkeleton referenceSkeleton, Tra
IsLoaded = UnrealSkeleton != null;
if (!IsLoaded) return;

ReferenceSkeleton = UnrealSkeleton.ReferenceSkeleton;
foreach ((var name, var boneIndex) in ReferenceSkeleton.FinalNameToIndexMap)
{
if (!referenceSkeleton.FinalNameToIndexMap.TryGetValue(name, out var newBoneIndex))
continue;
ReferenceSkeleton = referenceSkeleton;
foreach ((var name, var boneIndex) in referenceSkeleton.FinalNameToIndexMap)
BonesIndexByLoweredName[name.ToLower()] = boneIndex;

ReferenceSkeleton.FinalRefBonePose[boneIndex] = referenceSkeleton.FinalRefBonePose[newBoneIndex];
}
BonesIndexByName = ReferenceSkeleton.FinalNameToIndexMap;
UpdateBoneMatrices(transform.Matrix);
}

Expand All @@ -50,7 +47,7 @@ public void SetAnimation(CAnimSet anim)
public void UpdateBoneMatrices(Matrix4x4 matrix)
{
if (!IsLoaded) return;
foreach (var boneIndex in BonesIndexByName.Values)
foreach (var boneIndex in BonesIndexByLoweredName.Values)
{
var bone = ReferenceSkeleton.FinalRefBonePose[boneIndex];
var parentIndex = ReferenceSkeleton.FinalRefBoneInfo[boneIndex].ParentIndex;
Expand All @@ -69,22 +66,44 @@ public void UpdateBoneMatrices(Matrix4x4 matrix)
parentTransform = new Transform { Relation = matrix };

boneTransform.Relation = parentTransform.Matrix;
Matrix4x4.Invert(boneTransform.Matrix, out var inverted);

BonesTransformByIndex[boneIndex] = boneTransform;
InvertedBonesMatrixByIndex[boneIndex] = inverted;
}
}

public void SetPoseUniform(Shader shader)
{
if (!IsLoaded) return;
foreach ((var boneIndex, var transform) in BonesTransformByIndex)
{
if (boneIndex >= Constants.MAX_BONE_UNIFORM)
break;
shader.SetUniform($"uFinalBonesMatrix[{boneIndex}]", InvertedBonesMatrixByIndex[boneIndex] * transform.Matrix);
}
}

public void SetUniform(Shader shader)
{
if (!IsLoaded || Anim == null) return;
for (int boneIndex = 0; boneIndex < Anim.BoneTransforms.Length; boneIndex++)
if (!IsLoaded) return;
if (Anim == null) SetPoseUniform(shader);
else foreach ((var boneName, var trackIndex) in UnrealSkeleton.ReferenceSkeleton.FinalNameToIndexMap)
{
shader.SetUniform($"uFinalBonesMatrix[{boneIndex}]", Anim.BoneTransforms[boneIndex][Anim.CurrentTime].Matrix);
if (!BonesIndexByLoweredName.TryGetValue(boneName.ToLower(), out var boneIndex))
continue;
if (!InvertedBonesMatrixByIndex.TryGetValue(boneIndex, out var invertMatrix))
throw new ArgumentNullException($"no inverse matrix for bone '{boneIndex}'");
if (boneIndex >= Constants.MAX_BONE_UNIFORM)
break;

shader.SetUniform($"uFinalBonesMatrix[{boneIndex}]", invertMatrix * Anim.BoneTransforms[trackIndex][Anim.CurrentTime].Matrix);
}
}

public void Dispose()
{
BonesIndexByName.Clear();
BonesIndexByLoweredName.Clear();
BonesTransformByIndex.Clear();
Anim?.Dispose();
}
Expand Down
Loading

0 comments on commit f36a7b7

Please sign in to comment.