mirror of
https://github.com/4sval/FModel.git
synced 2026-03-21 17:24:26 -05:00
cleaned skeleton and bones
This commit is contained in:
parent
39f5855b12
commit
26e92238ba
|
|
@ -1 +1 @@
|
|||
Subproject commit 04239c2e1f7fd257c6671a0bb52a7896c0232930
|
||||
Subproject commit d0a849608247dbdcb14b9b6e6851addd761f3c73
|
||||
|
|
@ -76,19 +76,12 @@ public partial class MainWindow
|
|||
_discordHandler.Initialize(_applicationView.CUE4Parse.Provider.GameName);
|
||||
|
||||
#if DEBUG
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "ShooterGame/Content/Characters/_Core/3P/Models/TP_Core_NewMale_Skelmesh.uasset"));
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "Game/Characters/_Core/3P/Anims/TP_Core_SprintAddN_UB.uasset"));
|
||||
//
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "ShooterGame/Content/Characters/Guide/S0/1P/Models/FP_Guide_S0_Skelmesh.uasset"));
|
||||
// await _threadWorkerView.Begin(cancellationToken =>
|
||||
// _applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
// "/Game/Equippables/Guns/SniperRifles/Boltsniper/S0/1P/Anims/FP_Core_Boltsniper_S0_Fire.uasset"));
|
||||
await _threadWorkerView.Begin(cancellationToken =>
|
||||
_applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
"ShooterGame/Content/Characters/BountyHunter/S0/Ability_4/1P/Models/AB_BountyHunter_S0_4_TrailCreature_Skelmesh.uasset"));
|
||||
await _threadWorkerView.Begin(cancellationToken =>
|
||||
_applicationView.CUE4Parse.Extract(cancellationToken,
|
||||
"ShooterGame/Content/Characters/BountyHunter/S0/Ability_4/1P/Anims/FP_BountyHunter_S0_4_Aim_S.uasset"));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using System.Text.RegularExpressions;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
using AdonisUI.Controls;
|
||||
using CUE4Parse.Encryption.Aes;
|
||||
using CUE4Parse.FileProvider;
|
||||
|
|
@ -41,7 +40,6 @@ using FModel.Settings;
|
|||
using FModel.Views;
|
||||
using FModel.Views.Resources.Controls;
|
||||
using FModel.Views.Snooper;
|
||||
using ImGuiNET;
|
||||
using Newtonsoft.Json;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
using OpenTK.Windowing.Common;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using FModel.Framework;
|
||||
using FModel.Services;
|
||||
|
||||
|
|
@ -28,6 +29,7 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
|
|||
case "Assets_Extract_New_Tab":
|
||||
foreach (var asset in assetItems)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, true);
|
||||
}
|
||||
|
|
@ -35,6 +37,7 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
|
|||
case "Assets_Export_Data":
|
||||
foreach (var asset in assetItems)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
contextViewModel.CUE4Parse.ExportData(asset.FullPath);
|
||||
}
|
||||
|
|
@ -42,6 +45,7 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
|
|||
case "Assets_Save_Properties":
|
||||
foreach (var asset in assetItems)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Properties);
|
||||
}
|
||||
|
|
@ -49,6 +53,7 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
|
|||
case "Assets_Save_Textures":
|
||||
foreach (var asset in assetItems)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Textures);
|
||||
}
|
||||
|
|
@ -56,6 +61,7 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
|
|||
case "Assets_Save_Models":
|
||||
foreach (var asset in assetItems)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Meshes | EBulkType.Auto);
|
||||
}
|
||||
|
|
@ -63,6 +69,7 @@ public class RightClickMenuCommand : ViewModelCommand<ApplicationViewModel>
|
|||
case "Assets_Save_Animations":
|
||||
foreach (var asset in assetItems)
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
contextViewModel.CUE4Parse.Extract(cancellationToken, asset.FullPath, false, EBulkType.Animations | EBulkType.Auto);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using FModel.ViewModels.Commands;
|
|||
using FModel.Views.Resources.Controls;
|
||||
using ICSharpCode.AvalonEdit.Document;
|
||||
using ICSharpCode.AvalonEdit.Highlighting;
|
||||
using Microsoft.Win32;
|
||||
using Serilog;
|
||||
using SkiaSharp;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -17,7 +16,6 @@ using System.Windows;
|
|||
using System.Windows.Media.Imaging;
|
||||
using CUE4Parse.UE4.Assets.Exports.Texture;
|
||||
using CUE4Parse_Conversion.Textures;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
|
||||
namespace FModel.ViewModels;
|
||||
|
||||
|
|
|
|||
25
FModel/Views/Snooper/Animations/Bone.cs
Normal file
25
FModel/Views/Snooper/Animations/Bone.cs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
namespace FModel.Views.Snooper.Animations;
|
||||
|
||||
public class Bone
|
||||
{
|
||||
public readonly int Index;
|
||||
public readonly int ParentIndex;
|
||||
public readonly Transform Rest;
|
||||
public string LoweredParentName;
|
||||
|
||||
public int SkeletonIndex = -1;
|
||||
public bool[] IsAnimated;
|
||||
|
||||
public Bone(int i, int p, Transform t)
|
||||
{
|
||||
Index = i;
|
||||
ParentIndex = p;
|
||||
Rest = t;
|
||||
}
|
||||
|
||||
public bool IsRoot => Index == 0 && ParentIndex == -1 && string.IsNullOrEmpty(LoweredParentName);
|
||||
public bool IsMapped => SkeletonIndex > -1;
|
||||
public bool IsNative => Index == SkeletonIndex;
|
||||
|
||||
public override string ToString() => $"Mesh Ref '{Index}' is Skel Ref '{SkeletonIndex}' ({IsNative})";
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
namespace FModel.Views.Snooper.Animations;
|
||||
|
||||
public class BoneIndice
|
||||
{
|
||||
public int BoneIndex = -1;
|
||||
public int ParentBoneIndex = -1;
|
||||
public string LoweredParentBoneName;
|
||||
public bool IsRoot => BoneIndex == 0 && ParentBoneIndex == -1 && string.IsNullOrEmpty(LoweredParentBoneName);
|
||||
|
||||
public int TrackedBoneIndex = -1;
|
||||
public int TrackedParentBoneIndex = -1; // bone index of the first tracked parent bone
|
||||
public bool IsTracked => TrackedBoneIndex > -1;
|
||||
public bool IsParentTracked => TrackedParentBoneIndex > -1;
|
||||
|
||||
public bool IsNative => BoneIndex == TrackedBoneIndex;
|
||||
public bool IsParentNative => ParentBoneIndex == TrackedParentBoneIndex; // always true?
|
||||
|
||||
public override string ToString() => $"Mesh Ref '{BoneIndex}' is Skel Ref '{TrackedBoneIndex}' ({IsNative}, {IsParentNative})";
|
||||
}
|
||||
|
|
@ -16,8 +16,7 @@ public class Skeleton : IDisposable
|
|||
private BufferObject<Matrix4x4> _ssbo;
|
||||
|
||||
public string Name;
|
||||
public readonly Dictionary<string, BoneIndice> BonesIndicesByLoweredName;
|
||||
public readonly Dictionary<int, Transform> BonesTransformByIndex;
|
||||
public readonly Dictionary<string, Bone> BonesByLoweredName;
|
||||
|
||||
private int _previousAnimationSequence;
|
||||
private int _previousSequenceFrame;
|
||||
|
|
@ -28,48 +27,36 @@ public class Skeleton : IDisposable
|
|||
|
||||
public Skeleton()
|
||||
{
|
||||
BonesIndicesByLoweredName = new Dictionary<string, BoneIndice>();
|
||||
BonesTransformByIndex = new Dictionary<int, Transform>();
|
||||
BonesByLoweredName = new Dictionary<string, Bone>();
|
||||
_animatedBonesTransform = Array.Empty<Transform[][]>();
|
||||
_invertedBonesMatrix = Array.Empty<Matrix4x4>();
|
||||
}
|
||||
|
||||
public Skeleton(FReferenceSkeleton referenceSkeleton) : this()
|
||||
{
|
||||
for (int boneIndex = 0; boneIndex < referenceSkeleton.FinalRefBoneInfo.Length; boneIndex++)
|
||||
_invertedBonesMatrix = new Matrix4x4[referenceSkeleton.FinalRefBoneInfo.Length];
|
||||
for (int boneIndex = 0; boneIndex < _invertedBonesMatrix.Length; boneIndex++)
|
||||
{
|
||||
var info = referenceSkeleton.FinalRefBoneInfo[boneIndex];
|
||||
|
||||
var boneIndices = new BoneIndice { BoneIndex = boneIndex, ParentBoneIndex = info.ParentIndex };
|
||||
if (!boneIndices.IsRoot)
|
||||
boneIndices.LoweredParentBoneName =
|
||||
referenceSkeleton.FinalRefBoneInfo[boneIndices.ParentBoneIndex].Name.Text.ToLower();
|
||||
|
||||
BonesIndicesByLoweredName[info.Name.Text.ToLower()] = boneIndices;
|
||||
}
|
||||
|
||||
_invertedBonesMatrix = new Matrix4x4[BonesIndicesByLoweredName.Count];
|
||||
foreach (var boneIndices in BonesIndicesByLoweredName.Values)
|
||||
{
|
||||
var bone = referenceSkeleton.FinalRefBonePose[boneIndices.BoneIndex];
|
||||
if (!BonesTransformByIndex.TryGetValue(boneIndices.BoneIndex, out var boneTransform))
|
||||
var boneTransform = new Transform
|
||||
{
|
||||
boneTransform = new Transform
|
||||
{
|
||||
Rotation = bone.Rotation,
|
||||
Position = bone.Translation * Constants.SCALE_DOWN_RATIO,
|
||||
Scale = bone.Scale3D
|
||||
};
|
||||
Rotation = referenceSkeleton.FinalRefBonePose[boneIndex].Rotation,
|
||||
Position = referenceSkeleton.FinalRefBonePose[boneIndex].Translation * Constants.SCALE_DOWN_RATIO,
|
||||
Scale = referenceSkeleton.FinalRefBonePose[boneIndex].Scale3D
|
||||
};
|
||||
|
||||
var bone = new Bone(boneIndex, info.ParentIndex, boneTransform);
|
||||
if (!bone.IsRoot)
|
||||
{
|
||||
bone.LoweredParentName =
|
||||
referenceSkeleton.FinalRefBoneInfo[bone.ParentIndex].Name.Text.ToLower();
|
||||
bone.Rest.Relation = BonesByLoweredName[bone.LoweredParentName].Rest.Matrix;
|
||||
}
|
||||
|
||||
if (!BonesTransformByIndex.TryGetValue(boneIndices.ParentBoneIndex, out var parentTransform))
|
||||
parentTransform = new Transform { Relation = Matrix4x4.Identity };
|
||||
BonesByLoweredName[info.Name.Text.ToLower()] = bone;
|
||||
|
||||
boneTransform.Relation = parentTransform.Matrix;
|
||||
Matrix4x4.Invert(boneTransform.Matrix, out var inverted);
|
||||
|
||||
BonesTransformByIndex[boneIndices.BoneIndex] = boneTransform;
|
||||
_invertedBonesMatrix[boneIndices.BoneIndex] = inverted;
|
||||
_invertedBonesMatrix[bone.Index] = inverted;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -82,48 +69,47 @@ public class Skeleton : IDisposable
|
|||
{
|
||||
var sequence = anim.Sequences[s];
|
||||
_animatedBonesTransform[s] = new Transform[BoneCount][];
|
||||
foreach (var boneIndices in BonesIndicesByLoweredName.Values)
|
||||
foreach (var bone in BonesByLoweredName.Values)
|
||||
{
|
||||
var originalTransform = BonesTransformByIndex[boneIndices.BoneIndex];
|
||||
_animatedBonesTransform[s][boneIndices.BoneIndex] = new Transform[sequence.NumFrames];
|
||||
_animatedBonesTransform[s][bone.Index] = new Transform[sequence.NumFrames];
|
||||
|
||||
var trackedBoneIndex = boneIndices.TrackedBoneIndex;
|
||||
if (sequence.OriginalSequence.FindTrackForBoneIndex(trackedBoneIndex) < 0)
|
||||
var skeletonBoneIndex = bone.SkeletonIndex;
|
||||
bone.IsAnimated[s] = sequence.OriginalSequence.FindTrackForBoneIndex(skeletonBoneIndex) >= 0;
|
||||
if (!bone.IsAnimated[s])
|
||||
{
|
||||
for (int frame = 0; frame < _animatedBonesTransform[s][boneIndices.BoneIndex].Length; frame++)
|
||||
for (int frame = 0; frame < _animatedBonesTransform[s][bone.Index].Length; frame++)
|
||||
{
|
||||
_animatedBonesTransform[s][boneIndices.BoneIndex][frame] = new Transform
|
||||
_animatedBonesTransform[s][bone.Index][frame] = new Transform
|
||||
{
|
||||
Relation = boneIndices.IsParentTracked ?
|
||||
originalTransform.LocalMatrix * _animatedBonesTransform[s][boneIndices.TrackedParentBoneIndex][frame].Matrix :
|
||||
originalTransform.Relation
|
||||
Relation = bone.IsRoot ? bone.Rest.Relation :
|
||||
bone.Rest.LocalMatrix * _animatedBonesTransform[s][bone.ParentIndex][frame].Matrix
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int frame = 0; frame < _animatedBonesTransform[s][boneIndices.BoneIndex].Length; frame++)
|
||||
for (int frame = 0; frame < _animatedBonesTransform[s][bone.Index].Length; frame++)
|
||||
{
|
||||
var boneOrientation = originalTransform.Rotation;
|
||||
var bonePosition = originalTransform.Position;
|
||||
var boneScale = originalTransform.Scale;
|
||||
var boneOrientation = bone.Rest.Rotation;
|
||||
var bonePosition = bone.Rest.Position;
|
||||
var boneScale = bone.Rest.Scale;
|
||||
|
||||
sequence.Tracks[trackedBoneIndex].GetBoneTransform(frame, sequence.NumFrames, ref boneOrientation, ref bonePosition, ref boneScale);
|
||||
sequence.Tracks[skeletonBoneIndex].GetBoneTransform(frame, sequence.NumFrames, ref boneOrientation, ref bonePosition, ref boneScale);
|
||||
|
||||
switch (anim.Skeleton.BoneTree[trackedBoneIndex])
|
||||
switch (anim.Skeleton.BoneTree[skeletonBoneIndex])
|
||||
{
|
||||
case EBoneTranslationRetargetingMode.Skeleton when !rotationOnly:
|
||||
{
|
||||
var targetTransform = sequence.RetargetBasePose?[trackedBoneIndex] ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[trackedBoneIndex];
|
||||
var targetTransform = sequence.RetargetBasePose?[skeletonBoneIndex] ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[skeletonBoneIndex];
|
||||
bonePosition = targetTransform.Translation;
|
||||
break;
|
||||
}
|
||||
case EBoneTranslationRetargetingMode.AnimationScaled when !rotationOnly:
|
||||
{
|
||||
var sourceTranslationLength = (originalTransform.Position / Constants.SCALE_DOWN_RATIO).Size();
|
||||
var sourceTranslationLength = (bone.Rest.Position / Constants.SCALE_DOWN_RATIO).Size();
|
||||
if (sourceTranslationLength > UnrealMath.KindaSmallNumber)
|
||||
{
|
||||
var targetTranslationLength = sequence.RetargetBasePose?[trackedBoneIndex].Translation.Size() ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[trackedBoneIndex].Translation.Size();
|
||||
var targetTranslationLength = sequence.RetargetBasePose?[skeletonBoneIndex].Translation.Size() ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[skeletonBoneIndex].Translation.Size();
|
||||
bonePosition.Scale(targetTranslationLength / sourceTranslationLength);
|
||||
}
|
||||
break;
|
||||
|
|
@ -131,19 +117,19 @@ public class Skeleton : IDisposable
|
|||
case EBoneTranslationRetargetingMode.AnimationRelative when !rotationOnly:
|
||||
{
|
||||
// can't tell if it's working or not
|
||||
var sourceSkelTrans = originalTransform.Position / Constants.SCALE_DOWN_RATIO;
|
||||
var refPoseTransform = sequence.RetargetBasePose?[trackedBoneIndex] ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[trackedBoneIndex];
|
||||
var sourceSkelTrans = bone.Rest.Position / Constants.SCALE_DOWN_RATIO;
|
||||
var refPoseTransform = sequence.RetargetBasePose?[skeletonBoneIndex] ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[skeletonBoneIndex];
|
||||
|
||||
boneOrientation = boneOrientation * FQuat.Conjugate(originalTransform.Rotation) * refPoseTransform.Rotation;
|
||||
boneOrientation = boneOrientation * FQuat.Conjugate(bone.Rest.Rotation) * refPoseTransform.Rotation;
|
||||
bonePosition += refPoseTransform.Translation - sourceSkelTrans;
|
||||
boneScale *= refPoseTransform.Scale3D * originalTransform.Scale;
|
||||
boneScale *= refPoseTransform.Scale3D * bone.Rest.Scale;
|
||||
boneOrientation.Normalize();
|
||||
break;
|
||||
}
|
||||
case EBoneTranslationRetargetingMode.OrientAndScale when !rotationOnly:
|
||||
{
|
||||
var sourceSkelTrans = originalTransform.Position / Constants.SCALE_DOWN_RATIO;
|
||||
var targetSkelTrans = sequence.RetargetBasePose?[trackedBoneIndex].Translation ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[trackedBoneIndex].Translation;
|
||||
var sourceSkelTrans = bone.Rest.Position / Constants.SCALE_DOWN_RATIO;
|
||||
var targetSkelTrans = sequence.RetargetBasePose?[skeletonBoneIndex].Translation ?? anim.Skeleton.ReferenceSkeleton.FinalRefBonePose[skeletonBoneIndex].Translation;
|
||||
|
||||
if (!sourceSkelTrans.Equals(targetSkelTrans))
|
||||
{
|
||||
|
|
@ -163,11 +149,11 @@ public class Skeleton : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
_animatedBonesTransform[s][boneIndices.BoneIndex][frame] = new Transform
|
||||
_animatedBonesTransform[s][bone.Index][frame] = new Transform
|
||||
{
|
||||
Relation = boneIndices.IsParentTracked ? _animatedBonesTransform[s][boneIndices.TrackedParentBoneIndex][frame].Matrix : originalTransform.Relation,
|
||||
Relation = bone.IsRoot ? bone.Rest.Relation : _animatedBonesTransform[s][bone.ParentIndex][frame].Matrix,
|
||||
Rotation = boneOrientation,
|
||||
Position = rotationOnly ? originalTransform.Position : bonePosition * Constants.SCALE_DOWN_RATIO,
|
||||
Position = rotationOnly ? bone.Rest.Position : bonePosition * Constants.SCALE_DOWN_RATIO,
|
||||
Scale = boneScale
|
||||
};
|
||||
}
|
||||
|
|
@ -180,53 +166,35 @@ public class Skeleton : IDisposable
|
|||
{
|
||||
ResetAnimatedData();
|
||||
|
||||
// tracked bones
|
||||
for (int trackIndex = 0; trackIndex < anim.Skeleton.BoneCount; trackIndex++)
|
||||
// map bones
|
||||
for (int boneIndex = 0; boneIndex < anim.Skeleton.BoneCount; boneIndex++)
|
||||
{
|
||||
var info = anim.Skeleton.ReferenceSkeleton.FinalRefBoneInfo[trackIndex];
|
||||
if (!BonesIndicesByLoweredName.TryGetValue(info.Name.Text.ToLower(), out var boneIndices))
|
||||
var info = anim.Skeleton.ReferenceSkeleton.FinalRefBoneInfo[boneIndex];
|
||||
if (!BonesByLoweredName.TryGetValue(info.Name.Text.ToLower(), out var bone))
|
||||
continue;
|
||||
|
||||
boneIndices.TrackedBoneIndex = trackIndex;
|
||||
var parentTrackIndex = info.ParentIndex;
|
||||
|
||||
do
|
||||
{
|
||||
if (parentTrackIndex < 0) break;
|
||||
info = anim.Skeleton.ReferenceSkeleton.FinalRefBoneInfo[parentTrackIndex];
|
||||
if (boneIndices.LoweredParentBoneName.Equals(info.Name.Text, StringComparison.OrdinalIgnoreCase) && // same parent (name based)
|
||||
BonesIndicesByLoweredName.TryGetValue(info.Name.Text.ToLower(), out var parentBoneIndices) && parentBoneIndices.IsTracked)
|
||||
boneIndices.TrackedParentBoneIndex = parentBoneIndices.BoneIndex;
|
||||
else parentTrackIndex = info.ParentIndex;
|
||||
} while (!boneIndices.IsParentTracked);
|
||||
bone.SkeletonIndex = boneIndex;
|
||||
}
|
||||
|
||||
// fix parent of untracked bones
|
||||
foreach ((var boneName, var boneIndices) in BonesIndicesByLoweredName)
|
||||
var seqCount = anim.Sequences.Count;
|
||||
foreach ((var boneName, var bone) in BonesByLoweredName)
|
||||
{
|
||||
if (boneIndices.IsRoot || boneIndices.IsTracked && boneIndices.IsParentTracked) // assuming root bone always has a track
|
||||
bone.IsAnimated = new bool[seqCount];
|
||||
#if DEBUG
|
||||
if (bone.IsRoot || bone.IsMapped) // assuming root bone always is mapped
|
||||
continue;
|
||||
|
||||
#if DEBUG
|
||||
Log.Warning($"{Name} Bone Mismatch: {boneName} ({boneIndices.BoneIndex}) was not present in the anim's target skeleton");
|
||||
Log.Warning($"{Name} Bone Mismatch: {boneName} ({bone.Index}) was not present in the anim's target skeleton");
|
||||
#endif
|
||||
|
||||
var loweredParentBoneName = boneIndices.LoweredParentBoneName;
|
||||
do
|
||||
{
|
||||
var parentBoneIndices = BonesIndicesByLoweredName[loweredParentBoneName];
|
||||
if (parentBoneIndices.IsParentTracked || parentBoneIndices.IsRoot) boneIndices.TrackedParentBoneIndex = parentBoneIndices.BoneIndex;
|
||||
else loweredParentBoneName = parentBoneIndices.LoweredParentBoneName;
|
||||
} while (!boneIndices.IsParentTracked);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetAnimatedData(bool full = false)
|
||||
{
|
||||
foreach (var boneIndices in BonesIndicesByLoweredName.Values)
|
||||
foreach (var bone in BonesByLoweredName.Values)
|
||||
{
|
||||
boneIndices.TrackedBoneIndex = -1;
|
||||
boneIndices.TrackedParentBoneIndex = -1;
|
||||
bone.SkeletonIndex = -1;
|
||||
bone.IsAnimated = null;
|
||||
}
|
||||
|
||||
if (!full) return;
|
||||
|
|
@ -256,11 +224,11 @@ public class Skeleton : IDisposable
|
|||
_ssbo.Unbind();
|
||||
}
|
||||
|
||||
public Matrix4x4 GetBoneMatrix(BoneIndice boneIndices)
|
||||
public Matrix4x4 GetBoneMatrix(Bone bone)
|
||||
{
|
||||
return IsAnimated
|
||||
? _animatedBonesTransform[_previousAnimationSequence][boneIndices.BoneIndex][_previousSequenceFrame].Matrix
|
||||
: BonesTransformByIndex[boneIndices.BoneIndex].Matrix;
|
||||
? _animatedBonesTransform[_previousAnimationSequence][bone.Index][_previousSequenceFrame].Matrix
|
||||
: bone.Rest.Matrix;
|
||||
}
|
||||
|
||||
public void Render()
|
||||
|
|
@ -270,8 +238,7 @@ public class Skeleton : IDisposable
|
|||
|
||||
public void Dispose()
|
||||
{
|
||||
BonesIndicesByLoweredName.Clear();
|
||||
BonesTransformByIndex.Clear();
|
||||
BonesByLoweredName.Clear();
|
||||
|
||||
_ssbo?.Dispose();
|
||||
GL.DeleteProgram(_handle);
|
||||
|
|
|
|||
|
|
@ -256,8 +256,8 @@ public class Model : IDisposable
|
|||
foreach (var socket in Sockets)
|
||||
{
|
||||
var boneMatrix = Matrix4x4.Identity;
|
||||
if (HasSkeleton && Skeleton.BonesIndicesByLoweredName.TryGetValue(socket.BoneName.Text.ToLower(), out var boneIndices))
|
||||
boneMatrix = Skeleton.GetBoneMatrix(boneIndices);
|
||||
if (HasSkeleton && Skeleton.BonesByLoweredName.TryGetValue(socket.BoneName.Text.ToLower(), out var bone))
|
||||
boneMatrix = Skeleton.GetBoneMatrix(bone);
|
||||
|
||||
var socketRelation = boneMatrix * worldMatrix;
|
||||
foreach (var info in socket.AttachedModels)
|
||||
|
|
|
|||
|
|
@ -295,6 +295,7 @@ public class SnimGui
|
|||
- WASD to move around
|
||||
- Shift to move faster
|
||||
- XC to zoom
|
||||
- Z to animate selected model
|
||||
- Left Mouse Button pressed to look around
|
||||
- Right Click to select a model in the world
|
||||
|
||||
|
|
|
|||
|
|
@ -159,6 +159,12 @@ public class Snooper : GameWindow
|
|||
var delta = (float) e.Time;
|
||||
Renderer.CameraOp.Modify(KeyboardState, delta);
|
||||
|
||||
if (KeyboardState.IsKeyPressed(Keys.Z))
|
||||
{
|
||||
Renderer.Options.RemoveAnimations();
|
||||
Renderer.Options.AnimateMesh(true);
|
||||
WindowShouldClose(true, false);
|
||||
}
|
||||
if (KeyboardState.IsKeyPressed(Keys.Space))
|
||||
Renderer.Options.Tracker.IsPaused = !Renderer.Options.Tracker.IsPaused;
|
||||
if (KeyboardState.IsKeyPressed(Keys.Delete))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user