Просмотр исходного кода

MorphTargets: improving building API

Vicente Penades 6 лет назад
Родитель
Сommit
f94b442f58

+ 5 - 0
src/SharpGLTF.Toolkit/Geometry/MeshBuilder.cs

@@ -85,6 +85,11 @@ namespace SharpGLTF.Geometry
 
         #region API
 
+        public MorphTargetBuilder<TMaterial, TvG, TvS, TvM> UseMorphTarget(int index)
+        {
+            return new MorphTargetBuilder<TMaterial, TvG, TvS, TvM>(this, index);
+        }
+
         private PrimitiveBuilder<TMaterial, TvG, TvM, TvS> _UsePrimitive((TMaterial, int) key)
         {
             if (!_Primitives.TryGetValue(key, out PrimitiveBuilder<TMaterial, TvG, TvM, TvS> primitive))

+ 46 - 0
src/SharpGLTF.Toolkit/Geometry/MorphTargetBuilder.cs

@@ -1,5 +1,7 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
 using System.Text;
 
 using SharpGLTF.Geometry.VertexTypes;
@@ -185,4 +187,48 @@ namespace SharpGLTF.Geometry
 
         #endregion
     }
+
+    public class MorphTargetBuilder<TMaterial, TvG, TvS, TvM>
+            where TvG : struct, IVertexGeometry
+            where TvM : struct, IVertexMaterial
+            where TvS : struct, IVertexSkinning
+    {
+        internal MorphTargetBuilder(MeshBuilder<TMaterial, TvG, TvM, TvS> mesh, int morphTargetIndex)
+        {
+            _Mesh = mesh;
+            _MorphTargetIndex = morphTargetIndex;
+
+            _Positions = _Mesh.Primitives
+                .SelectMany(item => item.Vertices)
+                .Select(item => item.Position)
+                .Distinct()
+                .ToArray();
+        }
+
+        private readonly MeshBuilder<TMaterial, TvG, TvM, TvS> _Mesh;
+        private readonly int _MorphTargetIndex;
+
+        private readonly Vector3[] _Positions;
+
+        public IReadOnlyList<Vector3> Positions => _Positions;
+
+        public void SetVertexDisplacement(Vector3 key, Vector3 displacement)
+        {
+            var g = default(TvG);
+
+            g.SetPosition(displacement);
+
+            foreach (var p in _Mesh.Primitives)
+            {
+                for (int i = 0; i < p.Vertices.Count; ++i)
+                {
+                    if (p.Vertices[i].Position == key)
+                    {
+                        p.MorphTargets.SetVertexDisplacement(_MorphTargetIndex, i, g);
+                    }
+                }
+            }
+        }
+
+    }
 }

+ 2 - 1
src/SharpGLTF.Toolkit/Scenes/SceneBuilder.Schema2.cs

@@ -131,7 +131,8 @@ namespace SharpGLTF.Scenes
             if (animation == null) return;
 
             var dstMesh = dstNode.Mesh;
-            dstMesh.SetMorphWeights(default);
+
+            dstMesh.SetMorphWeights(animation.Value);
 
             foreach (var t in animation.Tracks) dstNode.WithMorphingAnimation(t.Key, t.Value);
         }

+ 2 - 0
src/SharpGLTF.Toolkit/Scenes/Transformers.Schema2.cs

@@ -21,6 +21,8 @@ namespace SharpGLTF.Scenes
             dstNode.LocalMatrix = _WorldTransform;
 
             schema2Target.Setup(dstNode, context);
+
+            context.SetMorphAnimation(dstNode, this.Morphings);
         }
     }
 

+ 53 - 0
tests/SharpGLTF.Tests/Scenes/SceneBuilderTests.cs

@@ -9,6 +9,7 @@ using SharpGLTF.Geometry.VertexTypes;
 using SharpGLTF.Geometry.Parametric;
 using SharpGLTF.Materials;
 using SharpGLTF.Schema2;
+using System.Collections.Generic;
 
 namespace SharpGLTF.Scenes
 {
@@ -429,6 +430,58 @@ namespace SharpGLTF.Scenes
             scene.AttachToCurrentTest("skinned.gltf");
         }
 
+        [Test]
+        public void CreateAllAnimationTypesScene()
+        {
+            // 3D View 7.1908.9012.0 has an issue displaying off-center meshes with animated morph targets.
+
+            TestContext.CurrentContext.AttachShowDirLink();
+            TestContext.CurrentContext.AttachGltfValidatorLinks();
+
+            // create two materials
+
+            var pink = new MaterialBuilder("material1")
+                .WithChannelParam(KnownChannels.BaseColor, new Vector4(1, 0, 1, 1));
+
+            var yellow = new MaterialBuilder("material2")
+                .WithChannelParam(KnownChannels.BaseColor, new Vector4(1, 1, 0, 1));
+
+            var scene = new SceneBuilder();
+
+            var mesh1 = VPOSNRM.CreateCompatibleMesh("shape1");
+            mesh1.AddCube(MaterialBuilder.CreateDefault(), Matrix4x4.Identity);
+            var inst1 = scene.AddMesh(mesh1, Matrix4x4.Identity);
+
+            var mesh2 = VPOSNRM.CreateCompatibleMesh("shape2");
+            mesh2.AddCube(pink, Matrix4x4.Identity);
+            var inst2 = scene.AddMesh(mesh2, Matrix4x4.CreateTranslation(2,0,0));
+
+            scene.AttachToCurrentTest("static.glb");
+            scene.AttachToCurrentTest("static.gltf");
+
+            var morphBuilder = mesh2.UseMorphTarget(0);
+
+            morphBuilder.SetVertexDisplacement(morphBuilder.Positions[0], Vector3.UnitY);
+            morphBuilder.SetVertexDisplacement(morphBuilder.Positions[1], Vector3.UnitY);
+            morphBuilder.SetVertexDisplacement(morphBuilder.Positions[2], Vector3.UnitY);
+            morphBuilder.SetVertexDisplacement(morphBuilder.Positions[3], Vector3.UnitY);
+
+            inst2.Content.UseMorphing().Value = Transforms.SparseWeight8.Create(1);
+            
+            var curve = inst2.Content.UseMorphing().UseTrackBuilder("Default");
+            curve.SetPoint(0, Transforms.SparseWeight8.Create(0));
+            curve.SetPoint(1, Transforms.SparseWeight8.Create(1));
+            curve.SetPoint(2, Transforms.SparseWeight8.Create(0));
+
+            var gltf = scene.ToSchema2();
+
+            // Assert.AreEqual(1, gltf.LogicalMeshes[1].MorphWeights[0]);
+
+            scene.AttachToCurrentTest("mopth.glb");
+            scene.AttachToCurrentTest("mopth.gltf");
+        }
+
+        
 
         [TestCase("AnimatedMorphCube.glb")]
         [TestCase("AnimatedMorphSphere.glb")]