mirror of
https://github.com/4sval/FModel.git
synced 2026-04-16 22:46:09 -05:00
fu
This commit is contained in:
parent
abab1e427e
commit
e96a3b6d4d
|
|
@ -84,6 +84,14 @@ public partial class MainWindow
|
|||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "FortniteGame/Content/Animation/Game/MainPlayer/Emotes/Acrobatic_Superhero/Emote_AcrobaticSuperhero_CMM.uasset"));
|
||||
#endif
|
||||
#if DEBUG
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "Hk_project/Content/Character/Drone/Mesh/SKM_Drone.uasset"));
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "Hk_project/Content/Animation/DRONE/B12_TestSpin360.uasset"));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ layout (location = 9) in mat4 vInstanceMatrix;
|
|||
layout (location = 13) in vec3 vMorphTargetPos;
|
||||
layout (location = 14) in vec3 vMorphTargetTangent;
|
||||
|
||||
const int MAX_BONES = 140;
|
||||
//const int MAX_BONES = 140;
|
||||
|
||||
uniform mat4 uView;
|
||||
uniform mat4 uProjection;
|
||||
uniform float uMorphTime;
|
||||
uniform mat4 uFinalBonesMatrix[MAX_BONES];
|
||||
//uniform mat4 uFinalBonesMatrix[MAX_BONES];
|
||||
|
||||
out vec3 fPos;
|
||||
out vec3 fNormal;
|
||||
|
|
@ -29,23 +29,28 @@ out vec4 fColor;
|
|||
void main()
|
||||
{
|
||||
vec4 bindPos = vec4(mix(vPos, vMorphTargetPos, uMorphTime), 1.0);
|
||||
vec3 tangent = mix(vTangent, vMorphTargetTangent, uMorphTime);
|
||||
vec4 bindNormal = vec4(vNormal, 1.0);
|
||||
vec4 bindTangent = vec4(mix(vTangent, vMorphTargetTangent, uMorphTime), 1.0);
|
||||
|
||||
vec4 finalPos = vec4(0.0);
|
||||
vec4 weights = normalize(vBoneWeights);
|
||||
for(int i = 0 ; i < 4; i++)
|
||||
{
|
||||
int boneIndex = int(vBoneIds[i]);
|
||||
if(boneIndex < 0) break;
|
||||
|
||||
finalPos += inverse(uFinalBonesMatrix[boneIndex]) * bindPos * weights[i];
|
||||
}
|
||||
// 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 = mat3(transpose(inverse(vInstanceMatrix))) * vNormal;
|
||||
fTangent = mat3(transpose(inverse(vInstanceMatrix))) * tangent;
|
||||
fNormal = vec3(transpose(inverse(vInstanceMatrix)) * bindNormal);
|
||||
fTangent = vec3(transpose(inverse(vInstanceMatrix)) * bindTangent);
|
||||
fTexCoords = vTexCoords;
|
||||
fTexLayer = vTexLayer;
|
||||
fColor = vColor;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ public abstract class Light : IDisposable
|
|||
1f, 1f, 0f,
|
||||
1f, -1f, 0
|
||||
};
|
||||
public string Name;
|
||||
public readonly FGuid Model;
|
||||
public readonly Texture Icon;
|
||||
public Transform Transform;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using CUE4Parse_Conversion.Animations;
|
||||
using CUE4Parse.UE4.Assets.Exports.Animation;
|
||||
using CUE4Parse.UE4.Objects.Core.Math;
|
||||
|
||||
namespace FModel.Views.Snooper.Models.Animations;
|
||||
|
|
@ -10,53 +8,45 @@ namespace FModel.Views.Snooper.Models.Animations;
|
|||
public class Animation : IDisposable
|
||||
{
|
||||
public int CurrentTime;
|
||||
public float DeltaTime;
|
||||
public CAnimSet CurrentAnimation;
|
||||
public readonly int MaxTime;
|
||||
public readonly Transform[][] BoneTransforms;
|
||||
|
||||
public Animation(CAnimSet anim)
|
||||
public Animation(Skeleton skeleton, CAnimSet anim)
|
||||
{
|
||||
CurrentTime = 1;
|
||||
CurrentAnimation = anim;
|
||||
}
|
||||
CurrentTime = 0;
|
||||
|
||||
public Dictionary<int, Transform> CalculateBoneTransform(FMeshBoneInfo[] boneInfos, Dictionary<int, Transform> bonesTransformByIndex)
|
||||
{
|
||||
var ret = new Dictionary<int, Transform>();
|
||||
var sequence = CurrentAnimation.Sequences[0];
|
||||
for (int boneIndex = 0; boneIndex < boneInfos.Length; boneIndex++)
|
||||
var sequence = anim.Sequences[0];
|
||||
MaxTime = sequence.NumFrames - 1;
|
||||
BoneTransforms = new Transform[skeleton.BonesTransformByIndex.Count][];
|
||||
for (var boneIndex = 0; boneIndex < BoneTransforms.Length; boneIndex++)
|
||||
{
|
||||
var boneOrientation = FQuat.Identity;
|
||||
var bonePosition = FVector.ZeroVector;
|
||||
var boneScale = FVector.OneVector;
|
||||
sequence.Tracks[boneIndex].GetBonePosition(CurrentTime, sequence.NumFrames, false, ref bonePosition, ref boneOrientation);
|
||||
if (CurrentTime < sequence.Tracks[boneIndex].KeyScale.Length)
|
||||
boneScale = sequence.Tracks[boneIndex].KeyScale[CurrentTime];
|
||||
var parentIndex = skeleton.ReferenceSkeleton.FinalRefBoneInfo[boneIndex].ParentIndex;
|
||||
if (!skeleton.BonesTransformByIndex.TryGetValue(boneIndex, out var originalTransform))
|
||||
throw new ArgumentNullException("no transform for bone " + boneIndex);
|
||||
|
||||
if (!bonesTransformByIndex.TryGetValue(boneIndex, out var originalTransform))
|
||||
originalTransform = new Transform { Relation = Matrix4x4.Identity };
|
||||
var boneOrientation = originalTransform.Rotation;
|
||||
var bonePosition = originalTransform.Position;
|
||||
var boneScale = originalTransform.Scale;
|
||||
|
||||
if (!ret.TryGetValue(boneInfos[boneIndex].ParentIndex, out var parentTransform))
|
||||
parentTransform = new Transform { Relation = Matrix4x4.Identity };
|
||||
else boneOrientation.Conjugate();
|
||||
|
||||
var boneTransform = new Transform
|
||||
BoneTransforms[boneIndex] = new Transform[sequence.NumFrames];
|
||||
for (var frame = 0; frame < BoneTransforms[boneIndex].Length; frame++)
|
||||
{
|
||||
Relation = parentTransform.Matrix,
|
||||
Rotation = boneOrientation * originalTransform.Rotation * FQuat.Conjugate(boneOrientation),
|
||||
Position = bonePosition * Constants.SCALE_DOWN_RATIO,
|
||||
Scale = boneScale
|
||||
};
|
||||
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];
|
||||
|
||||
// boneTransform.Rotation = originalTransform.Rotation * FQuat.Conjugate(originalTransform.Rotation) * parentTransform.Rotation
|
||||
boneTransform.Position -= boneTransform.Position - originalTransform.Position;
|
||||
boneOrientation.W *= -1;
|
||||
bonePosition *= Constants.SCALE_DOWN_RATIO;
|
||||
|
||||
// boneTransform.Rotation = originalTransform.Rotation * (boneTransform.Rotation * FQuat.Conjugate(originalTransform.Rotation));
|
||||
// boneTransform.Position = originalTransform.Position + (boneTransform.Position - originalTransform.Position);
|
||||
|
||||
ret[boneIndex] = boneTransform;
|
||||
BoneTransforms[boneIndex][frame] = new Transform
|
||||
{
|
||||
Relation = parentIndex >= 0 ? BoneTransforms[parentIndex][frame].Matrix : originalTransform.Relation,
|
||||
Rotation = boneOrientation,
|
||||
Position = bonePosition,
|
||||
Scale = boneScale
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ public class Skeleton : IDisposable
|
|||
public readonly USkeleton UnrealSkeleton;
|
||||
public readonly FReferenceSkeleton ReferenceSkeleton;
|
||||
public readonly Dictionary<string, int> BonesIndexByName;
|
||||
public Dictionary<int, Transform> BonesTransformByIndex;
|
||||
public Dictionary<int, Transform> AnimBonesTransformByIndex;
|
||||
public readonly Dictionary<int, Transform> BonesTransformByIndex;
|
||||
public readonly bool IsLoaded;
|
||||
|
||||
public Animation Anim;
|
||||
|
|
@ -23,7 +22,6 @@ public class Skeleton : IDisposable
|
|||
{
|
||||
BonesIndexByName = new Dictionary<string, int>();
|
||||
BonesTransformByIndex = new Dictionary<int, Transform>();
|
||||
AnimBonesTransformByIndex = new Dictionary<int, Transform>();
|
||||
}
|
||||
|
||||
public Skeleton(FPackageIndex package, FReferenceSkeleton referenceSkeleton, Transform transform) : this()
|
||||
|
|
@ -32,14 +30,21 @@ public class Skeleton : IDisposable
|
|||
IsLoaded = UnrealSkeleton != null;
|
||||
if (!IsLoaded) return;
|
||||
|
||||
ReferenceSkeleton = referenceSkeleton ?? UnrealSkeleton.ReferenceSkeleton;
|
||||
ReferenceSkeleton = UnrealSkeleton.ReferenceSkeleton;
|
||||
foreach ((var name, var boneIndex) in ReferenceSkeleton.FinalNameToIndexMap)
|
||||
{
|
||||
if (!referenceSkeleton.FinalNameToIndexMap.TryGetValue(name, out var newBoneIndex))
|
||||
continue;
|
||||
|
||||
ReferenceSkeleton.FinalRefBonePose[boneIndex] = referenceSkeleton.FinalRefBonePose[newBoneIndex];
|
||||
}
|
||||
BonesIndexByName = ReferenceSkeleton.FinalNameToIndexMap;
|
||||
UpdateBoneMatrices(transform.Matrix);
|
||||
}
|
||||
|
||||
public void SetAnimation(CAnimSet anim)
|
||||
{
|
||||
Anim = new Animation(anim);
|
||||
Anim = new Animation(this, anim);
|
||||
}
|
||||
|
||||
public void UpdateBoneMatrices(Matrix4x4 matrix)
|
||||
|
|
@ -64,17 +69,16 @@ public class Skeleton : IDisposable
|
|||
parentTransform = new Transform { Relation = matrix };
|
||||
|
||||
boneTransform.Relation = parentTransform.Matrix;
|
||||
BonesTransformByIndex[boneIndex] = AnimBonesTransformByIndex[boneIndex] = boneTransform;
|
||||
BonesTransformByIndex[boneIndex] = boneTransform;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetUniform(Shader shader)
|
||||
{
|
||||
if (!IsLoaded || Anim == null) return;
|
||||
AnimBonesTransformByIndex = Anim.CalculateBoneTransform(ReferenceSkeleton.FinalRefBoneInfo, BonesTransformByIndex);
|
||||
foreach ((int boneIndex, Transform boneTransform) in AnimBonesTransformByIndex)
|
||||
for (int boneIndex = 0; boneIndex < Anim.BoneTransforms.Length; boneIndex++)
|
||||
{
|
||||
shader.SetUniform($"uFinalBonesMatrix[{boneIndex}]", boneTransform.Matrix);
|
||||
shader.SetUniform($"uFinalBonesMatrix[{boneIndex}]", Anim.BoneTransforms[boneIndex][Anim.CurrentTime].Matrix);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -230,10 +230,13 @@ public class Model : IDisposable
|
|||
public void UpdateMatrices(Options options)
|
||||
{
|
||||
UpdateMatrices();
|
||||
for (int i = 0; i < options.Lights.Count; i++)
|
||||
if (HasSkeleton && Skeleton.Anim != null)
|
||||
{
|
||||
options.Lights[i].Transform = Skeleton.AnimBonesTransformByIndex[i];
|
||||
options.Lights[i].UpdateMatrices();
|
||||
for (int i = 0; i < options.Lights.Count; i++)
|
||||
{
|
||||
options.Lights[i].Transform = Skeleton.Anim.BoneTransforms[i][Skeleton.Anim.CurrentTime];
|
||||
options.Lights[i].UpdateMatrices();
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var socket in Sockets)
|
||||
|
|
|
|||
|
|
@ -178,10 +178,12 @@ public class Renderer : IDisposable
|
|||
if (Options.Models.ContainsKey(guid) || !original.TryConvert(out var mesh)) return;
|
||||
|
||||
Options.Models[guid] = new Model(original, mesh);
|
||||
foreach (var transform in Options.Models[guid].Skeleton.BonesTransformByIndex.Values)
|
||||
foreach ((var name, var index) in Options.Models[guid].Skeleton.BonesIndexByName)
|
||||
{
|
||||
if (!Options.Models[guid].Skeleton.BonesTransformByIndex.TryGetValue(index, out var transform)) continue;
|
||||
|
||||
Options.Lights.Add(
|
||||
new PointLight(guid, Options.Icons["pointlight"], original, original, transform));
|
||||
new PointLight(guid, Options.Icons["pointlight"], original, original, transform) { Name = name});
|
||||
}
|
||||
Options.SelectModel(guid);
|
||||
SetupCamera(Options.Models[guid].Box);
|
||||
|
|
|
|||
|
|
@ -159,9 +159,7 @@ public class SnimGui
|
|||
for (int i = 0; i < s.Renderer.Options.Lights.Count; i++)
|
||||
{
|
||||
var light = s.Renderer.Options.Lights[i];
|
||||
var id = s.Renderer.Options.TryGetModel(light.Model, out var lightModel) ? lightModel.Name : "None";
|
||||
|
||||
id += $"##{i}";
|
||||
var id = $"{light.Name}##{i}";
|
||||
if (ImGui.TreeNode(id) && ImGui.BeginTable(id, 2))
|
||||
{
|
||||
s.Renderer.Options.SelectModel(light.Model);
|
||||
|
|
@ -448,7 +446,7 @@ Snooper aims to give an accurate preview of models, materials, skeletal animatio
|
|||
{
|
||||
if (model.Skeleton.Anim != null)
|
||||
{
|
||||
ImGui.DragInt("Time", ref model.Skeleton.Anim.CurrentTime, 1, 0, 110);
|
||||
ImGui.DragInt("Time", ref model.Skeleton.Anim.CurrentTime, 1, 0, model.Skeleton.Anim.MaxTime);
|
||||
}
|
||||
Layout("Skeleton");ImGui.Text($" : {model.Skeleton.UnrealSkeleton.Name}");
|
||||
Layout("Bones");ImGui.Text($" : x{model.Skeleton.UnrealSkeleton.BoneTree.Length}");
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user