Browse Source

Sync code with SharpGLTF.Monogame.Demo

Vicente Penades 5 years ago
parent
commit
bd643f1496

+ 16 - 8
examples/SharpGLTF.Runtime.MonoGame/LoaderContext.cs

@@ -6,6 +6,14 @@ using Microsoft.Xna.Framework.Graphics;
 
 using SharpGLTF.Schema2;
 
+#if USINGMONOGAMEMODEL
+using MODELMESH = Microsoft.Xna.Framework.Graphics.ModelMesh;
+using MODELMESHPART = Microsoft.Xna.Framework.Graphics.ModelMeshPart;
+#else
+using MODELMESH = SharpGLTF.Runtime.ModelMeshReplacement;
+using MODELMESHPART = SharpGLTF.Runtime.ModelMeshPartReplacement;
+#endif
+
 namespace SharpGLTF.Runtime
 {
     /// <summary>
@@ -30,8 +38,8 @@ namespace SharpGLTF.Runtime
         private readonly GraphicsResourceTracker _Disposables = new GraphicsResourceTracker();
         private readonly MaterialFactory _MatFactory;        
 
-        private readonly Dictionary<Mesh, ModelMesh> _StaticMeshes = new Dictionary<Mesh, ModelMesh>();
-        private readonly Dictionary<Mesh, ModelMesh> _SkinnedMeshes = new Dictionary<Mesh, ModelMesh>();
+        private readonly Dictionary<Mesh, MODELMESH> _RigidMeshes = new Dictionary<Mesh, MODELMESH>();
+        private readonly Dictionary<Mesh, MODELMESH> _SkinnedMeshes = new Dictionary<Mesh, MODELMESH>();
         
         #endregion
 
@@ -39,7 +47,7 @@ namespace SharpGLTF.Runtime
 
         public IReadOnlyList<GraphicsResource> Disposables => _Disposables.Disposables;
 
-        #endregion                  
+        #endregion
 
         #region Mesh API
 
@@ -59,13 +67,13 @@ namespace SharpGLTF.Runtime
             }
         }
 
-        public ModelMesh CreateMesh(Schema2.Mesh srcMesh, int maxBones = 72)
+        public MODELMESH CreateMesh(Schema2.Mesh srcMesh, int maxBones = 72)
         {
             if (_Device == null) throw new InvalidOperationException();            
 
             var srcPrims = GetValidPrimitives(srcMesh).ToList();            
 
-            var dstMesh = new ModelMesh(_Device, Enumerable.Range(0, srcPrims.Count).Select(item => new ModelMeshPart()).ToList());
+            var dstMesh = new MODELMESH(_Device, Enumerable.Range(0, srcPrims.Count).Select(item => new MODELMESHPART()).ToList());
 
             dstMesh.Name = srcMesh.Name;
             dstMesh.BoundingSphere = srcMesh.CreateBoundingSphere();
@@ -81,17 +89,17 @@ namespace SharpGLTF.Runtime
             return dstMesh;
         }
 
-        private void CreateMeshPart(ModelMeshPart dstPart, MeshPrimitive srcPart, MeshNormalsFallback normalsFunc, int maxBones)
+        private void CreateMeshPart(MODELMESHPART dstPart, MeshPrimitive srcPart, MeshNormalsFallback normalsFunc, int maxBones)
         {
             var doubleSided = srcPart.Material?.DoubleSided ?? false;
 
             var srcGeometry = new MeshPrimitiveReader(srcPart, doubleSided, normalsFunc);
 
-            var eff = srcGeometry.IsSkinned ? _MatFactory.UseSkinnedEffect(srcPart.Material) : _MatFactory.UseStaticEffect(srcPart.Material);
+            var eff = srcGeometry.IsSkinned ? _MatFactory.UseSkinnedEffect(srcPart.Material) : _MatFactory.UseRigidEffect(srcPart.Material);
 
             dstPart.Effect = eff;            
 
-            var vb = srcGeometry.IsSkinned ? CreateVertexBuffer(srcGeometry.ToXnaSkinned()) : CreateVertexBuffer(srcGeometry.ToXnaStatic());
+            var vb = srcGeometry.IsSkinned ? CreateVertexBuffer(srcGeometry.ToXnaSkinned()) : CreateVertexBuffer(srcGeometry.ToXnaRigid());
 
             dstPart.VertexBuffer = vb;
             dstPart.NumVertices = srcGeometry.VertexCount;

+ 5 - 2
examples/SharpGLTF.Runtime.MonoGame/MeshPrimitiveReader.cs

@@ -12,6 +12,9 @@ using XYZW = System.Numerics.Vector4;
 
 namespace SharpGLTF.Runtime
 {
+    /// <summary>
+    /// Reads the content of a glTF <see cref="MeshPrimitive"/> object into a structure that's easier to consume.
+    /// </summary>
     class MeshPrimitiveReader
     {
         #region lifecycle
@@ -93,13 +96,13 @@ namespace SharpGLTF.Runtime
 
         public int VertexCount => _Positions?.Count ?? 0;
 
-        public (int, int, int)[] TriangleIndices => _Triangles;
+        public (int A, int B, int C)[] TriangleIndices => _Triangles;
 
         #endregion
 
         #region API        
 
-        public VertexPositionNormalTexture[] ToXnaStatic()
+        public VertexPositionNormalTexture[] ToXnaRigid()
         {
             var dst = new VertexPositionNormalTexture[_Positions.Count];
 

+ 113 - 0
examples/SharpGLTF.Runtime.MonoGame/ModelMeshReplacement.cs

@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace SharpGLTF.Runtime
+{
+    /// <summary>
+    /// Replaces <see cref="ModelMeshPart"/>.
+    /// </summary>
+    sealed class ModelMeshPartReplacement
+    {
+        internal ModelMeshReplacement _Parent;
+
+        private Effect _Effect;
+
+        public Effect Effect
+        {
+            get => _Effect;
+            set
+            {
+                if (_Effect == value) return;
+                _Effect = value;
+                _Parent.InvalidateEffectsCollection(); // if we change this property, we need to invalidate the parent's effect collection.
+            }
+        }
+
+        public IndexBuffer IndexBuffer { get; set; }
+
+        public int NumVertices { get; set; }
+
+        public int PrimitiveCount { get; set; }
+
+        public int StartIndex { get; set; }
+
+        public object Tag { get; set; }
+
+        public VertexBuffer VertexBuffer { get; set; }
+
+        public int VertexOffset { get; set; }
+    }
+
+    /// <summary>
+    /// Replaces <see cref="ModelMesh"/>
+    /// </summary>
+    sealed class ModelMeshReplacement
+    {
+        private GraphicsDevice graphicsDevice;
+
+        public ModelMeshReplacement(GraphicsDevice graphicsDevice, List<ModelMeshPartReplacement> parts)
+        {
+            // TODO: Complete member initialization
+            this.graphicsDevice = graphicsDevice;
+
+            MeshParts = parts.ToArray();
+
+            foreach (var mp in MeshParts) mp._Parent = this;
+        }
+
+        private IReadOnlyList<Effect> _Effects;
+
+        public IReadOnlyCollection<Effect> Effects
+        {
+            get
+            {
+                if (_Effects != null) return _Effects;
+
+                // effects collection has changed since last call, so we reconstruct the collection.
+                _Effects = MeshParts
+                    .Select(item => item.Effect)
+                    .Distinct()
+                    .ToArray();
+
+                return _Effects;
+            }
+        }
+
+        public Microsoft.Xna.Framework.BoundingSphere BoundingSphere { get; set; }
+
+        public IList<ModelMeshPartReplacement> MeshParts { get; set; }
+
+        public string Name { get; set; }
+
+        public ModelBone ParentBone { get; set; }
+
+        public object Tag { get; set; }
+
+        internal void InvalidateEffectsCollection() { _Effects = null; }
+
+        public void Draw()
+        {
+            for (int i = 0; i < MeshParts.Count; i++)
+            {
+                var part = MeshParts[i];
+                var effect = part.Effect;
+
+                if (part.PrimitiveCount > 0)
+                {
+                    this.graphicsDevice.SetVertexBuffer(part.VertexBuffer);
+                    this.graphicsDevice.Indices = part.IndexBuffer;
+
+                    for (int j = 0; j < effect.CurrentTechnique.Passes.Count; j++)
+                    {
+                        effect.CurrentTechnique.Passes[j].Apply();
+                        graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, part.VertexOffset, part.StartIndex, part.PrimitiveCount);
+                    }
+                }
+            }
+        }
+    }
+}

+ 9 - 1
examples/SharpGLTF.Runtime.MonoGame/MonoGameModelInstance.cs

@@ -5,6 +5,14 @@ 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.ModelMeshReplacement;
+using MODELMESHPART = SharpGLTF.Runtime.ModelMeshPartReplacement;
+#endif
+
 namespace SharpGLTF.Runtime
 {
     public sealed class MonoGameModelInstance
@@ -56,7 +64,7 @@ namespace SharpGLTF.Runtime
             }
         }
 
-        private void Draw(ModelMesh mesh, Matrix projectionXform, Matrix viewXform, Matrix worldXform, Transforms.IGeometryTransform modelXform)
+        private void Draw(MODELMESH mesh, Matrix projectionXform, Matrix viewXform, Matrix worldXform, Transforms.IGeometryTransform modelXform)
         {
             if (modelXform is Transforms.SkinnedTransform skinXform)
             {

+ 10 - 2
examples/SharpGLTF.Runtime.MonoGame/MonoGameModelTemplate.cs

@@ -5,6 +5,14 @@ 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.ModelMeshReplacement;
+using MODELMESHPART = SharpGLTF.Runtime.ModelMeshPartReplacement;
+#endif
+
 namespace SharpGLTF.Runtime
 {
     public class MonoGameModelTemplate
@@ -37,7 +45,7 @@ namespace SharpGLTF.Runtime
             return new MonoGameDeviceContent<MonoGameModelTemplate>(mdl, context.Disposables.ToArray());
         }
         
-        internal MonoGameModelTemplate(SceneTemplate[] scenes, int defaultSceneIndex, IReadOnlyDictionary<int, ModelMesh> meshes)
+        internal MonoGameModelTemplate(SceneTemplate[] scenes, int defaultSceneIndex, IReadOnlyDictionary<int, MODELMESH> meshes)
         {
             _Meshes = meshes;
             _Effects = _Meshes.Values
@@ -60,7 +68,7 @@ namespace SharpGLTF.Runtime
         /// <summary>
         /// Meshes shared by all the scenes.
         /// </summary>
-        internal readonly IReadOnlyDictionary<int, ModelMesh> _Meshes;
+        internal readonly IReadOnlyDictionary<int, MODELMESH> _Meshes;
 
         /// <summary>
         /// Effects shared by all the meshes.

+ 10 - 10
examples/SharpGLTF.Runtime.MonoGame/ResourceManager.cs

@@ -131,10 +131,10 @@ namespace SharpGLTF.Runtime
         private readonly TextureFactory _TexFactory;
         private readonly GraphicsResourceTracker _Disposables;
 
-        private readonly Dictionary<Object, Effect> _StaticEffects = new Dictionary<Object, Effect>();
+        private readonly Dictionary<Object, Effect> _RigidEffects = new Dictionary<Object, Effect>();
         private readonly Dictionary<Object, SkinnedEffect> _SkinnedEffects = new Dictionary<Object, SkinnedEffect>();
 
-        private BasicEffect _DefaultStatic;
+        private BasicEffect _DefaultRigid;
         private SkinnedEffect _DefaultSkinned;
 
         #endregion        
@@ -145,26 +145,26 @@ namespace SharpGLTF.Runtime
         // given monogame's limitations, we try to guess the most appropiate values
         // to have a reasonably good looking renders.
 
-        public Effect UseStaticEffect(Schema2.Material srcMaterial)
+        public Effect UseRigidEffect(Schema2.Material srcMaterial)
         {
             if (_Device == null) throw new InvalidOperationException();
 
             if (srcMaterial == null)
             {
-                if (_DefaultStatic == null)
+                if (_DefaultRigid == null)
                 {
-                    _DefaultStatic = new BasicEffect(_Device);
-                    _Disposables.AddDisposable(_DefaultStatic);
+                    _DefaultRigid = new BasicEffect(_Device);
+                    _Disposables.AddDisposable(_DefaultRigid);
                 }
 
-                return _DefaultStatic;
+                return _DefaultRigid;
             }
 
-            if (_StaticEffects.TryGetValue(srcMaterial, out Effect dstMaterial)) return dstMaterial;
+            if (_RigidEffects.TryGetValue(srcMaterial, out Effect dstMaterial)) return dstMaterial;
 
             dstMaterial = srcMaterial.Alpha == Schema2.AlphaMode.MASK ? CreateAlphaTestEffect(srcMaterial) : CreateBasicEffect(srcMaterial);
 
-            _StaticEffects[srcMaterial] = dstMaterial;
+            _RigidEffects[srcMaterial] = dstMaterial;
 
             return dstMaterial;
         }
@@ -225,7 +225,7 @@ namespace SharpGLTF.Runtime
                 if (_DefaultSkinned == null)
                 {
                     _DefaultSkinned = new SkinnedEffect(_Device);
-                    _Disposables.AddDisposable(_DefaultStatic);
+                    _Disposables.AddDisposable(_DefaultRigid);
                 }
 
                 return _DefaultSkinned;