Recreating Slice procedural mesh component UE5.5

Hello,

There is a crash when we do slice procedural mesh component too many time, see :

So i’m recreating a function that do the slice, so the assertion crash does not happens. However, when i’m recreating the the face where the plane has been sliced, i always have 1 or 2 missing triangle, at least visually.

Missing triangle example

the code

static void SliceSectionsByPlane(
    TArray<FProcMeshVertex>& Vertices,
    const FVector& PlaneLocation,
    const FVector& PlaneNormal,
    const TArray<uint32>& Triangles,
    TArray<uint32>& MainHalf,
    TArray<uint32>& OtherHalf
)
{
    TSet<uint32> UniqueCapVertices;

    /**
     * Each triangle are stored in an array of uint32,
     * Each uint32 is an index withing the Vertices array :
     * [Triangles] = { index vertex 1, index vertex 2, index vertex 3, index vertex 1, ... }
     * So a triangle is defined by 3 consecutive elements
     * 
     * that's why 'i += 3'
     */
    for (int32 i = 0; i + 2 < Triangles.Num(); i += 3)
    {
        uint32 p0 = Triangles[i];
        uint32 p1 = Triangles[i + 1];
        uint32 p2 = Triangles[i + 2];

        if (!Vertices.IsValidIndex(p0) || !Vertices.IsValidIndex(p1) || !Vertices.IsValidIndex(p2))
            continue;

        const FProcMeshVertex& V0 = Vertices[p0];
        const FProcMeshVertex& V1 = Vertices[p1];
        const FProcMeshVertex& V2 = Vertices[p2];

        // Check if each vertex is in the part that needs to be kept
        bool v0 = IsPointValid(V0, PlaneNormal, PlaneLocation);
        bool v1 = IsPointValid(V1, PlaneNormal, PlaneLocation);
        bool v2 = IsPointValid(V2, PlaneNormal, PlaneLocation);

        // triangle needs to be entirely  kept
        if (v0 && v1 && v2) {
            MainHalf.Append({ p0, p1, p2 });
            continue;
        }
        // the triangle needs to be totally erased
        if (!v0 && !v1 && !v2) {
            OtherHalf.Append({ p0, p1, p2 });
            continue;
        }
        /**
         * @brief Computes the intersection vertex between an edge and the slicing plane.
         *
         * Given two vertex indices defining an edge, this function computes the
         * intersection point with the slicing plane, interpolates the vertex attributes
         * (UVs and normals), and appends the resulting vertex to the mesh.
         *
         * A second copy of the vertex is also created with its normal aligned to the
         * plane normal. This duplicate is stored in the cap vertex list and is later
         * used to generate the closing cap geometry.
         *
         * @param A Index of the first vertex of the edge.
         * @param B Index of the second vertex of the edge.
         *
         * @return The index of the newly created intersection vertex in the mesh vertex array.
         *
         * @note The cap vertex created internally is added to UniqueCapVertices but its
         * index is not returned.
         */
        auto Intersect = [&](uint32 A, uint32 B) {
            const FProcMeshVertex& VA = Vertices[A];
            const FProcMeshVertex& VB = Vertices[B];

            FVector P = ReplacePointOnPlaneLocal(VA.Position, VB.Position, PlaneLocation, PlaneNormal);

            float EdgeLength = (VB.Position - VA.Position).Size();
            float Alpha = 0.f;

            if (EdgeLength > KINDA_SMALL_NUMBER)
                Alpha = (P - VA.Position).Size() / EdgeLength;

            FProcMeshVertex VNew;
            VNew.Position = P;
            VNew.UV0 = FMath::Lerp(VA.UV0, VB.UV0, Alpha);
            VNew.Normal = FMath::Lerp(VA.Normal, VB.Normal, Alpha).GetSafeNormal();

            uint32 MeshIndex = Vertices.Add(VNew);

            FProcMeshVertex CapVertex = VNew;
            CapVertex.Normal = PlaneNormal;
            uint32 CapIndex = Vertices.Add(CapVertex);
            UniqueCapVertices.Add(CapIndex);

            return MeshIndex;
        };

        // configuration : 1 vertex is in the good side
        if (v0 && !v1 && !v2) {
            uint32 i01 = Intersect(p0, p1);
            uint32 i02 = Intersect(p0, p2);

            MainHalf.Append({ p0, i01, i02 });

            OtherHalf.Append({ p1, p2, i02 });
            OtherHalf.Append({ p1, i02, i01 });
        }
        else if (!v0 && v1 && !v2) {
            uint32 i10 = Intersect(p1, p0);
            uint32 i12 = Intersect(p1, p2);

            MainHalf.Append({ p1, i12, i10 });

            OtherHalf.Append({ p0, i10, p2 });
            OtherHalf.Append({ p2, i10, i12 });
        }
        else if (!v0 && !v1 && v2) {
            uint32 i20 = Intersect(p2, p0);
            uint32 i21 = Intersect(p2, p1);

            MainHalf.Append({ p2, i20, i21 });

            OtherHalf.Append({ p0, p1, i21 });
            OtherHalf.Append({ p0, i21, i20 });
        }

        // configuration inverse : 2 vertices are in the good side
        else if (!v0 && v1 && v2) {
            uint32 i01 = Intersect(p0, p1);
            uint32 i02 = Intersect(p0, p2);

            OtherHalf.Append({ p0, i01, i02 });

            MainHalf.Append({ p1, p2, i02 });
            MainHalf.Append({ p1, i02, i01 });
        }
        else if (v0 && !v1 && v2) {
            uint32 i10 = Intersect(p1, p0);
            uint32 i12 = Intersect(p1, p2);

            OtherHalf.Append({ p1, i12, i10 });

            MainHalf.Append({ p0, i10, p2 });
            MainHalf.Append({ p2, i10, i12 });
        }
        else if (v0 && v1 && !v2)
        {
            uint32 i20 = Intersect(p2, p0);
            uint32 i21 = Intersect(p2, p1);

            OtherHalf.Append({ p2, i20, i21 });

            MainHalf.Append({ p0, p1, i21 });
            MainHalf.Append({ p0, i21, i20 });
        }
    }
    
    // This recreate the face where the plane sliced the mesh
    if (UniqueCapVertices.Num() >= 3) {
        TArray<uint32> CapVertices = UniqueCapVertices.Array();
        
        // Compute center location
        FVector CenterPos = FVector::ZeroVector;
        for (uint32 Index : CapVertices) {
            CenterPos += Vertices[Index].Position;
        }
        CenterPos /= CapVertices.Num();

        // Creating the center vertex
        FProcMeshVertex CenterVertex;
        CenterVertex.Position = CenterPos;
        CenterVertex.Normal = PlaneNormal;
        CenterVertex.UV0 = FVector2D(0.5f, 0.5f);
        uint32 Center = Vertices.Add(CenterVertex);
        for (int32 i = 1; i < CapVertices.Num(); ++i) {
            uint32 A = CapVertices[i % CapVertices.Num()];
            uint32 B = CapVertices[(i - 1) % CapVertices.Num()];
            MainHalf.Append({ Center, B, A });
            OtherHalf.Append({ Center, A, B });
        }
    }
}

I tried sorting the cap vertices angularly around the center, but it made the face disappear entirely.