From a58d9af990ddac9bc4725059c561a9c5146d85ca Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Tue, 2 Dec 2025 05:38:32 +0100 Subject: [PATCH] fix: Regression in mesh bounds calculation introduced through #2858 Reverts the method to what it was before #2858. This fix is not necessary on main branch where it was already applied by 8e791ad6b56356a5776e28ccbfde89714acee7a8. However that fix is not applicable on 4.2 branch because it needs .net10. --- .../Extensions/BoundingExtensions.cs | 68 +++++++++---------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/sources/engine/Stride.Rendering/Extensions/BoundingExtensions.cs b/sources/engine/Stride.Rendering/Extensions/BoundingExtensions.cs index 951739a582..87ea19c6d8 100644 --- a/sources/engine/Stride.Rendering/Extensions/BoundingExtensions.cs +++ b/sources/engine/Stride.Rendering/Extensions/BoundingExtensions.cs @@ -6,73 +6,69 @@ using Stride.Core.Mathematics; using Stride.Graphics; using Stride.Graphics.Data; -using Stride.Graphics.Semantics; namespace Stride.Extensions { public static class BoundingExtensions { - public static BoundingBox ComputeBounds(this VertexBufferBinding vertexBufferBinding, ref Matrix matrix, out BoundingSphere boundingSphere) + public static unsafe BoundingBox ComputeBounds(this VertexBufferBinding vertexBufferBinding, ref Matrix matrix, out BoundingSphere boundingSphere) { - var helper = new VertexBufferHelper(vertexBufferBinding, vertexBufferBinding.Buffer.GetSerializationData().Content, out _); + var positionOffset = vertexBufferBinding.Declaration + .EnumerateWithOffsets() + .First(x => x.VertexElement.SemanticAsText == "POSITION") + .Offset; - var computeBoundsStruct = new ComputeBoundsStruct - { - Box = BoundingBox.Empty, - Sphere = new BoundingSphere(), - Matrix = matrix - }; - helper.Read(default, computeBoundsStruct); - - boundingSphere = computeBoundsStruct.Sphere; - return computeBoundsStruct.Box; - } - - struct ComputeBoundsStruct : VertexBufferHelper.IReader - { - public required BoundingBox Box; - public required BoundingSphere Sphere; - public required Matrix Matrix; + var boundingBox = BoundingBox.Empty; + boundingSphere = new BoundingSphere(); - public unsafe void Read(byte* startPointer, int elementCount, int stride, Span destination) where TConverter : IConverter where TSource : unmanaged + var vertexStride = vertexBufferBinding.Declaration.VertexStride; + fixed (byte* bufferStart = &vertexBufferBinding.Buffer.GetSerializationData().Content[vertexBufferBinding.Offset]) { // Calculates bounding box and bounding sphere center - for (byte* sourcePtr = startPointer, end = startPointer + elementCount * stride; sourcePtr < end; sourcePtr += stride) + byte* buffer = bufferStart + positionOffset; + for (int i = 0; i < vertexBufferBinding.Count; ++i) { - TConverter.Convert(*(TSource*)sourcePtr, out var position); + var position = (Vector3*)buffer; Vector3 transformedPosition; - Vector3.TransformCoordinate(ref position, ref Matrix, out transformedPosition); + Vector3.TransformCoordinate(ref *position, ref matrix, out transformedPosition); // Prepass calculate the center of the sphere - Vector3.Add(ref transformedPosition, ref Sphere.Center, out Sphere.Center); - - BoundingBox.Merge(ref Box, ref transformedPosition, out Box); + Vector3.Add(ref transformedPosition, ref boundingSphere.Center, out boundingSphere.Center); + + BoundingBox.Merge(ref boundingBox, ref transformedPosition, out boundingBox); + + buffer += vertexStride; } //This is the center of our sphere. - Sphere.Center /= elementCount; + boundingSphere.Center /= (float)vertexBufferBinding.Count; // Calculates bounding sphere center - for (byte* sourcePtr = startPointer, end = startPointer + elementCount * stride; sourcePtr < end; sourcePtr += stride) + buffer = bufferStart + positionOffset; + for (int i = 0; i < vertexBufferBinding.Count; ++i) { - TConverter.Convert(*(TSource*)sourcePtr, out var position); + var position = (Vector3*)buffer; Vector3 transformedPosition; - Vector3.TransformCoordinate(ref position, ref Matrix, out transformedPosition); + Vector3.TransformCoordinate(ref *position, ref matrix, out transformedPosition); - //We are doing a relative distance comparison to find the maximum distance + //We are doing a relative distance comparasin to find the maximum distance //from the center of our sphere. float distance; - Vector3.DistanceSquared(ref Sphere.Center, ref transformedPosition, out distance); + Vector3.DistanceSquared(ref boundingSphere.Center, ref transformedPosition, out distance); - if (distance > Sphere.Radius) - Sphere.Radius = distance; + if (distance > boundingSphere.Radius) + boundingSphere.Radius = distance; + + buffer += vertexStride; } //Find the real distance from the DistanceSquared. - Sphere.Radius = MathF.Sqrt(Sphere.Radius); + boundingSphere.Radius = MathF.Sqrt(boundingSphere.Radius); } + + return boundingBox; } } }