// Slice mesh along plane intersection
    public static void SliceMesh(GameObject obj, CustomPlane plane, bool isConvex)
    {
        // original GameObject data
        Transform objTransform = obj.transform;
        Mesh objMesh = obj.GetComponent<MeshFilter>().mesh;
        Vector3[] meshVerts = objMesh.vertices;
        int[] meshTris = objMesh.triangles;
        Vector2[] meshUVs = objMesh.uv;

        // Slice mesh data
        slice1Verts = new List<Vector3>();
        slice2Verts = new List<Vector3>();
        slice1Tris = new List<int>();
        slice2Tris = new List<int>();
        slice1UVs = new List<Vector2>();
        slice2UVs = new List<Vector2>();
        lineLoop = new List<Line>();

        // Loop through triangles
        for(int i = 0; i < meshTris.Length / 3; i++) {
            // Define triangle
            Vector3[] triVertsLocal = new Vector3[3];
            Vector3[] triVertsWorld = new Vector3[3];
            Vector2[] triUVs = new Vector2[3];
            for(int j = 0; j < 3; j++) {
                int meshIndexor = (i + 1) * 3 - (3 - j);
                triVertsLocal[j] = meshVerts[meshTris[meshIndexor]]; 					// local model space vertices
                triVertsWorld[j] = objTransform.TransformPoint(triVertsLocal[j]); 		// world space vertices
                triUVs[j] = meshUVs[meshTris[meshIndexor]]; 							// original uv coordinates
            }
            // Side test: (0) = intersecting plane; (+) = above plane; (-) = below plane;
            float vert1Side = plane.GetSide(triVertsWorld[0]);
            float vert2Side = plane.GetSide(triVertsWorld[1]);
            float vert3Side = plane.GetSide(triVertsWorld[2]);
            // assign triangles that do not intersect plane
            if(vert1Side > 0 && vert2Side > 0 && vert3Side > 0) { 			// Slice 1
                for(int j = 0; j < triVertsLocal.Length; j++) {
                    slice1Verts.Add(triVertsLocal[j]);
                    slice1Tris.Add(slice1Verts.Count - 1);
                    slice1UVs.Add(triUVs[j]);
                }
            } else if(vert1Side < 0 && vert2Side < 0 && vert3Side < 0) {	// Slice 2
                for(int j = 0; j < triVertsLocal.Length; j++) {
                    slice2Verts.Add(triVertsLocal[j]);
                    slice2Tris.Add(slice2Verts.Count - 1);
                    slice2UVs.Add(triUVs[j]);
                }
            } else if(vert1Side == 0 || vert2Side == 0 || vert3Side == 0) {
                Debug.Log ("Point-Plane Intersection");
                return;
            } else {														// Intersecting Triangles
                Vector3[] slicedTriVerts = new Vector3[5];
                Vector2[] slicedTriUVs = new Vector2[5];
                Vector3[] triVertsWorld2 = new Vector3[3];
                int[] vertOrder; // triangle vertex-order CW vs. CCW
                if(vert1Side * vert2Side > 0) {
                    int[] triOrder = {2,0,1};
                    for(int j = 0; j < triOrder.Length; j++) {
                        slicedTriVerts[j] = triVertsLocal[triOrder[j]];
                        slicedTriUVs[j] = triUVs[triOrder[j]];
                        triVertsWorld2[j] = triVertsWorld[triOrder[j]];
                    }
                    vertOrder = vertOrderCW;
                } else if(vert1Side * vert3Side > 0) {
                    int[] triOrder = {1,0,2};
                    for(int j = 0; j < triOrder.Length; j++) {
                        slicedTriVerts[j] = triVertsLocal[triOrder[j]];
                        slicedTriUVs[j] = triUVs[triOrder[j]];
                        triVertsWorld2[j] = triVertsWorld[triOrder[j]];
                    }
                    vertOrder = vertOrderCCW;
                } else {
                    int[] triOrder = {0,1,2};
                    for(int j = 0; j < triOrder.Length; j++) {
                        slicedTriVerts[j] = triVertsLocal[triOrder[j]];
                        slicedTriUVs[j] = triUVs[triOrder[j]];
                        triVertsWorld2[j] = triVertsWorld[triOrder[j]];
                    }
                    vertOrder = vertOrderCW;
                }

                // Points of Intersection
                Vector3 poi1 = plane.VectorPlanePOI(triVertsWorld2[0], (triVertsWorld2[1] - triVertsWorld2[0]).normalized);
                Vector3 poi2 = plane.VectorPlanePOI(triVertsWorld2[0], (triVertsWorld2[2] - triVertsWorld2[0]).normalized);
                slicedTriVerts[3] = objTransform.InverseTransformPoint(poi1);
                slicedTriVerts[4] = objTransform.InverseTransformPoint(poi2);

                lineLoop.Add(new Line(slicedTriVerts[3], slicedTriVerts[4], poi1, poi2));

                // POI UVs
                float t1 = Vector3.Distance(slicedTriVerts[0], slicedTriVerts[3]) / Vector3.Distance(slicedTriVerts[0], slicedTriVerts[1]);
                float t2 = Vector3.Distance(slicedTriVerts[0], slicedTriVerts[4]) / Vector3.Distance(slicedTriVerts[0], slicedTriVerts[2]);
                slicedTriUVs[3] = Vector2.Lerp(slicedTriUVs[0], slicedTriUVs[1], t1);
                slicedTriUVs[4] = Vector2.Lerp(slicedTriUVs[0], slicedTriUVs[2], t2);

                // Add bisected triangle to slice respectively
                if(plane.GetSide(triVertsWorld2[0]) > 0) {
                    // Slice 1
                    for(int j = 0; j < 3; j++) {
                        slice1Verts.Add(slicedTriVerts[vertOrder[j]]);
                        slice1Tris.Add(slice1Verts.Count - 1);
                        slice1UVs.Add(slicedTriUVs[vertOrder[j]]);
                    }
                    // Slice 2
                    for(int j = 3; j < 9; j++) {
                        slice2Verts.Add(slicedTriVerts[vertOrder[j]]);
                        slice2Tris.Add(slice2Verts.Count - 1);
                        slice2UVs.Add(slicedTriUVs[vertOrder[j]]);
                    }
                } else {
                    // Slice 2
                    for(int j = 0; j < 3; j++) {
                        slice2Verts.Add(slicedTriVerts[vertOrder[j]]);
                        slice2Tris.Add(slice2Verts.Count - 1);
                        slice2UVs.Add(slicedTriUVs[vertOrder[j]]);
                    }
                    // Slice 1
                    for(int j = 3; j < 9; j++) {
                        slice1Verts.Add(slicedTriVerts[vertOrder[j]]);
                        slice1Tris.Add(slice1Verts.Count - 1);
                        slice1UVs.Add(slicedTriUVs[vertOrder[j]]);
                    }
                }
            }
        }
        if(lineLoop.Count > 0) {
            // Fill convex mesh
            if(isConvex) {
                Vector3 normal = plane.normal;
                do {
                    Polygon polygon = new Polygon(lineLoop, normal);
                    Vector3 polygonNormal = (polygon.isClockWise) ? normal : -normal;
                    TriangulatePolygon(polygon.edges, polygonNormal, polygon.isClockWise);
                } while(lineLoop.Count != 0);
            }
            // Build Meshes
            if(slice1Verts.Count > 0) {
                BuildSlice(obj, objTransform, slice1Verts.ToArray(), slice1Tris.ToArray(), slice1UVs.ToArray());
            }
            if(slice2Verts.Count > 0) {
                BuildSlice(obj, objTransform, slice2Verts.ToArray(), slice2Tris.ToArray(), slice2UVs.ToArray());
            }
            // Delete original
            GameObject.Destroy(obj);
        }
    }
Exemple #2
0
    // Slice mesh along plane intersection
    public static void SliceMesh(GameObject obj, CustomPlane plane, bool isConvex)
    {
        // original GameObject data
        Transform objTransform = obj.transform;
        Mesh      objMesh      = obj.GetComponent <MeshFilter>().mesh;

        Vector3[] meshVerts = objMesh.vertices;
        int[]     meshTris  = objMesh.triangles;
        Vector2[] meshUVs   = objMesh.uv;

        // Slice mesh data
        slice1Verts = new List <Vector3>();
        slice2Verts = new List <Vector3>();
        slice1Tris  = new List <int>();
        slice2Tris  = new List <int>();
        slice1UVs   = new List <Vector2>();
        slice2UVs   = new List <Vector2>();
        lineLoop    = new List <Line>();

        // Loop through triangles
        for (int i = 0; i < meshTris.Length / 3; i++)
        {
            // Define triangle
            Vector3[] triVertsLocal = new Vector3[3];
            Vector3[] triVertsWorld = new Vector3[3];
            Vector2[] triUVs        = new Vector2[3];
            for (int j = 0; j < 3; j++)
            {
                int meshIndexor = (i + 1) * 3 - (3 - j);
                triVertsLocal[j] = meshVerts[meshTris[meshIndexor]];                                            // local model space vertices
                triVertsWorld[j] = objTransform.TransformPoint(triVertsLocal[j]);                               // world space vertices
                triUVs[j]        = meshUVs[meshTris[meshIndexor]];                                              // original uv coordinates
            }
            // Side test: (0) = intersecting plane; (+) = above plane; (-) = below plane;
            float vert1Side = plane.GetSide(triVertsWorld[0]);
            float vert2Side = plane.GetSide(triVertsWorld[1]);
            float vert3Side = plane.GetSide(triVertsWorld[2]);
            // assign triangles that do not intersect plane
            if (vert1Side > 0 && vert2Side > 0 && vert3Side > 0)                                // Slice 1
            {
                for (int j = 0; j < triVertsLocal.Length; j++)
                {
                    slice1Verts.Add(triVertsLocal[j]);
                    slice1Tris.Add(slice1Verts.Count - 1);
                    slice1UVs.Add(triUVs[j]);
                }
            }
            else if (vert1Side < 0 && vert2Side < 0 && vert3Side < 0)                   // Slice 2
            {
                for (int j = 0; j < triVertsLocal.Length; j++)
                {
                    slice2Verts.Add(triVertsLocal[j]);
                    slice2Tris.Add(slice2Verts.Count - 1);
                    slice2UVs.Add(triUVs[j]);
                }
            }
            else if (vert1Side == 0 || vert2Side == 0 || vert3Side == 0)
            {
                Debug.Log("Point-Plane Intersection");
                return;
            }
            else                                                                                                                                // Intersecting Triangles
            {
                Vector3[] slicedTriVerts = new Vector3[5];
                Vector2[] slicedTriUVs   = new Vector2[5];
                Vector3[] triVertsWorld2 = new Vector3[3];
                int[]     vertOrder;             // triangle vertex-order CW vs. CCW
                if (vert1Side * vert2Side > 0)
                {
                    int[] triOrder = { 2, 0, 1 };
                    for (int j = 0; j < triOrder.Length; j++)
                    {
                        slicedTriVerts[j] = triVertsLocal[triOrder[j]];
                        slicedTriUVs[j]   = triUVs[triOrder[j]];
                        triVertsWorld2[j] = triVertsWorld[triOrder[j]];
                    }
                    vertOrder = vertOrderCW;
                }
                else if (vert1Side * vert3Side > 0)
                {
                    int[] triOrder = { 1, 0, 2 };
                    for (int j = 0; j < triOrder.Length; j++)
                    {
                        slicedTriVerts[j] = triVertsLocal[triOrder[j]];
                        slicedTriUVs[j]   = triUVs[triOrder[j]];
                        triVertsWorld2[j] = triVertsWorld[triOrder[j]];
                    }
                    vertOrder = vertOrderCCW;
                }
                else
                {
                    int[] triOrder = { 0, 1, 2 };
                    for (int j = 0; j < triOrder.Length; j++)
                    {
                        slicedTriVerts[j] = triVertsLocal[triOrder[j]];
                        slicedTriUVs[j]   = triUVs[triOrder[j]];
                        triVertsWorld2[j] = triVertsWorld[triOrder[j]];
                    }
                    vertOrder = vertOrderCW;
                }

                // Points of Intersection
                Vector3 poi1 = plane.VectorPlanePOI(triVertsWorld2[0], (triVertsWorld2[1] - triVertsWorld2[0]).normalized);
                Vector3 poi2 = plane.VectorPlanePOI(triVertsWorld2[0], (triVertsWorld2[2] - triVertsWorld2[0]).normalized);
                slicedTriVerts[3] = objTransform.InverseTransformPoint(poi1);
                slicedTriVerts[4] = objTransform.InverseTransformPoint(poi2);

                lineLoop.Add(new Line(slicedTriVerts[3], slicedTriVerts[4], poi1, poi2));

                // POI UVs
                float t1 = Vector3.Distance(slicedTriVerts[0], slicedTriVerts[3]) / Vector3.Distance(slicedTriVerts[0], slicedTriVerts[1]);
                float t2 = Vector3.Distance(slicedTriVerts[0], slicedTriVerts[4]) / Vector3.Distance(slicedTriVerts[0], slicedTriVerts[2]);
                slicedTriUVs[3] = Vector2.Lerp(slicedTriUVs[0], slicedTriUVs[1], t1);
                slicedTriUVs[4] = Vector2.Lerp(slicedTriUVs[0], slicedTriUVs[2], t2);

                // Add bisected triangle to slice respectively
                if (plane.GetSide(triVertsWorld2[0]) > 0)
                {
                    // Slice 1
                    for (int j = 0; j < 3; j++)
                    {
                        slice1Verts.Add(slicedTriVerts[vertOrder[j]]);
                        slice1Tris.Add(slice1Verts.Count - 1);
                        slice1UVs.Add(slicedTriUVs[vertOrder[j]]);
                    }
                    // Slice 2
                    for (int j = 3; j < 9; j++)
                    {
                        slice2Verts.Add(slicedTriVerts[vertOrder[j]]);
                        slice2Tris.Add(slice2Verts.Count - 1);
                        slice2UVs.Add(slicedTriUVs[vertOrder[j]]);
                    }
                }
                else
                {
                    // Slice 2
                    for (int j = 0; j < 3; j++)
                    {
                        slice2Verts.Add(slicedTriVerts[vertOrder[j]]);
                        slice2Tris.Add(slice2Verts.Count - 1);
                        slice2UVs.Add(slicedTriUVs[vertOrder[j]]);
                    }
                    // Slice 1
                    for (int j = 3; j < 9; j++)
                    {
                        slice1Verts.Add(slicedTriVerts[vertOrder[j]]);
                        slice1Tris.Add(slice1Verts.Count - 1);
                        slice1UVs.Add(slicedTriUVs[vertOrder[j]]);
                    }
                }
            }
        }
        if (lineLoop.Count > 0)
        {
            // Fill convex mesh
            if (isConvex)
            {
                Vector3 normal = plane.normal;
                do
                {
                    Polygon polygon       = new Polygon(lineLoop, normal);
                    Vector3 polygonNormal = (polygon.isClockWise) ? normal : -normal;
                    TriangulatePolygon(polygon.edges, polygonNormal, polygon.isClockWise);
                } while(lineLoop.Count != 0);
            }
            // Build Meshes
            if (slice1Verts.Count > 0)
            {
                BuildSlice(obj, objTransform, slice1Verts.ToArray(), slice1Tris.ToArray(), slice1UVs.ToArray());
            }
            if (slice2Verts.Count > 0)
            {
                BuildSlice(obj, objTransform, slice2Verts.ToArray(), slice2Tris.ToArray(), slice2UVs.ToArray());
            }
            // Delete original
            GameObject.Destroy(obj);
        }
    }