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();