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 allowVertex) - { - for (int i = 0; i < allowVertex.Length; ++i) - { - AllowVertex[i] = allowVertex[i] != 0; - } - } - internal DebugStep(EdgeEndpoints sourceEdge, QuickList rawVertexIndices, Vector3 faceNormal, Vector3 basisX, Vector3 basisY, QuickList reducedVertexIndices, Buffer allowVertex, QuickList faces, int faceIndex) + + internal DebugStep(EdgeEndpoints sourceEdge, QuickList rawVertexIndices, Vector3 faceNormal, Vector3 basisX, Vector3 basisY, QuickList reducedVertexIndices, int faceIndex) { SourceEdge = sourceEdge; FaceNormal = faceNormal; BasisX = basisX; BasisY = basisY; - ((Span)rawVertexIndices).ToArray(); - ((Span)reducedVertexIndices).ToArray(); - MergedRaw = null; - MergedReduced = null; - AllowVertex = new bool[allowVertex.Length]; - FillAllowVertex(allowVertex); + Raw = ((Span)rawVertexIndices).ToArray(); + Reduced = ((Span)reducedVertexIndices).ToArray(); + RawOverwrittenByMerge = null; + ReducedOverwrittenByMerge = null; + FaceIndex = faceIndex; + } + + internal DebugStep FillHistory(Buffer allowVertex, QuickList faces) + { FaceStarts = new List(faces.Count); FaceIndices = new List(); FaceNormals = new Vector3[faces.Count]; @@ -567,14 +564,20 @@ internal DebugStep(EdgeEndpoints sourceEdge, QuickList 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 rawFaceVertexIndices, QuickList reducedVertexIndices, Buffer allowVertex, int mergedFaceIndex) { - MergedRaw = ((Span)rawFaceVertexIndices).ToArray(); - MergedReduced = ((Span)reducedVertexIndices).ToArray(); - FillAllowVertex(allowVertex); + RawOverwrittenByMerge = Raw; + ReducedOverwrittenByMerge = Reduced; + Raw = ((Span)rawFaceVertexIndices).ToArray(); + Reduced = ((Span)reducedVertexIndices).ToArray(); FaceIndex = mergedFaceIndex; } } @@ -755,7 +758,7 @@ public static void ComputeHull(Span 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 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 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);