Browse Source

Monogame glTF loader now handles multiple shared scenes.

Vicente Penades 6 years ago
parent
commit
555d25a9e2

+ 74 - 43
examples/SharpGLTF.Runtime.MonoGame/MonoGameModelTemplate.cs

@@ -22,85 +22,116 @@ namespace SharpGLTF.Runtime
         {
         {
             srcModel.FixTextureSampler();
             srcModel.FixTextureSampler();
 
 
-            var template = Runtime.SceneTemplate.Create(srcModel.DefaultScene, true);
-
+            var templates = srcModel.LogicalScenes
+                .Select(item => SceneTemplate.Create(item, true))
+                .ToArray();
+            
             var context = new LoaderContext(device);
             var context = new LoaderContext(device);
 
 
-            var meshes = template
-                .LogicalMeshIds
-                .ToDictionary(k => k, k => context.CreateMesh(srcModel.LogicalMeshes[k]));
-            
+            var meshes = templates
+                .SelectMany(item => item.LogicalMeshIds)                
+                .ToDictionary(k => k, k => context.CreateMesh(srcModel.LogicalMeshes[k]));            
 
 
-            var mdl = new MonoGameModelTemplate(template, meshes);
+            var mdl = new MonoGameModelTemplate(templates,srcModel.DefaultScene.LogicalIndex, meshes);
 
 
             return new MonoGameDeviceContent<MonoGameModelTemplate>(mdl, context.Disposables.ToArray());
             return new MonoGameDeviceContent<MonoGameModelTemplate>(mdl, context.Disposables.ToArray());
         }
         }
-
-        internal MonoGameModelTemplate(Runtime.SceneTemplate scene, IReadOnlyDictionary<int, ModelMesh> meshes)
+        
+        internal MonoGameModelTemplate(SceneTemplate[] scenes, int defaultSceneIndex, IReadOnlyDictionary<int, ModelMesh> meshes)
         {
         {
-            _Template = scene;
             _Meshes = meshes;
             _Meshes = meshes;
-
             _Effects = _Meshes.Values
             _Effects = _Meshes.Values
                 .SelectMany(item => item.Effects)
                 .SelectMany(item => item.Effects)
                 .Distinct()
                 .Distinct()
                 .ToArray();
                 .ToArray();
 
 
-            var instance = _Template.CreateInstance();
-            instance.SetPoseTransforms();
-
-            _Bounds = default(BoundingSphere);
-
-            foreach (var d in instance.DrawableReferences)
-            {
-                var b = meshes[d.Item1].BoundingSphere;
-
-                if (d.Item2 is Transforms.StaticTransform statXform) b = b.Transform(statXform.WorldMatrix.ToXna());
-
-                if (d.Item2 is Transforms.SkinTransform skinXform)
-                {
-                    // this is a bit agressive and probably over-reaching, but with skins you never know the actual bounds
-                    // unless you calculate the bounds frame by frame.
-
-                    var bb = b;
-                    
-                    foreach(var xb in skinXform.SkinMatrices.Select(item => bb.Transform(item.ToXna())))
-                    {
-                        b = BoundingSphere.CreateMerged(b, xb);
-                    }                    
-                }
+            _Scenes = scenes;
+            _Bounds = scenes
+                .Select(item => CalculateBounds(item))
+                .ToArray();
 
 
-                _Bounds = _Bounds.Radius == 0 ? b : BoundingSphere.CreateMerged(_Bounds, b);
-            }            
+            _DefaultSceneIndex = defaultSceneIndex;
         }
         }
 
 
         #endregion
         #endregion
 
 
         #region data
         #region data
-
-        private readonly Runtime.SceneTemplate _Template;
+        
+        /// <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.
+        /// </summary>
         private readonly Effect[] _Effects;
         private readonly Effect[] _Effects;
-        private readonly BoundingSphere _Bounds;
+
+
+        private readonly SceneTemplate[] _Scenes;
+        private readonly BoundingSphere[] _Bounds;
+
+        private readonly int _DefaultSceneIndex;
 
 
         #endregion
         #endregion
 
 
         #region properties
         #region properties
 
 
+        public int SceneCount => _Scenes.Length;
+
         public IReadOnlyList<Effect> Effects => _Effects;
         public IReadOnlyList<Effect> Effects => _Effects;
 
 
-        public BoundingSphere Bounds => _Bounds;
+        public BoundingSphere Bounds => GetBounds(_DefaultSceneIndex);
 
 
-        public IEnumerable<string> AnimationTracks => _Template.AnimationTracks;
+        public IEnumerable<string> AnimationTracks => GetAnimationTracks(_DefaultSceneIndex);
 
 
         #endregion
         #endregion
 
 
         #region API
         #region API
 
 
-        public MonoGameModelInstance CreateInstance()
+        public int IndexOfScene(string sceneName) => Array.FindIndex(_Scenes, item => item.Name == sceneName);
+
+        public BoundingSphere GetBounds(int sceneIndex) => _Bounds[sceneIndex];
+
+        public IEnumerable<string> GetAnimationTracks(int sceneIndex) => _Scenes[sceneIndex].AnimationTracks;
+
+        public MonoGameModelInstance CreateInstance() => CreateInstance(_DefaultSceneIndex);
+
+        public MonoGameModelInstance CreateInstance(int sceneIndex)
         {
         {
-            return new MonoGameModelInstance(this, _Template.CreateInstance());
+            return new MonoGameModelInstance(this, _Scenes[sceneIndex].CreateInstance());
+        }
+
+        private BoundingSphere CalculateBounds(SceneTemplate scene)
+        {
+            var instance = scene.CreateInstance();
+            instance.SetPoseTransforms();
+
+            var bounds = default(BoundingSphere);
+
+            foreach (var d in instance.DrawableReferences)
+            {
+                var b = _Meshes[d.Item1].BoundingSphere;
+
+                if (d.Item2 is Transforms.StaticTransform statXform) b = b.Transform(statXform.WorldMatrix.ToXna());
+
+                if (d.Item2 is Transforms.SkinTransform skinXform)
+                {
+                    // this is a bit agressive and probably over-reaching, but with skins you never know the actual bounds
+                    // unless you calculate the bounds frame by frame.
+
+                    var bb = b;
+
+                    foreach (var xb in skinXform.SkinMatrices.Select(item => bb.Transform(item.ToXna())))
+                    {
+                        b = BoundingSphere.CreateMerged(b, xb);
+                    }
+                }
+
+                bounds = bounds.Radius == 0 ? b : BoundingSphere.CreateMerged(bounds, b);
+            }
+
+            return bounds;
         }
         }
         
         
         #endregion        
         #endregion        

+ 7 - 2
src/SharpGLTF.Core/Runtime/SceneTemplate.cs

@@ -378,11 +378,12 @@ namespace SharpGLTF.Runtime
                 dstTracks.SetValue(index, name, anim.Duration);
                 dstTracks.SetValue(index, name, anim.Duration);
             }
             }
 
 
-            return new SceneTemplate(dstNodes, drawables, dstTracks);
+            return new SceneTemplate(srcScene.Name, dstNodes, drawables, dstTracks);
         }
         }
 
 
-        private SceneTemplate(NodeTemplate[] nodes, DrawableReference[] drawables, Collections.NamedList<float> animTracks)
+        private SceneTemplate(string name, NodeTemplate[] nodes, DrawableReference[] drawables, Collections.NamedList<float> animTracks)
         {
         {
+            _Name = name;
             _NodeTemplates = nodes;
             _NodeTemplates = nodes;
             _DrawableReferences = drawables;
             _DrawableReferences = drawables;
             _AnimationTracks = animTracks;
             _AnimationTracks = animTracks;
@@ -392,6 +393,8 @@ namespace SharpGLTF.Runtime
 
 
         #region data
         #region data
 
 
+        private readonly String _Name;
+
         private readonly NodeTemplate[] _NodeTemplates;
         private readonly NodeTemplate[] _NodeTemplates;
         private readonly DrawableReference[] _DrawableReferences;
         private readonly DrawableReference[] _DrawableReferences;
 
 
@@ -401,6 +404,8 @@ namespace SharpGLTF.Runtime
 
 
         #region properties
         #region properties
 
 
+        public String Name => _Name;
+
         /// <summary>
         /// <summary>
         /// Gets the unique indices of <see cref="Schema2.Mesh"/> instances in <see cref="Schema2.ModelRoot.LogicalMeshes"/>
         /// Gets the unique indices of <see cref="Schema2.Mesh"/> instances in <see cref="Schema2.ModelRoot.LogicalMeshes"/>
         /// </summary>
         /// </summary>