Browse Source

more validations and tests

Vicente Penades 6 years ago
parent
commit
3483a205b2

+ 2 - 2
src/Shared/_Extensions.cs

@@ -325,10 +325,10 @@ namespace SharpGLTF
 
 
         public static IEnumerable<(int, int, int)> GetTrianglesIndices(this PrimitiveType ptype, int count)
         public static IEnumerable<(int, int, int)> GetTrianglesIndices(this PrimitiveType ptype, int count)
         {
         {
-            return ptype.GetTrianglesIndices(Enumerable.Range(0, count).Select(item => (UInt32)item), IndexEncodingType.UNSIGNED_INT);
+            return ptype.GetTrianglesIndices(Enumerable.Range(0, count).Select(item => (UInt32)item));
         }
         }
 
 
-        public static IEnumerable<(int, int, int)> GetTrianglesIndices(this PrimitiveType ptype, IEnumerable<UInt32> sourceIndices, IndexEncodingType sourceEncoding)
+        public static IEnumerable<(int, int, int)> GetTrianglesIndices(this PrimitiveType ptype, IEnumerable<UInt32> sourceIndices)
         {
         {
             switch (ptype)
             switch (ptype)
             {
             {

+ 38 - 0
src/SharpGLTF.Core/Schema2/gltf.Accessors.cs

@@ -387,6 +387,44 @@ namespace SharpGLTF.Schema2
             }
             }
         }
         }
 
 
+        internal void ValidateIndices(IList<Exception> result, uint vertexCount, PrimitiveType drawingType)
+        {
+            switch (drawingType)
+            {
+                case PrimitiveType.LINE_LOOP:
+                case PrimitiveType.LINE_STRIP:
+                    if (this.Count < 2) result.Add(new EXCEPTION(this, $"Indices count {this.Count} is less than 2"));
+                    break;
+
+                case PrimitiveType.TRIANGLE_FAN:
+                case PrimitiveType.TRIANGLE_STRIP:
+                    if (this.Count < 3) result.Add(new EXCEPTION(this, $"Indices count {this.Count} is less than 3"));
+                    break;
+
+                case PrimitiveType.LINES:
+                    if (!this.Count.IsMultipleOf(2)) result.Add(new EXCEPTION(this, $"Indices count {this.Count} incompatible with Primitive.{drawingType}"));
+                    break;
+
+                case PrimitiveType.TRIANGLES:
+                    if (!this.Count.IsMultipleOf(3)) result.Add(new EXCEPTION(this, $"Indices count {this.Count} incompatible with Primitive.{drawingType}"));
+                    break;
+            }
+
+            uint restart_value = 0xff;
+            if (this.Encoding == EncodingType.UNSIGNED_SHORT) restart_value = 0xffff;
+            if (this.Encoding == EncodingType.UNSIGNED_INT) restart_value = 0xffffffff;
+
+            var indices = this.AsIndicesArray();
+
+            for (int i = 0; i < indices.Count; ++i)
+            {
+                var idx = indices[i];
+
+                if (idx == restart_value) result.Add(new EXCEPTION(this, $"PRIMITIVE RESTART value {restart_value} found at index {i}"));
+                else if (idx >= vertexCount) result.Add(new EXCEPTION(this, $"Invalid vertex index {idx} found at index {i}"));
+            }
+        }
+
         #endregion
         #endregion
     }
     }
 
 

+ 3 - 4
src/SharpGLTF.Core/Schema2/gltf.Asset.cs

@@ -46,6 +46,7 @@ namespace SharpGLTF.Schema2
 
 
         private static readonly Version ZEROVERSION = new Version(0, 0);
         private static readonly Version ZEROVERSION = new Version(0, 0);
         private static readonly Version MINVERSION = new Version(2, 0);
         private static readonly Version MINVERSION = new Version(2, 0);
+        private static readonly Version MAXVERSION = new Version(2, 0);
 
 
         public string Copyright { get => _copyright; set => _copyright = value.AsEmptyNullable(); }
         public string Copyright { get => _copyright; set => _copyright = value.AsEmptyNullable(); }
         public string Generator { get => _generator; set => _generator = value.AsEmptyNullable(); }
         public string Generator { get => _generator; set => _generator = value.AsEmptyNullable(); }
@@ -74,10 +75,8 @@ namespace SharpGLTF.Schema2
 
 
             if (string.IsNullOrWhiteSpace(_version)) result.Add(new EXCEPTION(this, "version number is missing"));
             if (string.IsNullOrWhiteSpace(_version)) result.Add(new EXCEPTION(this, "version number is missing"));
 
 
-            var curVer = this.Version;
-            var minVer = this.MinVersion;
-
-            if (curVer < minVer) result.Add(new EXCEPTION(this, $"invalid version number {this.Version} expected {MINVERSION}"));
+            if (Version < MINVERSION) result.Add(new EXCEPTION(this, $"Minimum supported version is {MINVERSION} but found:{MinVersion}"));
+            if (MinVersion > MAXVERSION) result.Add(new EXCEPTION(this, $"Maximum supported version is {MAXVERSION} but found:{MinVersion}"));
         }
         }
 
 
         private string _GetExtraInfo(string key)
         private string _GetExtraInfo(string key)

+ 9 - 9
src/SharpGLTF.Core/Schema2/gltf.MeshPrimitive.cs

@@ -201,15 +201,15 @@ namespace SharpGLTF.Schema2
         {
         {
             base.Validate(result);
             base.Validate(result);
 
 
-            if (IndexAccessor != null)
-            {
-                switch (DrawPrimitiveType)
-                {
-                    case PrimitiveType.TRIANGLES:
-                        if ((IndexAccessor.Count % 3) != 0) result.Add(new EXCEPTION(this, $"Indices count {IndexAccessor.Count} incompatible with Primitive.{DrawPrimitiveType}"));
-                        break;
-                }
-            }
+            var vertexCounts = VertexAccessors
+                .Select(item => item.Value.Count)
+                .Distinct();
+
+            if (vertexCounts.Count() != 1) result.Add(new EXCEPTION(this, $"Vertex Accessors have mismatching vertices count."));
+
+            var vertexCount = (uint)vertexCounts.First();
+
+            if (IndexAccessor != null) IndexAccessor.ValidateIndices(result, vertexCount, DrawPrimitiveType);
         }
         }
 
 
         #endregion
         #endregion

+ 1 - 1
src/SharpGLTF.Toolkit/Schema2/MeshExtensions.cs

@@ -348,7 +348,7 @@ namespace SharpGLTF.Schema2
         {
         {
             if (primitive.IndexAccessor == null) return primitive.DrawPrimitiveType.GetTrianglesIndices(primitive.GetVertexAccessor("POSITION").Count);
             if (primitive.IndexAccessor == null) return primitive.DrawPrimitiveType.GetTrianglesIndices(primitive.GetVertexAccessor("POSITION").Count);
 
 
-            return primitive.DrawPrimitiveType.GetTrianglesIndices(primitive.IndexAccessor.AsIndicesArray(), primitive.IndexAccessor.Encoding.ToIndex());
+            return primitive.DrawPrimitiveType.GetTrianglesIndices(primitive.IndexAccessor.AsIndicesArray());
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 51 - 1
tests/SharpGLTF.Tests/Schema2/LoadAndSave/LoadGeneratedTests.cs

@@ -24,7 +24,7 @@ namespace SharpGLTF.Schema2.LoadAndSave
         #endregion        
         #endregion        
 
 
         [Test]
         [Test]
-        public void TestLoadReferenceModels()
+        public void TestLoadPositiveModels()
         {
         {
             TestContext.CurrentContext.AttachShowDirLink();
             TestContext.CurrentContext.AttachShowDirLink();
 
 
@@ -72,5 +72,55 @@ namespace SharpGLTF.Schema2.LoadAndSave
 
 
             Assert.IsTrue(passed);
             Assert.IsTrue(passed);
         }
         }
+
+        [Test]
+        public void TestLoadNegativeModels()
+        {
+            TestContext.CurrentContext.AttachShowDirLink();
+
+            var files = TestFiles.GetReferenceModelPaths(true);
+
+            bool passed = true;
+
+            foreach (var f in files)
+            {
+                try
+                {
+                    var model = ModelRoot.Load(f.Item1);
+
+                    if (!f.Item2)
+                    {
+                        TestContext.Error.WriteLine($"{f.Item1.ToShortDisplayPath()} 👎😦 Should not load!");
+                        passed = false;
+                    }
+                    else
+                    {
+                        TestContext.WriteLine($"{f.Item1.ToShortDisplayPath()} 🙂👍");
+                    }
+                }
+                catch (Exception ex)
+                {
+                    if (f.Item2)
+                    {
+                        TestContext.Error.WriteLine($"{f.Item1.ToShortDisplayPath()} 👎😦 Should load!");
+                        TestContext.Error.WriteLine($"   ERROR: {ex.Message}");
+                        passed = false;
+                    }
+                    else
+                    {
+                        TestContext.WriteLine($"{f.Item1.ToShortDisplayPath()} 🙂👍");
+                        TestContext.WriteLine($"   Exception: {ex.Message}");
+                    }
+                }
+
+                if (f.Item2 && !f.Item1.ToLower().Contains("compatibility"))
+                {
+                    var model = ModelRoot.Load(f.Item1);
+                    model.AttachToCurrentTest(System.IO.Path.ChangeExtension(System.IO.Path.GetFileName(f.Item1), ".obj"));
+                }
+            }
+
+            Assert.IsTrue(passed);
+        }
     }
     }
 }
 }

+ 6 - 3
tests/SharpGLTF.Tests/TestFiles.cs

@@ -63,12 +63,12 @@ namespace SharpGLTF
             return GetModelPathsInDirectory(_SchemaDir, "extensions", "2.0");         
             return GetModelPathsInDirectory(_SchemaDir, "extensions", "2.0");         
         }
         }
 
 
-        public static IEnumerable<(string, bool)> GetReferenceModelPaths()
+        public static IEnumerable<(string, bool)> GetReferenceModelPaths(bool useNegative = false)
         {
         {
             var dirPath = _GeneratedModelsDir;
             var dirPath = _GeneratedModelsDir;
             if (dirPath.EndsWith(".zip")) dirPath = dirPath.Substring(0, dirPath.Length - 4);
             if (dirPath.EndsWith(".zip")) dirPath = dirPath.Substring(0, dirPath.Length - 4);
 
 
-            var manifestsPath = System.IO.Path.Combine(dirPath, "Positive");
+            var manifestsPath = System.IO.Path.Combine(dirPath, useNegative? "Negative" : "Positive");
 
 
             var manifests = System.IO.Directory.GetFiles(manifestsPath, "Manifest.json", System.IO.SearchOption.AllDirectories)
             var manifests = System.IO.Directory.GetFiles(manifestsPath, "Manifest.json", System.IO.SearchOption.AllDirectories)
                 .Skip(1)
                 .Skip(1)
@@ -86,7 +86,10 @@ namespace SharpGLTF
                 foreach(var model in models)
                 foreach(var model in models)
                 {
                 {
                     var mdlPath = (String)model.SelectToken("fileName");
                     var mdlPath = (String)model.SelectToken("fileName");
-                    var loadable = (Boolean)model.SelectToken("loadable");
+
+                    var loadable = !useNegative;
+
+                    if (loadable) loadable = (Boolean)model.SelectToken("loadable");
 
 
                     mdlPath = System.IO.Path.Combine(d, mdlPath);
                     mdlPath = System.IO.Path.Combine(d, mdlPath);