2
0
Эх сурвалжийг харах

WIP scene builder, looking for an easy to use API...

Vicente Penades 6 жил өмнө
parent
commit
cb63fa9e69

+ 83 - 0
src/SharpGLTF.Toolkit/Animations/Curves.cs

@@ -113,6 +113,89 @@ namespace SharpGLTF.Animations
         #endregion
         #endregion
     }
     }
 
 
+    class SingleLinearCurve : Curve<Single, Single>, ICurveWriter<Single>
+    {
+        #region API
+
+        public override Single GetSample(float offset)
+        {
+            var sample = FindSample(offset);
+
+            return sample.Item1 * (1-sample.Item3) + (sample.Item2 * sample.Item3);
+        }
+
+        public void SetControlPoint(float offset, Single value)
+        {
+            SetKey(offset, value);
+        }
+
+        #endregion
+    }
+
+    class SingleCubicCurve : Curve<(Single, Single, Single), Single>, ICubicCurveWriter<Single>
+    {
+        #region API
+
+        public override Single GetSample(float offset)
+        {
+            var sample = FindSample(offset);
+
+            return Hermite(sample.Item1.Item2, sample.Item1.Item3, sample.Item2.Item2, sample.Item2.Item1, sample.Item3);
+        }
+
+        private static Single Hermite(Single value1, Single tangent1, Single value2, Single tangent2, float amount)
+        {
+            // http://mathworld.wolfram.com/HermitePolynomial.html
+
+            var squared = amount * amount;
+            var cubed = amount * squared;
+
+            var part1 = (2.0f * cubed) - (3.0f * squared) + 1.0f;
+            var part2 = (-2.0f * cubed) + (3.0f * squared);
+            var part3 = (cubed - (2.0f * squared)) + amount;
+            var part4 = cubed - squared;
+
+            return (value1 * part1) + (value2 * part2) + (tangent1 * part3) + (tangent2 * part4);
+        }
+
+        public void SetControlPoint(float key, Single value)
+        {
+            var val = GetKey(key) ?? default;
+            val.Item2 = value;
+            SetKey(key, val);
+        }
+
+        public void SetControlPointIn(float key, Single value)
+        {
+            var val = GetKey(key) ?? default;
+            val.Item1 = value - val.Item2;
+            SetKey(key, val);
+        }
+
+        public void SetControlPointOut(float key, Single value)
+        {
+            var val = GetKey(key) ?? default;
+            val.Item3 = value + val.Item2;
+            SetKey(key, val);
+        }
+
+        public void SetTangentIn(float key, Single value)
+        {
+            var val = GetKey(key) ?? default;
+            val.Item1 = value;
+            SetKey(key, val);
+        }
+
+        public void SetTangentOut(float key, Single value)
+        {
+            var val = GetKey(key) ?? default;
+            val.Item3 = value;
+            SetKey(key, val);
+        }
+
+        #endregion
+    }
+
     class Vector3LinearCurve : Curve<Vector3, Vector3>, ICurveWriter<Vector3>
     class Vector3LinearCurve : Curve<Vector3, Vector3>, ICurveWriter<Vector3>
     {
     {
         #region API
         #region API

+ 106 - 18
src/SharpGLTF.Toolkit/Scenes/Content.cs

@@ -13,6 +13,10 @@ namespace SharpGLTF.Scenes
 
 
     interface IContentRoot
     interface IContentRoot
     {
     {
+        MESHBUILDER GetGeometryAsset();
+
+        NodeBuilder GetArmatureAsset();
+
         void Setup(Scene dstScene, Schema2SceneBuilder context);
         void Setup(Scene dstScene, Schema2SceneBuilder context);
     }
     }
 
 
@@ -23,47 +27,111 @@ namespace SharpGLTF.Scenes
 
 
     interface IRenderableContent : IContent
     interface IRenderableContent : IContent
     {
     {
-        MESHBUILDER GeometryAsset { get; }
+        MESHBUILDER GetGeometryAsset();
     }
     }
 
 
-    class StaticController : IContentRoot
+    class StaticTransformer : IContentRoot
     {
     {
-        private IContent _target;// Can be either a morphController or a mesh, or light or camera
+        #region lifecycle
+
+        public StaticTransformer(MESHBUILDER mesh, Matrix4x4 xform)
+        {
+            _Transform = xform;
+            _Target = new MeshContent(mesh);
+        }
+
+        #endregion
+
+        #region data
+
+        private IContent _Target;// Can be either a morphController or a mesh, or light or camera
 
 
         private Matrix4x4 _Transform;
         private Matrix4x4 _Transform;
 
 
+        #endregion
+
+        #region API
+
+        public NodeBuilder GetArmatureAsset() { return null; }
+
+        public MESHBUILDER GetGeometryAsset() { return (_Target as IRenderableContent)?.GetGeometryAsset(); }
+
         public void Setup(Scene dstScene, Schema2SceneBuilder context)
         public void Setup(Scene dstScene, Schema2SceneBuilder context)
         {
         {
             var node = dstScene.CreateNode();
             var node = dstScene.CreateNode();
             node.LocalMatrix = _Transform;
             node.LocalMatrix = _Transform;
 
 
-            _target.Setup(node, context);
+            _Target.Setup(node, context);
         }
         }
+
+        #endregion
     }
     }
 
 
-    class TransformController : IContentRoot
+    class NodeTransformer : IContentRoot
     {
     {
-        private IContent _target;// Can be either a morphController or a mesh, or light or camera
+        #region lifecycle
+
+        public NodeTransformer(MESHBUILDER mesh, NodeBuilder node)
+        {
+            _Node = node;
+            _Target = new MeshContent(mesh);
+        }
+
+        #endregion
+
+        #region data
+
+        private IContent _Target; // Can be either a morphController or a mesh, or light or camera
 
 
         private NodeBuilder _Node;
         private NodeBuilder _Node;
 
 
+        #endregion
+
+        #region API
+
+        public NodeBuilder GetArmatureAsset() { return _Node.Root; }
+
+        public MESHBUILDER GetGeometryAsset() { return (_Target as IRenderableContent)?.GetGeometryAsset(); }
+
         public void Setup(Schema2.Scene dstScene, Schema2SceneBuilder context)
         public void Setup(Schema2.Scene dstScene, Schema2SceneBuilder context)
         {
         {
             var node = context.GetNode(_Node);
             var node = context.GetNode(_Node);
 
 
             if (node == null) dstScene.CreateNode();
             if (node == null) dstScene.CreateNode();
 
 
-            _target.Setup(node, context);
+            _Target.Setup(node, context);
         }
         }
+
+        #endregion
     }
     }
 
 
-    class SkinController : IContentRoot
+    class SkinTransformer : IContentRoot
     {
     {
+        #region lifecycle
+
+        public SkinTransformer(MESHBUILDER mesh, NodeBuilder[] joints)
+        {
+            _Target = new MeshContent(mesh);
+            _Joints.AddRange(joints);
+        }
+
+        #endregion
+
+        #region data
+
         private IRenderableContent _Target; // Can be either a morphController or a mesh
         private IRenderableContent _Target; // Can be either a morphController or a mesh
 
 
         // condition: all NodeBuilder objects must have the same root.
         // condition: all NodeBuilder objects must have the same root.
         private readonly List<NodeBuilder> _Joints = new List<NodeBuilder>();
         private readonly List<NodeBuilder> _Joints = new List<NodeBuilder>();
 
 
+        #endregion
+
+        #region API
+
+        public MESHBUILDER GetGeometryAsset() { return (_Target as IRenderableContent)?.GetGeometryAsset(); }
+
+        public NodeBuilder GetArmatureAsset() { return _Joints.Select(item => item.Root).Distinct().FirstOrDefault(); }
+
         public void Setup(Scene dstScene, Schema2SceneBuilder context)
         public void Setup(Scene dstScene, Schema2SceneBuilder context)
         {
         {
             var skinnedMeshNode = dstScene.CreateNode();
             var skinnedMeshNode = dstScene.CreateNode();
@@ -74,20 +142,25 @@ namespace SharpGLTF.Scenes
 
 
             _Target.Setup(skinnedMeshNode, context);
             _Target.Setup(skinnedMeshNode, context);
         }
         }
-    }
 
 
+        #endregion
+    }
 
 
     // We really have two options here: Either implement this here, or as a derived of IMeshBuilder<MaterialBuilder>
     // 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
     class MorphModifier : IRenderableContent // must be a child of a controller, and the parent of a mesh
     {
     {
-        private IRenderableContent _Target; // must be a mesh
+        #region data
+
+        private IRenderableContent _Target;
+
+        private readonly List<Animations.Animatable<float>> _MorphWeights = new List<Animations.Animatable<float>>();
 
 
-        // morph targets here
+        #endregion
 
 
-        private readonly Animations.Animatable<Vector4> _MorphWeights = new Animations.Animatable<Vector4>();
+        #region API
 
 
-        public MESHBUILDER GeometryAsset => _Target?.GeometryAsset;
+        public MESHBUILDER GetGeometryAsset() => _Target?.GetGeometryAsset();
 
 
         public void Setup(Node dstNode, Schema2SceneBuilder context)
         public void Setup(Node dstNode, Schema2SceneBuilder context)
         {
         {
@@ -95,22 +168,37 @@ namespace SharpGLTF.Scenes
 
 
             // setup morphs here!
             // setup morphs here!
         }
         }
+
+        #endregion
     }
     }
 
 
     class MeshContent : IRenderableContent
     class MeshContent : IRenderableContent
     {
     {
-        private MESHBUILDER _Geometry;
+        #region lifecycle
 
 
-        public MESHBUILDER GeometryAsset
+        public MeshContent(MESHBUILDER mesh)
         {
         {
-            get => _Geometry;
-            set => _Geometry = value;
+            _Mesh = mesh;
         }
         }
 
 
+        #endregion
+
+        #region data
+
+        private MESHBUILDER _Mesh;
+
+        #endregion
+
+        #region API
+
+        public MESHBUILDER GetGeometryAsset() => _Mesh;
+
         public void Setup(Node dstNode, Schema2SceneBuilder context)
         public void Setup(Node dstNode, Schema2SceneBuilder context)
         {
         {
-            dstNode.Mesh = context.GetMesh(_Geometry);
+            dstNode.Mesh = context.GetMesh(_Mesh);
         }
         }
+
+        #endregion
     }
     }
 
 
     class LightContent : IContent
     class LightContent : IContent

+ 12 - 4
src/SharpGLTF.Toolkit/Scenes/InstanceBuilder.cs

@@ -23,18 +23,26 @@ namespace SharpGLTF.Scenes
 
 
         #endregion
         #endregion
 
 
+        #region public
+
+        internal IContentRoot Content
+        {
+            get => _Content;
+            set => _Content = value;
+        }
+
+        #endregion
+
         #region API
         #region API
 
 
         internal Geometry.IMeshBuilder<Materials.MaterialBuilder> GetGeometryAsset()
         internal Geometry.IMeshBuilder<Materials.MaterialBuilder> GetGeometryAsset()
         {
         {
-            if (_Content is IRenderableContent renderable) return renderable.GeometryAsset;
-
-            return null;
+            return _Content?.GetGeometryAsset();
         }
         }
 
 
         internal NodeBuilder GetArmatureAsset()
         internal NodeBuilder GetArmatureAsset()
         {
         {
-            throw new NotImplementedException();
+            return _Content?.GetArmatureAsset();
         }
         }
 
 
         internal void Setup(Schema2.Scene dstScene, Schema2SceneBuilder context)
         internal void Setup(Schema2.Scene dstScene, Schema2SceneBuilder context)

+ 3 - 3
src/SharpGLTF.Toolkit/Scenes/SceneBuilder.Schema2.cs

@@ -63,7 +63,7 @@ namespace SharpGLTF.Scenes
 
 
             foreach (var armature in armatures)
             foreach (var armature in armatures)
             {
             {
-                CreateNodeTree(dstScene,  armature);
+                CreateArmature(dstScene,  armature);
             }
             }
 
 
             // process instances
             // process instances
@@ -74,14 +74,14 @@ namespace SharpGLTF.Scenes
             }
             }
         }
         }
 
 
-        private void CreateNodeTree(IVisualNodeContainer container, NodeBuilder srcNode)
+        private void CreateArmature(IVisualNodeContainer container, NodeBuilder srcNode)
         {
         {
             var dstNode = container.CreateNode(srcNode.Name);
             var dstNode = container.CreateNode(srcNode.Name);
             _Nodes[srcNode] = dstNode;
             _Nodes[srcNode] = dstNode;
 
 
             // assign animation here
             // assign animation here
 
 
-            foreach (var c in srcNode.Children) CreateNodeTree(dstNode, c);
+            foreach (var c in srcNode.Children) CreateArmature(dstNode, c);
         }
         }
 
 
         #endregion
         #endregion

+ 24 - 4
src/SharpGLTF.Toolkit/Scenes/SceneBuilder.cs

@@ -1,9 +1,12 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Numerics;
 using System.Text;
 using System.Text;
 
 
 namespace SharpGLTF.Scenes
 namespace SharpGLTF.Scenes
 {
 {
+    using MESHBUILDER = Geometry.IMeshBuilder<Materials.MaterialBuilder>;
+
     public partial class SceneBuilder
     public partial class SceneBuilder
     {
     {
         #region data
         #region data
@@ -20,11 +23,28 @@ namespace SharpGLTF.Scenes
 
 
         #region API
         #region API
 
 
-        public InstanceBuilder CreateInstance()
+        public void AddMesh(MESHBUILDER mesh, Matrix4x4 transform)
+        {
+            var instance = new InstanceBuilder(this);
+            instance.Content = new StaticTransformer(mesh, transform);
+
+            _Instances.Add(instance);
+        }
+
+        public void AddMesh(MESHBUILDER mesh, NodeBuilder node)
         {
         {
-            var inst = new InstanceBuilder(this);
-            _Instances.Add(inst);
-            return inst;
+            var instance = new InstanceBuilder(this);
+            instance.Content = new NodeTransformer(mesh, node);
+
+            _Instances.Add(instance);
+        }
+
+        public void AddSkinnedMesh(MESHBUILDER mesh, params NodeBuilder[] joints)
+        {
+            var instance = new InstanceBuilder(this);
+            instance.Content = new SkinTransformer(mesh, joints);
+
+            _Instances.Add(instance);
         }
         }
 
 
         #endregion
         #endregion