Esempio n. 1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="polygon">Polygon to triangulate</param>
        /// <param name="verticesCount">lenght of the vertexList of the mesh that has been sliced - 1</param>
        public static FinishedPolygon Triangulate(PolygonCreator polygon, int verticesCount)
        {
            FinishedPolygon finishedPolygon = new FinishedPolygon();

            //polygon creator has outlines and holes;

            //for each outline we need a seperate polygon to triangulate
            for (int i = 0; i < polygon.Outlines.Count; i++)
            {
                EarClippingPolygon earClipPoly = new EarClippingPolygon(new PolygonMetaData(polygon.Outlines[i]));
                for (int j = 0; j < polygon.Holes.Count; j++)
                {
                    if (polygon.Holes[j].Parent == polygon.Outlines[i].ID)
                    {
                        earClipPoly.AddHole(new PolygonMetaData(polygon.Holes[j]));
                    }
                }
                //outline is combined with hole(s) if any and is ready to be earclipped
                //add triangle offset to make up for vertices that are already inside the mesh
                int triangleOffsetIndex = verticesCount + finishedPolygon.vertices.Count;

                Earclipping earClipper = new Earclipping(earClipPoly, triangleOffsetIndex);
                earClipper.ClipEars();

                finishedPolygon.triangles.AddRange(earClipper.Triangles);
                finishedPolygon.uv.AddRange(earClipper.UV);
                finishedPolygon.vertices.AddRange(earClipper.Vertices);
                for (int n = 0; n < earClipper.Vertices.Count; n++)
                {
                    finishedPolygon.normals.Add(polygon.Normal);
                }
            }
            return(finishedPolygon);
        }
Esempio n. 2
0
    private List <SlicedMesh> GenerateMesh(SlicedMesh original, Plane plane, bool positiveSide, Transform objectTransform)
    {
        SlicedMesh slicePositive = new SlicedMesh();
        SlicedMesh sliceNegative = new SlicedMesh();
        //polygon we use to fill in the sliced surface
        PolygonCreator polygonPositive = new PolygonCreator(objectTransform, plane.normal * -1);
        PolygonCreator polygonNegative = new PolygonCreator(objectTransform, plane.normal);
        bool           matPositiveAdded = false, matNegativeAdded = false;

        //we loop over all submeshes
        for (int submesh = 0; submesh < original.triangles.Length; submesh++)
        {
            int[] originalTriangles = original.triangles[submesh];
            setEdge = false;

            //increase t by 3 because a triangle consist out of 3 vertices;
            for (int t = 0; t < originalTriangles.Length; t += 3)
            {
                //which triangle we need
                int t1 = t, t2 = t + 1, t3 = t + 2;

                //Check if vertice is on positive side of the plane
                bool sideA = plane.GetSide(original.vertices[originalTriangles[t1]]) == positiveSide;
                bool sideB = plane.GetSide(original.vertices[originalTriangles[t2]]) == positiveSide;
                bool sideC = plane.GetSide(original.vertices[originalTriangles[t3]]) == positiveSide;

                //how many vertices are on the positive side of the plane
                int sideCount = (sideA ? 1 : 0) +
                                (sideB ? 1 : 0) +
                                (sideC ? 1 : 0);

                //if none of the vertices is located on the positive side
                if (sideCount == 0)
                {
                    //add entire triangle to negative side
                    sliceNegative.AddTriangle(submesh, original.vertices[originalTriangles[t1]], original.vertices[originalTriangles[t2]], original.vertices[originalTriangles[t3]],
                                              original.normals[originalTriangles[t1]], original.normals[originalTriangles[t2]], original.normals[originalTriangles[t3]],
                                              original.uv[originalTriangles[t1]], original.uv[originalTriangles[t2]], original.uv[originalTriangles[t3]]);
                    if (!matNegativeAdded)
                    {
                        matNegativeAdded = true;
                        sliceNegative.materialIndex.Add(submesh);
                    }

                    continue;
                }
                //if all the vertices are located on the positive side
                else if (sideCount == 3)
                {
                    //add entire triangle to positive side
                    slicePositive.AddTriangle(submesh, original.vertices[originalTriangles[t1]], original.vertices[originalTriangles[t2]], original.vertices[originalTriangles[t3]],
                                              original.normals[originalTriangles[t1]], original.normals[originalTriangles[t2]], original.normals[originalTriangles[t3]],
                                              original.uv[originalTriangles[t1]], original.uv[originalTriangles[t2]], original.uv[originalTriangles[t3]]);
                    if (!matPositiveAdded)
                    {
                        matPositiveAdded = true;
                        slicePositive.materialIndex.Add(submesh);
                    }

                    continue;
                }

                //else a triangle is cut and submesh material must be added to both sides
                if (!matNegativeAdded)
                {
                    matNegativeAdded = true;
                    sliceNegative.materialIndex.Add(submesh);
                }
                if (!matPositiveAdded)
                {
                    matPositiveAdded = true;
                    slicePositive.materialIndex.Add(submesh);
                }


                //determines which vertex in the triangle is solely located on one side of the plane
                int singleIndex = sideB == sideC ? 0 : sideA == sideC ? 1 : 2;
                int indexB = t + ((singleIndex + 1) % 3), indexC = t + ((singleIndex + 2) % 3);
                singleIndex += t;

                //calculate which vertices/normals/uv should be used to calculate intersection points
                Vector3 singleVertex = original.vertices[originalTriangles[singleIndex]],
                        vertexB      = original.vertices[originalTriangles[indexB]],            //right vertex
                        vertexC      = original.vertices[originalTriangles[indexC]];            //left vertex
                Vector3 singleNormal = original.normals[originalTriangles[singleIndex]],
                        normalB      = original.normals[originalTriangles[indexB]],
                        normalC      = original.normals[originalTriangles[indexC]];
                Vector2 singleUv     = original.uv[originalTriangles[singleIndex]],
                        uvB          = original.uv[originalTriangles[indexB]],
                        uvC          = original.uv[originalTriangles[indexC]];

                //calculate new vertices/normals/uv where edge intersects plane
                float   lerpB, lerpC;
                Vector3 newVertexB = PointOnPlane(plane, singleVertex, vertexB, out lerpB),     //new right vertex
                        newVertexC = PointOnPlane(plane, singleVertex, vertexC, out lerpC);     //new left vertex
                Vector3 newNormalB = Vector3.Lerp(singleNormal, normalB, lerpB),                //lerp to get the point between the old vertices where the new vertex is located
                        newNormalC = Vector3.Lerp(singleNormal, normalC, lerpC);
                Vector2 newUvB     = Vector2.Lerp(singleUv, uvB, lerpB),
                        newUvC     = Vector2.Lerp(singleUv, uvC, lerpC);

                if (!concave)
                {
                    //add and edge to "fill" the mesh
                    AddSliceTriangle(submesh, slicePositive, newVertexB, newVertexC,
                                     plane.normal * -1,
                                     newUvB, newUvC);
                    AddSliceTriangle(submesh, sliceNegative, newVertexB, newVertexC,
                                     plane.normal,
                                     newUvB, newUvC);
                }

                if (sideCount == 1)
                {
                    //positive data
                    slicePositive.AddTriangle(submesh, singleVertex, newVertexB, newVertexC, singleNormal, newNormalB, newNormalC, singleUv, newUvB, newUvC);
                    //negative data
                    sliceNegative.AddTriangle(submesh, newVertexB, vertexB, vertexC, newNormalB, normalB, normalC, newUvB, uvB, uvC);
                    sliceNegative.AddTriangle(submesh, newVertexB, vertexC, newVertexC, newNormalB, normalC, newNormalC, newUvB, uvC, newUvC);

                    if (concave)
                    {
                        //positive
                        Edge edgePositive = new Edge(newVertexB, newVertexC, plane.normal * -1, newUvB, newUvC);
                        polygonPositive.AddEdge(edgePositive);
                        //negative
                        Edge edgeNegative = new Edge(newVertexC, newVertexB, plane.normal, newUvC, newUvB);
                        polygonNegative.AddEdge(edgeNegative);
                    }
                    continue;
                }
                else if (sideCount == 2)
                {
                    //positive data
                    slicePositive.AddTriangle(submesh, newVertexB, vertexB, vertexC, newNormalB, normalB, normalC, newUvB, uvB, uvC);
                    slicePositive.AddTriangle(submesh, newVertexB, vertexC, newVertexC, newNormalB, normalC, newNormalC, newUvB, uvC, newUvC);
                    //negative data
                    sliceNegative.AddTriangle(submesh, singleVertex, newVertexB, newVertexC, singleNormal, newNormalB, newNormalC, singleUv, newUvB, newUvC);
                    if (concave)
                    {
                        //positive
                        Edge edgePositive = new Edge(newVertexC, newVertexB, plane.normal * -1, newUvC, newUvB);
                        polygonPositive.AddEdge(edgePositive);
                        //negative
                        Edge edgeNegative = new Edge(newVertexB, newVertexC, plane.normal, newUvB, newUvC);
                        polygonNegative.AddEdge(edgeNegative);
                    }
                    continue;
                }
            }
        }

        if (concave)
        {
            //build polygons
            polygonPositive.ConnectEdges();
            polygonNegative.ConnectEdges();

            //build meshdata for polygons
            FinishedPolygon polygonPositiveFinished = Triangulation.Triangulate(polygonPositive, slicePositive.VertexCount);
            FinishedPolygon polygonNegativeFinished = Triangulation.Triangulate(polygonNegative, sliceNegative.VertexCount);

            //add meshdata to slices
            slicePositive.AddPolygon(polygonPositiveFinished);
            sliceNegative.AddPolygon(polygonNegativeFinished);
        }

        slicePositive.FillArray(correctData);
        sliceNegative.FillArray(correctData);

        return(new List <SlicedMesh>()
        {
            slicePositive, sliceNegative
        });
    }