Пример #1
0
    public static bool CutTriangleMesh(Mesh[] outputMeshes, Mesh sourceMesh, Plane cuttingPlane, Transform transform, Transform rotation, bool cap)
    {
        float epsilon = 0.00001f;

        debugPolyLoop       = new List <Vector3>();
        debugEdgePoints     = new List <Vector3>();
        debugEdges          = new List <Vector3[]>();
        debugLoopEdgePoints = new List <Vector3[]>();

        int vertCount = sourceMesh.vertexCount;

        Vector3[]           verts    = sourceMesh.vertices;
        Triangle3D.Vertex[] allVerts = new Triangle3D.Vertex[vertCount];
        for (int i = 0; i < vertCount; i++)
        {
            allVerts[i] = new Triangle3D.Vertex(transform.TransformPoint(verts[i]));
        }

        List <Triangle3D.Vertex> allVertList = new List <Triangle3D.Vertex>();

        Vector2[] originalUVs      = sourceMesh.uv;
        Vector3[] originalNormals  = sourceMesh.normals;
        Vector4[] originalTangents = sourceMesh.tangents;

        int triCount = sourceMesh.triangles.Length / 3;

        Triangle3D[] originalTriangles = new Triangle3D[triCount];

        int offset = 0;

        for (int j = 0; j < sourceMesh.subMeshCount; j++)
        {
            uint  triOffset       = 0;
            int[] subMeshIndices  = sourceMesh.GetTriangles(j);
            int   subMeshTriCount = subMeshIndices.Length / 3;

            for (int i = 0; i < subMeshTriCount; i++)
            {
                int idx0 = subMeshIndices[triOffset + 0];
                int idx1 = subMeshIndices[triOffset + 1];
                int idx2 = subMeshIndices[triOffset + 2];


                originalTriangles[offset++] = new Triangle3D(allVertList, new Triangle3D.Vertex[] { allVerts[idx0], allVerts[idx1], allVerts[idx2] }, new Vector3[] { originalNormals[idx0], originalNormals[idx1], originalNormals[idx2] }, new Vector2[] { originalUVs[idx0], originalUVs[idx1], originalUVs[idx2] }, new Vector4[] { originalTangents[idx0], originalTangents[idx1], originalTangents[idx2] }, new int[] { subMeshIndices[triOffset + 0], subMeshIndices[triOffset + 1], subMeshIndices[triOffset + 2] }, j);

                triOffset += 3;
            }
        }

        if (originalTriangles.Length > 0)
        {
            int          processedTriCount = 0;
            Triangle3D[] processedTris     = new Triangle3D[originalTriangles.Length * 3];

            ClassificationUtil.Classification prevSide = ClassificationUtil.Classification.UNDEFINED;
            foreach (Triangle3D originalTriangle in originalTriangles)
            {
                ClassificationUtil.Classification side;
                Triangle3D[] splitTriangles = TriangleUtil.SplitTriangleWithPlane(originalTriangle, cuttingPlane, epsilon, out side, cap);
                if (prevSide != ClassificationUtil.Classification.UNDEFINED && prevSide != side)
                {
                }
                prevSide = side;
                if (splitTriangles != null)
                {
                    // Triangle was cut
                    foreach (Triangle3D splitTriangle in splitTriangles)
                    {
                        processedTris[processedTriCount] = splitTriangle;
                        processedTriCount++;
                    }
                }

                else
                {
                    // Triangle was not cut
                    processedTris[processedTriCount] = originalTriangle;
                    processedTriCount++;
                }
            }

            int          triangleBucketACount = 0;
            int          triangleBucketBCount = 0;
            Triangle3D[] triangleBucketA      = new Triangle3D[processedTriCount];
            Triangle3D[] triangleBucketB      = new Triangle3D[processedTriCount];
            for (int i = 0; i < processedTriCount; i++)
            {
                ClassificationUtil.Classification[] classes;
                ClassificationUtil.Classification   triClass = ClassificationUtil.ClassifyPoints(processedTris[i].pos, cuttingPlane, out classes, epsilon);

                if (triClass == ClassificationUtil.Classification.FRONT)
                {
                    triangleBucketA[triangleBucketACount++] = processedTris[i];
                }

                else if (triClass == ClassificationUtil.Classification.BACK)
                {
                    triangleBucketB[triangleBucketBCount++] = processedTris[i];
                }
            }

            if (triangleBucketACount == 0 || triangleBucketBCount == 0)
            {
                return(false);
            }

            List <Triangle3D>        totalCapTriBucket  = new List <Triangle3D>();
            List <Triangle3D.Vertex> totalCapVertBucket = new List <Triangle3D.Vertex>();

            while (cap && debugEdges.Count > 2)
            {
                List <Triangle3D>        capTriBucket  = new List <Triangle3D>();
                List <Triangle3D.Vertex> capVertBucket = new List <Triangle3D.Vertex>();

                Triangle3D.Vertex[] sortedVerts = GetPolyLoop(ref debugEdges);

                if (sortedVerts != null)
                {
                    CapMesh(out capTriBucket, out capVertBucket, sortedVerts, transform, rotation, totalCapTriBucket.Count);
                }

                if (capVertBucket.Count > 2)
                {
                    for (int i = 0; i < capVertBucket.Count - 1; i++)
                    {
                        Debug.DrawLine(transform.TransformPoint(capVertBucket[i].pos), transform.TransformPoint(capVertBucket[i + 1].pos));
                    }
                    Debug.DrawLine(transform.TransformPoint(capVertBucket[capVertBucket.Count - 1].pos), transform.TransformPoint(capVertBucket[0].pos));
                }

                totalCapTriBucket.AddRange(capTriBucket);
                totalCapVertBucket.AddRange(capVertBucket);
            }

            if (triangleBucketACount > 0)
            {
                SortMesh(outputMeshes[0], triangleBucketA, triangleBucketACount, transform, totalCapTriBucket, totalCapVertBucket, false);
            }
            if (triangleBucketBCount > 0)
            {
                SortMesh(outputMeshes[1], triangleBucketB, triangleBucketBCount, transform, totalCapTriBucket, totalCapVertBucket, true);
            }
            return(true);
        }

        else
        {
            Debug.Log("source geometry empty");
            return(false);
        }
    }
Пример #2
0
    public static bool CutTriangleMeshFast(Mesh[] outputMeshes, Mesh sourceMesh, Transform objectTransform, Transform planeTransform, bool cap)
    {
        float epsilon = 0.00001f;

        hashCheck           = new Dictionary <Vector3, int>();
        debugPolyLoop       = new List <Vector3>();
        debugEdgePoints     = new List <Vector3>();
        debugEdges          = new List <Vector3[]>();
        debugLoopEdgePoints = new List <Vector3[]>();

        int originalVertexCount = sourceMesh.vertexCount;

        Vector3[] originalVertices = sourceMesh.vertices;

        int originalIndexCount = sourceMesh.triangles.Length;

        int[] originalIndices = sourceMesh.triangles;

        Vector3 centre       = objectTransform.transform.InverseTransformPoint(planeTransform.position);
        Vector3 up           = objectTransform.transform.InverseTransformDirection(planeTransform.up);
        Plane   cuttingPlane = new Plane(up, centre);

        int totalIndexCount  = originalIndexCount;
        int totalVertexCount = originalVertexCount;

        int indexBufferCountA  = 0;
        int vertexBufferCountA = 0;

        Vector3[] vertexBufferA = new Vector3[totalVertexCount * 10];
        int[]     indexBufferA  = new int[originalIndexCount * 10];

        int indexBufferCountB  = 0;
        int vertexBufferCountB = 0;

        Vector3[] vertexBufferB = new Vector3[totalVertexCount * 10];
        int[]     indexBufferB  = new int[originalIndexCount * 10];

        Vector3[] points     = new Vector3[3];
        int[]     triIndices = new int[3];

        for (int i = 0; i < totalIndexCount; i += 3)
        {
            triIndices[0] = originalIndices[i];
            triIndices[1] = originalIndices[i + 1];
            triIndices[2] = originalIndices[i + 2];

            points[0] = originalVertices[triIndices[0]];
            points[1] = originalVertices[triIndices[1]];
            points[2] = originalVertices[triIndices[2]];

            int[]     newTris;
            Vector3[] newPoints;

            ClassificationUtil.Classification side;
            TriangleUtil.SplitTriangleWithPlane(
                ref totalVertexCount,
                points,
                triIndices,
                cuttingPlane,
                epsilon,
                out side,
                cap,
                out newTris,
                out newPoints);

            // Slice the triangle then classify which side it's on
            if (newTris != null)
            {
                for (int j = 0; j < newTris.Length; j += 3)
                {
                    ClassificationUtil.Classification[] classes;
                    ClassificationUtil.Classification   triClass = ClassificationUtil.ClassifyPoints(
                        new Vector3[] { newPoints[j + 0], newPoints[j + 1], newPoints[j + 2] },
                        cuttingPlane,
                        out classes,
                        epsilon);

                    //Debug.DrawLine(newPoints[j + 0], newPoints[j + 1]);
                    //Debug.DrawLine(newPoints[j + 1], newPoints[j + 2]);
                    //Debug.DrawLine(newPoints[j + 2], newPoints[j + 0]);

                    if (triClass == ClassificationUtil.Classification.FRONT)
                    {
                        indexBufferA[indexBufferCountA++]   = newTris[j + 0];
                        indexBufferA[indexBufferCountA++]   = newTris[j + 1];
                        indexBufferA[indexBufferCountA++]   = newTris[j + 2];
                        vertexBufferA[vertexBufferCountA++] = newPoints[j + 0];
                        vertexBufferA[vertexBufferCountA++] = newPoints[j + 1];
                        vertexBufferA[vertexBufferCountA++] = newPoints[j + 2];
                    }
                    else if (triClass == ClassificationUtil.Classification.BACK)
                    {
                        indexBufferB[indexBufferCountB++]   = newTris[j + 0];
                        indexBufferB[indexBufferCountB++]   = newTris[j + 1];
                        indexBufferB[indexBufferCountB++]   = newTris[j + 2];
                        vertexBufferB[vertexBufferCountB++] = newPoints[j + 0];
                        vertexBufferB[vertexBufferCountB++] = newPoints[j + 1];
                        vertexBufferB[vertexBufferCountB++] = newPoints[j + 2];
                    }
                }
            }
            else
            {
                ClassificationUtil.Classification[] classes;
                ClassificationUtil.Classification   triClass = ClassificationUtil.ClassifyPoints(
                    new Vector3[] { points[0], points[1], points[2] },
                    cuttingPlane,
                    out classes,
                    epsilon);

                //Debug.DrawLine(points[0], points[1], Color.red);
                //Debug.DrawLine(points[1], points[2], Color.red);
                //Debug.DrawLine(points[2], points[0], Color.red);

                if (triClass == ClassificationUtil.Classification.FRONT)
                {
                    indexBufferA[indexBufferCountA++]   = triIndices[0];
                    indexBufferA[indexBufferCountA++]   = triIndices[1];
                    indexBufferA[indexBufferCountA++]   = triIndices[2];
                    vertexBufferA[vertexBufferCountA++] = points[0];
                    vertexBufferA[vertexBufferCountA++] = points[1];
                    vertexBufferA[vertexBufferCountA++] = points[2];
                }
                else if (triClass == ClassificationUtil.Classification.BACK)
                {
                    indexBufferB[indexBufferCountB++]   = triIndices[0];
                    indexBufferB[indexBufferCountB++]   = triIndices[1];
                    indexBufferB[indexBufferCountB++]   = triIndices[2];
                    vertexBufferB[vertexBufferCountB++] = points[0];
                    vertexBufferB[vertexBufferCountB++] = points[1];
                    vertexBufferB[vertexBufferCountB++] = points[2];
                }
            }
        }

        if (indexBufferCountA > 0)
        {
            SortMesh(outputMeshes[0], indexBufferA, vertexBufferA, indexBufferCountA, false);
        }
        if (indexBufferCountB > 0)
        {
            SortMesh(outputMeshes[1], indexBufferB, vertexBufferB, indexBufferCountB, true);
        }
        return(true);
    }