using System; using System.Collections.Generic; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; #if USINGMONOGAMEMODEL using MODELMESH = Microsoft.Xna.Framework.Graphics.ModelMesh; using MODELMESHPART = Microsoft.Xna.Framework.Graphics.ModelMeshPart; #else using MODELMESH = SharpGLTF.Runtime.RuntimeModelMesh; using MODELMESHPART = SharpGLTF.Runtime.RuntimeModelMeshPart; #endif namespace SharpGLTF.Runtime { public sealed class MonoGameModelInstance { #region lifecycle internal MonoGameModelInstance(MonoGameModelTemplate template, SceneInstance instance) { _Template = template; _Controller = instance; } #endregion #region data private readonly MonoGameModelTemplate _Template; private readonly SceneInstance _Controller; #endregion #region properties /// /// Gets a reference to the template used to create this . /// public MonoGameModelTemplate Template => _Template; /// /// Gets a reference to the animation controller of this . /// public SceneInstance Controller => _Controller; #endregion #region API /// /// Draws this into the current . /// /// The projection matrix. /// The view matrix. /// The world matrix. public void Draw(Matrix projection, Matrix view, Matrix world) { foreach (var inst in _Controller) { Draw(_Template._Meshes[inst.Template.LogicalMeshIndex], projection, view, world, inst.Transform); } } private void Draw(MODELMESH mesh, Matrix projectionXform, Matrix viewXform, Matrix worldXform, Transforms.IGeometryTransform modelXform) { if (modelXform is Transforms.SkinnedTransform skinXform) { var skinTransforms = skinXform.SkinMatrices.Select(item => item.ToXna()).ToArray(); foreach (var effect in mesh.Effects) { UpdateTransforms(effect, projectionXform, viewXform, worldXform, skinTransforms); } } if (modelXform is Transforms.RigidTransform statXform) { worldXform = Matrix.Multiply(statXform.WorldMatrix, worldXform); foreach (var effect in mesh.Effects) { UpdateTransforms(effect, projectionXform, viewXform, worldXform); } } mesh.Draw(); } private static void UpdateTransforms(Effect effect, Matrix projectionXform, Matrix viewXform, Matrix worldXform, Matrix[] skinTransforms = null) { if (effect is IEffectMatrices matrices) { matrices.Projection = projectionXform; matrices.View = viewXform; matrices.World = worldXform; } if (effect is SkinnedEffect skin && skinTransforms != null) { var xposed = skinTransforms.Select(item => Matrix.Transpose(item)).ToArray(); skin.SetBoneTransforms(skinTransforms); } if (effect is IEffectBones iskin && skinTransforms != null) { var xposed = skinTransforms.Select(item => Matrix.Transpose(item)).ToArray(); iskin.SetBoneTransforms(skinTransforms, 0, skinTransforms.Length); } } #endregion } }