diff --git a/src/Bliss.Test/Game.cs b/src/Bliss.Test/Game.cs index 9dc5ca6..3c4ef87 100644 --- a/src/Bliss.Test/Game.cs +++ b/src/Bliss.Test/Game.cs @@ -166,7 +166,7 @@ protected virtual void FixedUpdate() { this._playingAnim = true; this._frameCount++; - if (this._frameCount >= this._playerModel.Animations[0].FrameCount) { + if (this._frameCount >= this._playerModel.Animations[2].FrameCount) { this._frameCount = 0; } } @@ -195,7 +195,7 @@ protected virtual void Draw(GraphicsDevice graphicsDevice, CommandList commandLi if (this._cam3D.GetFrustum().ContainsBox(this._playerModel.BoundingBox)) { if (this._playingAnim) { - this._playerModel.UpdateAnimationBones(commandList, this._playerModel.Animations[0], this._frameCount); + this._playerModel.UpdateAnimationBones(commandList, this._playerModel.Animations[2], this._frameCount); } this._playerModel.Draw(commandList, this.FullScreenTexture.Framebuffer.OutputDescription, new Transform() { Translation = new Vector3(0, 0.05F, 0)}, Color.Blue); } diff --git a/src/Bliss.Test/content/player.glb b/src/Bliss.Test/content/player.glb index 5e5d49c..12a8dd8 100644 Binary files a/src/Bliss.Test/content/player.glb and b/src/Bliss.Test/content/player.glb differ diff --git a/src/Bliss/CSharp/Geometry/Animations/MeshAmateurBuilder.cs b/src/Bliss/CSharp/Geometry/Animations/MeshAmateurBuilder.cs index 07de34a..6e5311d 100644 --- a/src/Bliss/CSharp/Geometry/Animations/MeshAmateurBuilder.cs +++ b/src/Bliss/CSharp/Geometry/Animations/MeshAmateurBuilder.cs @@ -17,10 +17,24 @@ namespace Bliss.CSharp.Geometry.Animations; public class MeshAmateurBuilder { + /// + /// The root node of the model. This node typically contains the root transformations for the mesh and references to other child nodes. + /// private Node _rootNode; + + /// + /// An array of objects that represent animations applied to the model. + /// private ModelAnimation[] _animations; + /// + /// A dictionary mapping bone IDs to the corresponding objects. This allows efficient look-up of bones by their ID or name. + /// private Dictionary _bonesByName; + + /// + /// An array of transformation matrices for the bones, used for skeletal animation. Each bone has a corresponding transformation matrix. + /// private Matrix4x4[] _boneTransformations; /// @@ -83,8 +97,8 @@ private Dictionary SetupBoneInfos(ModelAnimation animation) { /// The current frame index being processed. /// The transformation matrix of the parent node. private void UpdateChannel(Node node, ModelAnimation animation, int frame, AMatrix4x4 parentTransform) { - AMatrix4x4 nodeTransformation = AMatrix4x4.Identity; - + AMatrix4x4 nodeTransformation = node.Transform; + if (this.GetChannel(node, animation, out NodeAnimationChannel? channel)) { AMatrix4x4 scale = this.InterpolateScale(channel!, animation, frame); AMatrix4x4 rotation = this.InterpolateRotation(channel!, animation, frame); @@ -140,7 +154,7 @@ private AMatrix4x4 InterpolateTranslation(NodeAnimationChannel channel, ModelAni Vector3D start = currentFrame.Value; Vector3D end = nextFrame.Value; - position = start + (float) delta * (end - start); + position = start + (float) Math.Clamp(delta, 0.0F, 1.0F) * (end - start); } return AMatrix4x4.FromTranslation(position); @@ -176,7 +190,7 @@ private AMatrix4x4 InterpolateRotation(NodeAnimationChannel channel, ModelAnimat AQuaternion start = currentFrame.Value; AQuaternion end = nextFrame.Value; - rotation = AQuaternion.Slerp(start, end, (float) delta); + rotation = AQuaternion.Slerp(start, end, (float) Math.Clamp(delta, 0.0F, 1.0F)); rotation.Normalize(); } @@ -214,7 +228,7 @@ private AMatrix4x4 InterpolateScale(NodeAnimationChannel channel, ModelAnimation Vector3D start = currentFrame.Value; Vector3D end = nextFrame.Value; - scale = start + (float) delta * (end - start); + scale = start + (float) Math.Clamp(delta, 0.0F, 1.0F) * (end - start); } return AMatrix4x4.FromScaling(scale); diff --git a/src/Bliss/CSharp/Geometry/Model.cs b/src/Bliss/CSharp/Geometry/Model.cs index 7755734..030e7ac 100644 --- a/src/Bliss/CSharp/Geometry/Model.cs +++ b/src/Bliss/CSharp/Geometry/Model.cs @@ -9,6 +9,7 @@ using System.Numerics; using System.Text; using Assimp; +using Assimp.Configs; using Bliss.CSharp.Effects; using Bliss.CSharp.Geometry.Animations; using Bliss.CSharp.Geometry.Conversions; @@ -36,7 +37,30 @@ public class Model : Disposable { /// This includes flipping the winding order, triangulating, pre-transforming vertices, /// calculating tangent space, and generating smooth normals. /// - private const PostProcessSteps DefaultPostProcessSteps = PostProcessSteps.FlipWindingOrder | PostProcessSteps.Triangulate | PostProcessSteps.CalculateTangentSpace | PostProcessSteps.GenerateSmoothNormals; + private const PostProcessSteps DefaultPostProcessSteps = PostProcessSteps.FlipWindingOrder | + PostProcessSteps.Triangulate | + PostProcessSteps.CalculateTangentSpace | + PostProcessSteps.GenerateSmoothNormals | + PostProcessSteps.JoinIdenticalVertices | + PostProcessSteps.FindInvalidData | + PostProcessSteps.ImproveCacheLocality | + PostProcessSteps.FixInFacingNormals | + PostProcessSteps.GenerateUVCoords | + PostProcessSteps.ValidateDataStructure | + PostProcessSteps.FindInstances | + PostProcessSteps.GlobalScale; + + /// + /// A collection of default property configurations applied to the 3D model importer. + /// These configurations include settings to limit vertex bone weights, exclude certain elements, + /// and adjust import behavior for specific file formats like FBX. + /// + private static readonly List PropertyConfigs = [ + new NoSkeletonMeshesConfig(true), + new VertexBoneWeightLimitConfig(4), + new FBXImportCamerasConfig(false), + new FBXStrictModeConfig(false) + ]; /// /// The default effect applied to models. @@ -95,6 +119,11 @@ public Model(GraphicsDevice graphicsDevice, Mesh[] meshes, ModelAnimation[] anim /// Returns a new instance of the class with the loaded meshes. public static Model Load(GraphicsDevice graphicsDevice, string path, bool loadMaterial = true, bool flipUv = false) { using AssimpContext context = new AssimpContext(); + + foreach (PropertyConfig config in PropertyConfigs) { + context.SetConfig(config); + } + Scene scene = context.ImportFile(path, DefaultPostProcessSteps); List meshes = new List();