Browse Source

Relaxed accessor validation to let some new valid tests to pass.

vpenades 2 years ago
parent
commit
681b03b863
1 changed files with 25 additions and 24 deletions
  1. 25 24
      src/SharpGLTF.Core/Schema2/gltf.MeshPrimitive.cs

+ 25 - 24
src/SharpGLTF.Core/Schema2/gltf.MeshPrimitive.cs

@@ -375,38 +375,39 @@ namespace SharpGLTF.Schema2
                 validate.IsTrue(nameof(_indices), !incompatiblePrimitiveCount, "Mismatch between indices count and PrimitiveType");
             }
 
-            // check vertex attributes accessors ByteStride
+            // check access to shared BufferViews            
 
-            foreach (var group in this.VertexAccessors.Values.GroupBy(item => item.SourceBufferView))
-            {
-                if (!group.Skip(1).Any()) continue;
-
-                // if more than one accessor shares a BufferView, it must define a ByteStride
-
-                validate.IsGreater("ByteStride", group.Key.ByteStride, 0); // " must be defined when two or more accessors use the same BufferView."
+            var accessorsWithSharedBufferViews = this.VertexAccessors
+                .Values
+                .Distinct() // it is allowed that multiple attributes use the same accessor
+                .GroupBy(item => item.SourceBufferView);
 
-                // determine if we're sequential or strided by checking if the memory buffers overlap
-                var memories = group.Select(item => item._GetMemoryAccessor());
-                var overlap = Memory.MemoryAccessor.HaveOverlappingBuffers(memories);
+            foreach (var group in accessorsWithSharedBufferViews)
+            {
+                if (!group.Skip(1).Any()) continue; // buffer is not shared, skipping overlap tests
 
-                bool ok = false;
+                // if more than one accessor shares a BufferView, it can happen that:
+                // - ByteStride is 0, in which case access to the shared BufferView is sequential.
+                // - ByteStride is not 0, in which case access to the shared BufferView is interleaved.                
 
-                // strided buffer detected
-                if (overlap)
+                if (group.Key.ByteStride > 0)
                 {
-                    ok = group.Sum(item => item.Format.ByteSizePadded) <= group.Key.ByteStride;
+                    foreach(var item in group)
+                    {
+                        if (item.Format.ByteSizePadded > group.Key.ByteStride)
+                        {
+                            validate._LinkThrow("Attributes", $"Attribute element size {item.Format.ByteSizePadded} exceeds ByteStride {group.Key.ByteStride}");
+                        }                        
+                    }                    
                 }
-
-                // sequential buffer detected
                 else
                 {
-                    ok = group.All(item => item.Format.ByteSizePadded <= group.Key.ByteStride);
-                }
-
-                if (!ok)
-                {
-                    var accessors = string.Join(" ", group.Select(item => item.LogicalIndex));
-                    validate._LinkThrow("Attributes", $"Inconsistent accessors configuration: {accessors}");
+                    var memories = group.Select(item => item._GetMemoryAccessor());
+                    var overlap = Memory.MemoryAccessor.HaveOverlappingBuffers(memories);
+                    if (overlap)
+                    {
+                        validate._LinkThrow("Attributes", $"BufferView access is expected to be sequential, but some buffers overlap.");
+                    }
                 }
             }