Browse Source

WIP scene builder

Vicente Penades 6 years ago
parent
commit
5e53a8d166

+ 78 - 6
src/SharpGLTF.Toolkit/Scenes/Content.cs

@@ -1,21 +1,44 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Numerics;
 using System.Text;
+using SharpGLTF.Geometry;
+using SharpGLTF.Materials;
+using SharpGLTF.Schema2;
 
 namespace SharpGLTF.Scenes
 {
-    interface IContentRoot { }
+    using MESHBUILDER = IMeshBuilder<MaterialBuilder>;
 
-    interface IContent { }
+    interface IContentRoot
+    {
+        void Setup(Scene dstScene, Schema2SceneBuilder context);
+    }
+
+    interface IContent
+    {
+        void Setup(Node dstNode, Schema2SceneBuilder context);
+    }
 
-    interface IRenderableContent : IContent { }
+    interface IRenderableContent : IContent
+    {
+        MESHBUILDER GeometryAsset { get; }
+    }
 
     class StaticController : IContentRoot
     {
         private IContent _target;// Can be either a morphController or a mesh, or light or camera
 
         private Matrix4x4 _Transform;
+
+        public void Setup(Scene dstScene, Schema2SceneBuilder context)
+        {
+            var node = dstScene.CreateNode();
+            node.LocalMatrix = _Transform;
+
+            _target.Setup(node, context);
+        }
     }
 
     class TransformController : IContentRoot
@@ -23,6 +46,15 @@ namespace SharpGLTF.Scenes
         private IContent _target;// Can be either a morphController or a mesh, or light or camera
 
         private NodeBuilder _Node;
+
+        public void Setup(Schema2.Scene dstScene, Schema2SceneBuilder context)
+        {
+            var node = context.GetNode(_Node);
+
+            if (node == null) dstScene.CreateNode();
+
+            _target.Setup(node, context);
+        }
     }
 
     class SkinController : IContentRoot
@@ -31,8 +63,22 @@ namespace SharpGLTF.Scenes
 
         // condition: all NodeBuilder objects must have the same root.
         private readonly List<NodeBuilder> _Joints = new List<NodeBuilder>();
+
+        public void Setup(Scene dstScene, Schema2SceneBuilder context)
+        {
+            var skinnedMeshNode = dstScene.CreateNode();
+
+            var skinnedJoints = _Joints.Select(j => context.GetNode(j)).ToArray();
+
+            skinnedMeshNode.WithSkinBinding(skinnedJoints);
+
+            _Target.Setup(skinnedMeshNode, context);
+        }
     }
 
+
+    // We really have two options here: Either implement this here, or as a derived of IMeshBuilder<MaterialBuilder>
+
     class MorphModifier : IRenderableContent // must be a child of a controller, and the parent of a mesh
     {
         private IRenderableContent _Target; // must be a mesh
@@ -40,20 +86,46 @@ namespace SharpGLTF.Scenes
         // morph targets here
 
         private readonly Animations.Animatable<Vector4> _MorphWeights = new Animations.Animatable<Vector4>();
+
+        public MESHBUILDER GeometryAsset => _Target?.GeometryAsset;
+
+        public void Setup(Node dstNode, Schema2SceneBuilder context)
+        {
+            _Target.Setup(dstNode, context);
+
+            // setup morphs here!
+        }
     }
 
     class MeshContent : IRenderableContent
     {
-        private Geometry.IMeshBuilder<Materials.MaterialBuilder> _Geometry;
+        private MESHBUILDER _Geometry;
+
+        public MESHBUILDER GeometryAsset
+        {
+            get => _Geometry;
+            set => _Geometry = value;
+        }
+
+        public void Setup(Node dstNode, Schema2SceneBuilder context)
+        {
+            dstNode.Mesh = context.GetMesh(_Geometry);
+        }
     }
 
     class LightContent : IContent
     {
-
+        public void Setup(Node dstNode, Schema2SceneBuilder context)
+        {
+            throw new NotImplementedException();
+        }
     }
 
     class CameraContent : IContent
     {
-
+        public void Setup(Node dstNode, Schema2SceneBuilder context)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 13 - 1
src/SharpGLTF.Toolkit/Scenes/InstanceBuilder.cs

@@ -25,11 +25,23 @@ namespace SharpGLTF.Scenes
 
         #region API
 
-        internal Geometry.IMeshBuilder<Materials.MaterialBuilder> GetMesh()
+        internal Geometry.IMeshBuilder<Materials.MaterialBuilder> GetGeometryAsset()
+        {
+            if (_Content is IRenderableContent renderable) return renderable.GeometryAsset;
+
+            return null;
+        }
+
+        internal NodeBuilder GetArmatureAsset()
         {
             throw new NotImplementedException();
         }
 
+        internal void Setup(Schema2.Scene dstScene, Schema2SceneBuilder context)
+        {
+            _Content.Setup(dstScene, context);
+        }
+
         #endregion
     }
 }

+ 2 - 0
src/SharpGLTF.Toolkit/Scenes/NodeBuilder.cs

@@ -40,6 +40,8 @@ namespace SharpGLTF.Scenes
 
         public NodeBuilder Parent => _Parent;
 
+        public NodeBuilder Root => _Parent == null ? this : _Parent.Root;
+
         public IReadOnlyList<NodeBuilder> Children => _Children;
 
         #endregion

+ 70 - 11
src/SharpGLTF.Toolkit/Scenes/SceneBuilder.Schema2.cs

@@ -7,38 +7,97 @@ namespace SharpGLTF.Scenes
 {
     using Schema2;
 
-    public partial class SceneBuilder
+    using MESHBUILDER = Geometry.IMeshBuilder<Materials.MaterialBuilder>;
+
+    class Schema2SceneBuilder
     {
+        #region data
 
-        public ModelRoot ToSchema2()
-        {
-            var dstModel = ModelRoot.CreateModel();
+        private readonly Dictionary<MESHBUILDER, Mesh> _Meshes = new Dictionary<MESHBUILDER, Mesh>();
+
+        private readonly Dictionary<NodeBuilder, Node> _Nodes = new Dictionary<NodeBuilder, Node>();
+
+        #endregion
+
+        #region API
+
+        public Mesh GetMesh(MESHBUILDER key) { return key == null ? null : _Meshes.TryGetValue(key, out Mesh val) ? val : null; }
+
+        public Node GetNode(NodeBuilder key) { return key == null ? null : _Nodes.TryGetValue(key, out Node val) ? val : null; }
 
+        public void AddScene(Scene dstScene, SceneBuilder srcScene)
+        {
             // gather all meshes and group them by their attribute layout.
 
-            var meshGroups = _Instances
-                .Select(item => item.GetMesh())
+            var meshGroups = srcScene.Instances
+                .Select(item => item.GetGeometryAsset())
                 .Where(item => item != null)
                 .Distinct()
                 .ToList()
                 .GroupBy(item => item.GetType());
 
-            // create schema2.mesh collections for every gathered group.
-
-            var meshMap = new Dictionary<Geometry.IMeshBuilder<Materials.MaterialBuilder>, Mesh>();
+            // create Schema2.Mesh collections for every gathered group.
 
             foreach (var meshGroup in meshGroups)
             {
                 var meshArray = meshGroup.ToArray();
 
-                var meshDst = dstModel.CreateMeshes(meshArray);
+                var meshDst = dstScene.LogicalParent.CreateMeshes(meshArray);
 
                 for (int i = 0; i < meshArray.Length; ++i)
                 {
-                    meshMap[meshArray[i]] = meshDst[i];
+                    _Meshes[meshArray[i]] = meshDst[i];
                 }
             }
 
+            // gather all armatures
+
+            var armatures = srcScene.Instances
+                .Select(item => item.GetArmatureAsset())
+                .Where(item => item != null)
+                .Select(item => item.Root)
+                .Distinct()
+                .ToList();
+
+            // create Schema2.Node trees for every armature
+
+            foreach (var armature in armatures)
+            {
+                CreateNodeTree(dstScene,  armature);
+            }
+
+            // process instances
+
+            foreach (var inst in srcScene.Instances)
+            {
+                inst.Setup(dstScene, this);
+            }
+        }
+
+        private void CreateNodeTree(IVisualNodeContainer container, NodeBuilder srcNode)
+        {
+            var dstNode = container.CreateNode(srcNode.Name);
+            _Nodes[srcNode] = dstNode;
+
+            // assign animation here
+
+            foreach (var c in srcNode.Children) CreateNodeTree(dstNode, c);
+        }
+
+        #endregion
+    }
+
+    public partial class SceneBuilder
+    {
+        public ModelRoot ToSchema2()
+        {
+            var dstModel = ModelRoot.CreateModel();
+
+            var dstScene = dstModel.UseScene(0);
+
+            var context = new Schema2SceneBuilder();
+            context.AddScene(dstScene, this);
+
             return dstModel;
         }
     }