Skip to content

Commit

Permalink
Relaxed accessor validation to let some new valid tests to pass.
Browse files Browse the repository at this point in the history
  • Loading branch information
vpenades committed Dec 2, 2023
1 parent 6fc681f commit 681b03b
Showing 1 changed file with 25 additions and 24 deletions.
49 changes: 25 additions & 24 deletions src/SharpGLTF.Core/Schema2/gltf.MeshPrimitive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -375,38 +375,39 @@ protected override void OnValidateContent(Validation.ValidationContext validate)
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.");
}
}
}

Expand Down

0 comments on commit 681b03b

Please sign in to comment.