diff --git a/BepuPhysics/Collidables/ConvexHullHelper.cs b/BepuPhysics/Collidables/ConvexHullHelper.cs index 834c68b0..12e7f715 100644 --- a/BepuPhysics/Collidables/ConvexHullHelper.cs +++ b/BepuPhysics/Collidables/ConvexHullHelper.cs @@ -475,7 +475,6 @@ public override string ToString() internal struct EarlyFace { public QuickList VertexIndices; - public bool Deleted; public Vector3 Normal; } @@ -526,35 +525,39 @@ public struct DebugStep { public EdgeEndpoints SourceEdge; public int[] Raw; - public int[] Premerged; public int[] Reduced; + public int[] MergedRaw; + public int[] MergedReduced; public bool[] AllowVertex; public Vector3 FaceNormal; public Vector3 BasisX; public Vector3 BasisY; public List FaceStarts; public List FaceIndices; - public bool[] FaceDeleted; public int FaceIndex; public Vector3[] FaceNormals; - internal DebugStep(EdgeEndpoints sourceEdge, ref QuickList raw, Vector3 faceNormal, Vector3 basisX, Vector3 basisY, ref QuickList reduced, ref Buffer allowVertex, ref QuickList faces, int faceIndex) + 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) { SourceEdge = sourceEdge; FaceNormal = faceNormal; BasisX = basisX; BasisY = basisY; - ((Span)raw).ToArray(); - ((Span)reduced).ToArray(); - Premerged = null; + ((Span)rawVertexIndices).ToArray(); + ((Span)reducedVertexIndices).ToArray(); + MergedRaw = null; + MergedReduced = null; AllowVertex = new bool[allowVertex.Length]; - for (int i = 0; i < allowVertex.Length; ++i) - { - AllowVertex[i] = allowVertex[i] != 0; - } + FillAllowVertex(allowVertex); FaceStarts = new List(faces.Count); FaceIndices = new List(); - FaceDeleted = new bool[faces.Count]; FaceNormals = new Vector3[faces.Count]; for (int i = 0; i < faces.Count; ++i) { @@ -562,16 +565,17 @@ internal DebugStep(EdgeEndpoints sourceEdge, ref QuickList raw, Vector3 fac FaceStarts.Add(FaceIndices.Count); for (int j = 0; j < face.VertexIndices.Count; ++j) FaceIndices.Add(face.VertexIndices[j]); - FaceDeleted[i] = face.Deleted; FaceNormals[i] = face.Normal; } FaceIndex = faceIndex; } - internal void UpdateForFaceMerge(Span mergedFaceIndices) + internal void UpdateForFaceMerge(QuickList rawFaceVertexIndices, QuickList reducedVertexIndices, Buffer allowVertex, int mergedFaceIndex) { - PremergeFaceIndices = this.MergedFaceIndices; - this.MergedFaceIndices = mergedFaceIndices.ToArray(); + MergedRaw = ((Span)rawFaceVertexIndices).ToArray(); + MergedReduced = ((Span)reducedVertexIndices).ToArray(); + FillAllowVertex(allowVertex); + FaceIndex = mergedFaceIndex; } } /// @@ -751,9 +755,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, ref rawFaceVertexIndices, initialFaceNormal, debugInitialBasisX, debugInitialBasisY, ref reducedFaceIndices, ref allowVertices, ref faces, reducedFaceIndices.Count >= 3 ? 0 : -1)); - - int facesDeletedCount = 0; + steps.Add(new DebugStep(initialSourceEdge, rawFaceVertexIndices, initialFaceNormal, debugInitialBasisX, debugInitialBasisY, reducedFaceIndices, allowVertices, faces, reducedFaceIndices.Count >= 3 ? 0 : -1)); while (edgesToTest.Count > 0) { @@ -780,18 +782,18 @@ public static void ComputeHull(Span points, BufferPool pool, out HullDa if (reducedFaceIndices.Count < 3) { - steps.Add(new DebugStep(edgeToTest.Endpoints, ref rawFaceVertexIndices, faceNormal, basisX, basisY, ref reducedFaceIndices, ref allowVertices, ref faces, -1)); + steps.Add(new DebugStep(edgeToTest.Endpoints, rawFaceVertexIndices, faceNormal, basisX, basisY, reducedFaceIndices, allowVertices, faces, -1)); //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. 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) { ref var face = ref faces[i]; - if (face.Deleted) - continue; if (Vector3.Dot(face.Normal, faceNormal) > normalCoplanarityEpsilon) { Console.WriteLine($"Merging face {i} with new face, dot {Vector3.Dot(face.Normal, faceNormal)}:"); @@ -811,12 +813,11 @@ public static void ComputeHull(Span points, BufferPool pool, out HullDa } } // Rerun reduction for the merged face. - var step = new DebugStep(edgeToTest.Endpoints, ref rawFaceVertexIndices, faceNormal, basisX, basisY, ref reducedFaceIndices, ref allowVertices, ref faces, i); face.VertexIndices.Count = 0; facePoints.Count = 0; face.VertexIndices.EnsureCapacity(rawFaceVertexIndices.Count, pool); ReduceFace(ref rawFaceVertexIndices, faceNormal, points, planeEpsilonNarrow, ref facePoints, ref allowVertices, ref face.VertexIndices); - steps.Add(step); + step.UpdateForFaceMerge(rawFaceVertexIndices, face.VertexIndices, allowVertices, i); mergedFace = true; break; } @@ -826,7 +827,6 @@ public static void ComputeHull(Span points, BufferPool pool, out HullDa var faceCountPriorToAdd = faces.Count; AddFace(ref faces, pool, faceNormal, reducedFaceIndices); AddFaceEdgesToTestList(pool, ref reducedFaceIndices, ref edgesToTest, ref submittedEdgeTests, faceNormal, faceCountPriorToAdd); - steps.Add(new DebugStep(edgeToTest.Endpoints, ref rawFaceVertexIndices, faceNormal, basisX, basisY, ref reducedFaceIndices, ref allowVertices, ref faces, faceCountPriorToAdd)); } if (steps.Count > 500) @@ -855,28 +855,6 @@ public static void ComputeHull(Span points, BufferPool pool, out HullDa // } //} - if (facesDeletedCount > 0) - { - //During execution, some faces were found to be coplanar and got merged. To avoid breaking face index references during execution, we left those triangles in place. - //Now, though, we need to get rid of any faces that are marked deleted! - int shift = 0; - for (int i = 0; i < faces.Count; ++i) - { - if (faces[i].Deleted) - { - //Removing the face from the list, so we gotta dispose it now rather than later. - faces[i].VertexIndices.Dispose(pool); - ++shift; - } - else if (shift > 0) - { - faces[i - shift] = faces[i]; - } - } - Debug.Assert(facesDeletedCount == shift); - faces.Count -= facesDeletedCount; - } - //Create a reduced hull point set from the face vertex references. int totalIndexCount = 0; for (int i = 0; i < faces.Count; ++i) @@ -921,7 +899,6 @@ public static void ComputeHull(Span points, BufferPool pool, out HullDa faces[i].VertexIndices.Dispose(pool); } faces.Dispose(pool); - facesNeedingMerge.Dispose(pool); } diff --git a/Demos/SpecializedTests/ConvexHullTestDemo.cs b/Demos/SpecializedTests/ConvexHullTestDemo.cs index c64d9ce0..3a83ed29 100644 --- a/Demos/SpecializedTests/ConvexHullTestDemo.cs +++ b/Demos/SpecializedTests/ConvexHullTestDemo.cs @@ -736,7 +736,18 @@ void DrawVertexIndex(int i, Vector3 color, Vector2 offset = default) } if (showFaceVertexStatuses) { - for (int i = 0; i < step.Raw.Count; ++i) + 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) { var color = new Vector3(0.3f, 0.3f, 1); var pose = new RigidPose(renderOffset + points[step.Raw[i]] * scale); @@ -744,7 +755,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 < step.Reduced.Count; ++i) + for (int i = 0; i < reduced.Length; ++i) { var color = new Vector3(0, 1, 0); var pose = new RigidPose(renderOffset + points[step.Reduced[i]] * scale);