Browse Source

Merge pull request #142 from ptasev/pt-tests

Added personal tests
Vicente Penades 3 years ago
parent
commit
55a58ec366

+ 32 - 4
src/SharpGLTF.Core/Runtime/MeshDecoder.cs

@@ -2,7 +2,7 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 using System.Text;
 using System.Text;
-
+using SharpGLTF.Transforms;
 using XY = System.Numerics.Vector2;
 using XY = System.Numerics.Vector2;
 using XYZ = System.Numerics.Vector3;
 using XYZ = System.Numerics.Vector3;
 using XYZW = System.Numerics.Vector4;
 using XYZW = System.Numerics.Vector4;
@@ -140,7 +140,7 @@ namespace SharpGLTF.Runtime
         public static XYZ GetPosition(this IMeshPrimitiveDecoder primitive, int idx, Transforms.IGeometryTransform xform)
         public static XYZ GetPosition(this IMeshPrimitiveDecoder primitive, int idx, Transforms.IGeometryTransform xform)
         {
         {
             Guard.NotNull(primitive, nameof(primitive));
             Guard.NotNull(primitive, nameof(primitive));
-            Guard.MustBeBetweenOrEqualTo(idx, 0, primitive.VertexCount + 1, nameof(idx));
+            Guard.MustBeBetweenOrEqualTo(idx, 0, primitive.VertexCount - 1, nameof(idx));
             Guard.NotNull(xform, nameof(xform));
             Guard.NotNull(xform, nameof(xform));
 
 
             var p = primitive.GetPosition(idx);
             var p = primitive.GetPosition(idx);
@@ -153,7 +153,7 @@ namespace SharpGLTF.Runtime
         public static XYZ GetNormal(this IMeshPrimitiveDecoder primitive, int idx, Transforms.IGeometryTransform xform)
         public static XYZ GetNormal(this IMeshPrimitiveDecoder primitive, int idx, Transforms.IGeometryTransform xform)
         {
         {
             Guard.NotNull(primitive, nameof(primitive));
             Guard.NotNull(primitive, nameof(primitive));
-            Guard.MustBeBetweenOrEqualTo(idx, 0, primitive.VertexCount + 1, nameof(idx));
+            Guard.MustBeBetweenOrEqualTo(idx, 0, primitive.VertexCount - 1, nameof(idx));
             Guard.NotNull(xform, nameof(xform));
             Guard.NotNull(xform, nameof(xform));
 
 
             var n = primitive.GetNormal(idx);
             var n = primitive.GetNormal(idx);
@@ -166,7 +166,7 @@ namespace SharpGLTF.Runtime
         public static XYZW GetTangent(this IMeshPrimitiveDecoder primitive, int idx, Transforms.IGeometryTransform xform)
         public static XYZW GetTangent(this IMeshPrimitiveDecoder primitive, int idx, Transforms.IGeometryTransform xform)
         {
         {
             Guard.NotNull(primitive, nameof(primitive));
             Guard.NotNull(primitive, nameof(primitive));
-            Guard.MustBeBetweenOrEqualTo(idx, 0, primitive.VertexCount + 1, nameof(idx));
+            Guard.MustBeBetweenOrEqualTo(idx, 0, primitive.VertexCount - 1, nameof(idx));
             Guard.NotNull(xform, nameof(xform));
             Guard.NotNull(xform, nameof(xform));
 
 
             var t = primitive.GetTangent(idx);
             var t = primitive.GetTangent(idx);
@@ -176,6 +176,34 @@ namespace SharpGLTF.Runtime
             return xform.TransformTangent(t, d, w);
             return xform.TransformTangent(t, d, w);
         }
         }
 
 
+        public static XY GetTextureCoord(this IMeshPrimitiveDecoder primitive, int idx, int textureSetIndex,
+            IMaterialTransform xform)
+        {
+            Guard.NotNull(primitive, nameof(primitive));
+            Guard.MustBeBetweenOrEqualTo(idx, 0, primitive.VertexCount - 1, nameof(idx));
+            Guard.MustBeBetweenOrEqualTo(textureSetIndex, 0, primitive.TexCoordsCount - 1, nameof(textureSetIndex));
+            Guard.NotNull(xform, nameof(xform));
+
+            var tc = primitive.GetTextureCoord(idx, textureSetIndex);
+            var tcd = primitive.GetTextureCoordDeltas(idx, textureSetIndex);
+
+            return xform.MorphTexCoord(tc, tcd);
+        }
+
+        public static XYZW GetColor(this IMeshPrimitiveDecoder primitive, int idx, int colorSetIndex,
+            IMaterialTransform xform)
+        {
+            Guard.NotNull(primitive, nameof(primitive));
+            Guard.MustBeBetweenOrEqualTo(idx, 0, primitive.VertexCount - 1, nameof(idx));
+            Guard.MustBeBetweenOrEqualTo(colorSetIndex, 0, primitive.ColorsCount - 1, nameof(colorSetIndex));
+            Guard.NotNull(xform, nameof(xform));
+
+            var c = primitive.GetColor(idx, colorSetIndex);
+            var cd = primitive.GetColorDeltas(idx, colorSetIndex);
+
+            return xform.MorphColors(c, cd);
+        }
+
         public static (XYZ Min, XYZ Max) EvaluateBoundingBox(this Schema2.Scene scene, float samplingTimeStep = 1.0f)
         public static (XYZ Min, XYZ Max) EvaluateBoundingBox(this Schema2.Scene scene, float samplingTimeStep = 1.0f)
         {
         {
             Guard.NotNull(scene, nameof(scene));
             Guard.NotNull(scene, nameof(scene));

+ 100 - 0
tests/SharpGLTF.ThirdParty.Tests/PetarTasevTests.cs

@@ -0,0 +1,100 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Numerics;
+using NUnit.Framework;
+using SharpGLTF.Geometry;
+using SharpGLTF.Geometry.VertexTypes;
+using SharpGLTF.Materials;
+using SharpGLTF.Schema2;
+using SharpGLTF.Validation;
+
+namespace SharpGLTF.ThirdParty
+{
+    using VBColor1 = VertexBuilder<VertexPosition,VertexColor1,VertexEmpty>;
+    
+    [ResourcePathFormat("*\\Assets")]
+    [AttachmentPathFormat("*\\?")]
+    public class PetarTasevTests
+    {
+        [Test]
+        public void MorphColor_MultiplePrimitives()
+        {
+            // create material
+            var material = new MaterialBuilder("mat1")
+                .WithDoubleSide(true)
+                .WithMetallicRoughnessShader();
+            var material2 = new MaterialBuilder("mat2")
+                .WithDoubleSide(true)
+                .WithMetallicRoughnessShader();
+
+            // create a mesh with two primitives, one for each material
+
+            var triangle = new MeshBuilder<VertexPosition, VertexColor1>("mesh");
+
+            var prim = triangle.UsePrimitive(material);
+            var redColor = new Vector4(1f, 0f, 0f, 1f);
+            prim.AddTriangle(new VBColor1(new VertexPosition(-10, 0, 0), redColor),
+                new VBColor1(new VertexPosition(10, 0, 0), redColor),
+                new VBColor1(new VertexPosition(0, 10, 0), redColor));
+            
+            var prim2 = triangle.UsePrimitive(material2);
+            prim2.AddTriangle(new VBColor1(new VertexPosition(-10, 0, 0), redColor),
+                new VBColor1(new VertexPosition(10, 0, 0), redColor),
+                new VBColor1(new VertexPosition(0, 10, 0), redColor));
+
+            // create a morph target that will change the color from red to green only for prim2
+            var greenColor = new Vector4(0f, 1f, 0f, 1f);
+            foreach (var p in triangle.Primitives)
+            {
+                for (var i = 0; i < p.Vertices.Count; ++i)
+                {
+                    var oldVertexPosition = p.Vertices[i];
+                    var greenMat = new VertexColor1(greenColor);
+
+                    ((IPrimitiveBuilder)p).SetVertexDelta(0, i, default,
+                        ReferenceEquals(p, prim2)
+                            ? greenMat.Subtract(oldVertexPosition.Material)
+                            : VertexMaterialDelta.Zero);
+                }
+            }
+
+            // create a scene
+            var scene = new Scenes.SceneBuilder();
+            scene.AddRigidMesh(triangle, Matrix4x4.Identity);
+
+            // save the model in different formats
+            var model = scene.ToGltf2();
+            var animation = model.CreateAnimation();
+
+            // create a morph channel
+            animation.CreateMorphChannel(model.LogicalNodes[0],
+                new Dictionary<float, float[]>
+                {
+                    { 0f, new[] { 0f } },
+                    { 1f, new[] { 1f } }
+                }, 1);
+
+            // evaluate triangles at animation 0.5, and get the color of the first pixel of the first triangle
+            var triangles = model.DefaultScene
+                .EvaluateTriangles(null, model.LogicalAnimations[0], 0.5f)
+                .ToArray();
+            var expMorphColor = Vector4.Lerp(redColor, greenColor, 0.5f);
+
+            // Assert
+            var morphedColor = triangles[1].A.GetMaterial().GetColor(0);
+            Assert.AreEqual(expMorphColor, morphedColor);
+            
+            morphedColor = triangles[0].A.GetMaterial().GetColor(0);
+            Assert.AreEqual(redColor, morphedColor);
+
+            // save the model in different formats
+            AttachmentInfo
+                .From("ColorMorphingMultiPrim.glb")
+                .WriteFile(f => model.Save(f.FullName, new WriteSettings() { Validation = ValidationMode.Skip }));
+
+            AttachmentInfo
+                .From("ColorMorphingMultiPrim.gltf")
+                .WriteFile(f => model.Save(f.FullName, new WriteSettings() { Validation = ValidationMode.Skip }));
+        }
+    }
+}