From d5a9e8343941cd2f43947b7f4725cce475701081 Mon Sep 17 00:00:00 2001
From: Ross Nordby <norbo@bepuentertainment.com>
Date: Sat, 16 Nov 2024 17:52:00 -0600
Subject: [PATCH] Debug fixes.

---
 BepuPhysics/Collidables/ConvexHullHelper.cs  | 52 +++++++------
 Demos/SpecializedTests/ConvexHullTestDemo.cs | 81 +++++++++-----------
 2 files changed, 63 insertions(+), 70 deletions(-)

diff --git a/BepuPhysics/Collidables/ConvexHullHelper.cs b/BepuPhysics/Collidables/ConvexHullHelper.cs
index 12e7f715..4560f188 100644
--- a/BepuPhysics/Collidables/ConvexHullHelper.cs
+++ b/BepuPhysics/Collidables/ConvexHullHelper.cs
@@ -526,8 +526,8 @@ public struct DebugStep
             public EdgeEndpoints SourceEdge;
             public int[] Raw;
             public int[] Reduced;
-            public int[] MergedRaw;
-            public int[] MergedReduced;
+            public int[] RawOverwrittenByMerge;
+            public int[] ReducedOverwrittenByMerge;
             public bool[] AllowVertex;
             public Vector3 FaceNormal;
             public Vector3 BasisX;
@@ -537,25 +537,22 @@ public struct DebugStep
             public int FaceIndex;
             public Vector3[] FaceNormals;
 
-            void FillAllowVertex(Buffer<int> allowVertex)
-            {
-                for (int i = 0; i < allowVertex.Length; ++i)
-                {
-                    AllowVertex[i] = allowVertex[i] != 0;
-                }
-            }
-            internal DebugStep(EdgeEndpoints sourceEdge, QuickList<int> rawVertexIndices, Vector3 faceNormal, Vector3 basisX, Vector3 basisY, QuickList<int> reducedVertexIndices, Buffer<int> allowVertex, QuickList<EarlyFace> faces, int faceIndex)
+
+            internal DebugStep(EdgeEndpoints sourceEdge, QuickList<int> rawVertexIndices, Vector3 faceNormal, Vector3 basisX, Vector3 basisY, QuickList<int> reducedVertexIndices, int faceIndex)
             {
                 SourceEdge = sourceEdge;
                 FaceNormal = faceNormal;
                 BasisX = basisX;
                 BasisY = basisY;
-                ((Span<int>)rawVertexIndices).ToArray();
-                ((Span<int>)reducedVertexIndices).ToArray();
-                MergedRaw = null;
-                MergedReduced = null;
-                AllowVertex = new bool[allowVertex.Length];
-                FillAllowVertex(allowVertex);
+                Raw = ((Span<int>)rawVertexIndices).ToArray();
+                Reduced = ((Span<int>)reducedVertexIndices).ToArray();
+                RawOverwrittenByMerge = null;
+                ReducedOverwrittenByMerge = null;      
+                FaceIndex = faceIndex;
+            }
+
+            internal DebugStep FillHistory(Buffer<int> allowVertex, QuickList<EarlyFace> faces)
+            {
                 FaceStarts = new List<int>(faces.Count);
                 FaceIndices = new List<int>();
                 FaceNormals = new Vector3[faces.Count];
@@ -567,14 +564,20 @@ internal DebugStep(EdgeEndpoints sourceEdge, QuickList<int> rawVertexIndices, Ve
                         FaceIndices.Add(face.VertexIndices[j]);
                     FaceNormals[i] = face.Normal;
                 }
-                FaceIndex = faceIndex;
+                AllowVertex = new bool[allowVertex.Length]; 
+                for (int i = 0; i < allowVertex.Length; ++i)
+                {
+                    AllowVertex[i] = allowVertex[i] != 0;
+                }
+                return this;
             }
 
             internal void UpdateForFaceMerge(QuickList<int> rawFaceVertexIndices, QuickList<int> reducedVertexIndices, Buffer<int> allowVertex, int mergedFaceIndex)
             {
-                MergedRaw = ((Span<int>)rawFaceVertexIndices).ToArray();
-                MergedReduced = ((Span<int>)reducedVertexIndices).ToArray();
-                FillAllowVertex(allowVertex);
+                RawOverwrittenByMerge = Raw;
+                ReducedOverwrittenByMerge = Reduced;
+                Raw = ((Span<int>)rawFaceVertexIndices).ToArray();
+                Reduced = ((Span<int>)reducedVertexIndices).ToArray();
                 FaceIndex = mergedFaceIndex;
             }
         }
@@ -755,7 +758,7 @@ public static void ComputeHull(Span<Vector3> points, BufferPool pool, out HullDa
             }
             Vector3Wide.ReadFirst(initialBasisX, out var debugInitialBasisX);
             Vector3Wide.ReadFirst(initialBasisY, out var debugInitialBasisY);
-            steps.Add(new DebugStep(initialSourceEdge, rawFaceVertexIndices, initialFaceNormal, debugInitialBasisX, debugInitialBasisY, reducedFaceIndices, allowVertices, faces, reducedFaceIndices.Count >= 3 ? 0 : -1));
+            steps.Add(new DebugStep(initialSourceEdge, rawFaceVertexIndices, initialFaceNormal, debugInitialBasisX, debugInitialBasisY, reducedFaceIndices, reducedFaceIndices.Count >= 3 ? 0 : -1).FillHistory(allowVertices, faces));
 
             while (edgesToTest.Count > 0)
             {
@@ -782,14 +785,13 @@ public static void ComputeHull(Span<Vector3> points, BufferPool pool, out HullDa
 
                 if (reducedFaceIndices.Count < 3)
                 {
-                    steps.Add(new DebugStep(edgeToTest.Endpoints, rawFaceVertexIndices, faceNormal, basisX, basisY, reducedFaceIndices, allowVertices, faces, -1));
+                    steps.Add(new DebugStep(edgeToTest.Endpoints, rawFaceVertexIndices, faceNormal, basisX, basisY, reducedFaceIndices, -1).FillHistory(allowVertices, faces));
                     //Degenerate face found; don't bother creating work for it.
                     continue;
                 }
                 // Brute force scan all the faces to see if the new face is coplanar with any of them.
+                var step = new DebugStep(edgeToTest.Endpoints, rawFaceVertexIndices, faceNormal, basisX, basisY, reducedFaceIndices, faces.Count);
                 Console.WriteLine($"step count: {steps.Count}");
-                var step = new DebugStep(edgeToTest.Endpoints, rawFaceVertexIndices, faceNormal, basisX, basisY, reducedFaceIndices, allowVertices, faces, faces.Count);
-                steps.Add(step);
                 bool mergedFace = false;
                 for (int i = 0; i < faces.Count; ++i)
                 {
@@ -828,6 +830,8 @@ public static void ComputeHull(Span<Vector3> points, BufferPool pool, out HullDa
                     AddFace(ref faces, pool, faceNormal, reducedFaceIndices);
                     AddFaceEdgesToTestList(pool, ref reducedFaceIndices, ref edgesToTest, ref submittedEdgeTests, faceNormal, faceCountPriorToAdd);
                 }
+                step.FillHistory(allowVertices, faces);
+                steps.Add(step);
 
                 if (steps.Count > 500)
                     break;
diff --git a/Demos/SpecializedTests/ConvexHullTestDemo.cs b/Demos/SpecializedTests/ConvexHullTestDemo.cs
index 3a83ed29..4ce7a485 100644
--- a/Demos/SpecializedTests/ConvexHullTestDemo.cs
+++ b/Demos/SpecializedTests/ConvexHullTestDemo.cs
@@ -736,18 +736,7 @@ void DrawVertexIndex(int i, Vector3 color, Vector2 offset = default)
         }
         if (showFaceVertexStatuses)
         {
-            int[] raw, reduced;
-            if (step.MergedRaw == null)
-            {
-                raw = step.Raw;
-                reduced = step.Reduced;
-            }
-            else
-            {
-                raw = step.MergedRaw;
-                reduced = step.MergedReduced;
-            }
-            for (int i = 0; i < raw.Length; ++i)
+            for (int i = 0; i < step.Raw.Length; ++i)
             {
                 var color = new Vector3(0.3f, 0.3f, 1);
                 var pose = new RigidPose(renderOffset + points[step.Raw[i]] * scale);
@@ -755,7 +744,7 @@ void DrawVertexIndex(int i, Vector3 color, Vector2 offset = default)
                 if (showVertexIndices)
                     DrawVertexIndex(step.Raw[i], color, new Vector2(0, 2));
             }
-            for (int i = 0; i < reduced.Length; ++i)
+            for (int i = 0; i < step.Reduced.Length; ++i)
             {
                 var color = new Vector3(0, 1, 0);
                 var pose = new RigidPose(renderOffset + points[step.Reduced[i]] * scale);
@@ -767,49 +756,48 @@ void DrawVertexIndex(int i, Vector3 color, Vector2 offset = default)
 
         {
             var pose = new RigidPose(renderOffset);
-            for (int i = 0; i < step.FaceStarts.Count; ++i)
+            void DrawFace(DebugStep step, int[] raw, int[] reduced, bool deleted, int i)
             {
-                if (showDeleted || !step.FaceDeleted[i])
+                var color = deleted ? new Vector3(0.25f, 0.25f, 0.25f) : stepIndex == i ? new Vector3(1, 0, 0.5f) : new Vector3(1, 0, 1);
+                var deletionInducedScale = deleted ? new Vector3(1.1f) : new Vector3(1f);
+
+                var offset = deleted ? step.FaceNormal * 0.25f : new Vector3();
+                if (showWireframe)
                 {
-                    var faceStart = step.FaceStarts[i];
-                    var faceEnd = i + 1 < step.FaceStarts.Count ? step.FaceStarts[i + 1] : step.FaceIndices.Count;
-                    var count = faceEnd - faceStart;
-                    var color = step.FaceDeleted[i] ? new Vector3(0.25f, 0.25f, 0.25f) : step.FaceIndex == i ? new Vector3(1, 0, 0.5f) : new Vector3(1, 0, 1);
-                    var deletionInducedScale = step.FaceDeleted[i] ? new Vector3(1.1f) : new Vector3(1f);
-
-                    var offset = step.FaceDeleted[i] ? step.FaceNormals[i] * 0.25f : new Vector3();
-                    if (showWireframe)
+                    var previousIndex = reduced.Length - 1;
+                    for (int q = 0; q < reduced.Length; ++q)
                     {
-                        var previousIndex = faceEnd - 1;
-                        for (int q = faceStart; q < faceEnd; ++q)
-                        {
-                            var a = points[step.FaceIndices[q]] * scale + pose.Position + offset;
-                            var b = points[step.FaceIndices[previousIndex]] * scale + pose.Position + offset;
-                            previousIndex = q;
-                            renderer.Lines.Allocate() = new LineInstance(a, b, color, Vector3.Zero);
-                        }
+                        var a = points[reduced[q]] * scale + pose.Position + offset;
+                        var b = points[reduced[previousIndex]] * scale + pose.Position + offset;
+                        previousIndex = q;
+                        renderer.Lines.Allocate() = new LineInstance(a, b, color, Vector3.Zero);
                     }
-                    else
+                }
+                else
+                {
+                    for (int k = 2; k < reduced.Length; ++k)
                     {
-                        for (int k = faceStart + 2; k < faceEnd; ++k)
+                        renderer.Shapes.AddShape(new Triangle
                         {
-                            renderer.Shapes.AddShape(new Triangle
-                            {
-                                A = points[step.FaceIndices[faceStart]] * scale + offset,
-                                B = points[step.FaceIndices[k]] * scale + offset,
-                                C = points[step.FaceIndices[k - 1]] * scale + offset
-                            }, Simulation.Shapes, pose, color);
-                        }
+                            A = points[reduced[0]] * scale + offset,
+                            B = points[reduced[k]] * scale + offset,
+                            C = points[reduced[k - 1]] * scale + offset
+                        }, Simulation.Shapes, pose, color);
                     }
                 }
             }
-        }
-        //Console.WriteLine("Current step edges: ");
-        //for (int i = 0; i < step.Reduced.Count; ++i)
-        //{
-        //    Console.WriteLine($"  Edge {i}: ({step.Reduced[i]}, {step.Reduced[(i + 1) % step.Reduced.Count]})");
-        //}
+            for (int i = 0; i <= stepIndex; ++i)
+            {
+                var localStep = debugSteps[i];
+                DrawFace(localStep, localStep.Raw, localStep.Reduced, false, i);
+                if (localStep.RawOverwrittenByMerge != null)
+                {
+                    DrawFace(localStep, localStep.RawOverwrittenByMerge, localStep.ReducedOverwrittenByMerge, true, i);
+                }
 
+            }
+        }
+        Console.WriteLine($"face count: {step.FaceStarts.Count}");
 
         if (showVertexIndices)
         {
@@ -829,6 +817,7 @@ void DrawVertexIndex(int i, Vector3 color, Vector2 offset = default)
         renderer.TextBatcher.Write(text.Clear().Append("Show deleted: U ").Append(showDeleted ? "(on)" : "(off)"), new Vector2(32, renderer.Surface.Resolution.Y - 100), 20, new Vector3(1), font);
         renderer.TextBatcher.Write(text.Clear().Append("Show vertex indices: Y ").Append(showVertexIndices ? "(on)" : "(off)"), new Vector2(32, renderer.Surface.Resolution.Y - 80), 20, new Vector3(1), font);
         renderer.TextBatcher.Write(text.Clear().Append("Show face vertex statuses: H ").Append(showFaceVertexStatuses ? "(on)" : "(off)"), new Vector2(32, renderer.Surface.Resolution.Y - 60), 20, new Vector3(1), font);
+        renderer.TextBatcher.Write(text.Clear().Append("Face count: ").Append(step.FaceStarts.Count), new Vector2(32, renderer.Surface.Resolution.Y - 20), 20, new Vector3(1), font);
 
 
         base.Render(renderer, camera, input, text, font);