示例#1
0
文件: Triangulate.cs 项目: wHo2/TMC
        static void TriangulateConstrainedDelaunay( List<List<Vector3>> listlistPointsConstrainedDelaunay, List<List<int>> listlistHashValuesConstrainedDelaunay, bool bForceVertexSoup, FracturedObject fracturedComponent,
                                                    bool bConnectivityPostprocess, MeshFaceConnectivity faceConnectivityPos, MeshFaceConnectivity faceConnectivityNeg, MeshDataConnectivity meshConnectivityPos, MeshDataConnectivity meshConnectivityNeg, int nForceMeshConnectivityHash,
                                                    int nSplitCloseSubMesh, Matrix4x4 mtxPlane, Matrix4x4 mtxToLocalPos, Matrix4x4 mtxToLocalNeg, Vector3 v3CenterPos, Vector3 v3CenterNeg,
                                                    List<int>[] aListIndicesPosInOut, List<VertexData> listVertexDataPosInOut, List<int>[] aListIndicesNegInOut, List<VertexData> listVertexDataNegInOut)
        {
            // Pass to two dimensional plane:

            Matrix4x4 mtxPlaneInverse = mtxPlane.inverse;
            List<List<Poly2Tri.Point2D>>      listlistCapPoints        = new List<List<Poly2Tri.Point2D>>();
            List<List<Poly2Tri.PolygonPoint>> listlistCapPolygonPoints = new List<List<Poly2Tri.PolygonPoint>>();
            List<Poly2Tri.Polygon>            listCapPolygons          = new List<Poly2Tri.Polygon>();

            for(int i = 0; i < listlistPointsConstrainedDelaunay.Count; i++)
            {
                List<Poly2Tri.Point2D>      listCapPoints         = new List<Poly2Tri.Point2D>();
                List<Poly2Tri.PolygonPoint> listCapPolygonsPoints = new List<Poly2Tri.PolygonPoint>();

                foreach(Vector3 v3Vertex in listlistPointsConstrainedDelaunay[i])
                {
                    Vector3 v3VertexInPlane = mtxPlaneInverse.MultiplyPoint3x4(v3Vertex);
                    listCapPoints.Add        (new Poly2Tri.Point2D     (v3VertexInPlane.x, v3VertexInPlane.z));
                    listCapPolygonsPoints.Add(new Poly2Tri.PolygonPoint(v3VertexInPlane.x, v3VertexInPlane.z));
                }

                listlistCapPoints.Add(listCapPoints);
                listlistCapPolygonPoints.Add(listCapPolygonsPoints);
                listCapPolygons.Add(new Poly2Tri.Polygon(listCapPolygonsPoints));
            }

            // Remove close vertices

            float fPrecisionFix = Mathf.Max(Parameters.EPSILONCAPPRECISIONMIN, fracturedComponent.CapPrecisionFix);

            if(fPrecisionFix > 0.0f)
            {
                for(int nCap = 0; nCap < listlistCapPolygonPoints.Count; nCap++)
                {
                    double lastX = listlistCapPolygonPoints[nCap][listlistCapPolygonPoints[nCap].Count - 1].X;
                    double lastY = listlistCapPolygonPoints[nCap][listlistCapPolygonPoints[nCap].Count - 1].Y;

                    bool bDeleteCap = false;

                    for(int nVertex = 0; nVertex < listlistCapPolygonPoints[nCap].Count; nVertex++)
                    {
                        double vecX = listlistCapPolygonPoints[nCap][nVertex].X - lastX;
                        double vecY = listlistCapPolygonPoints[nCap][nVertex].Y - lastY;

                        if(System.Math.Sqrt(vecX * vecX + vecY * vecY) < fPrecisionFix)
                        {
                            listlistCapPolygonPoints[nCap].RemoveAt(nVertex);
                            nVertex--;

                            if(listlistCapPolygonPoints[nCap].Count < 3)
                            {
                                bDeleteCap = true;
                                break;
                            }
                        }
                        else
                        {
                            lastX = listlistCapPolygonPoints[nCap][nVertex].X;
                            lastY = listlistCapPolygonPoints[nCap][nVertex].Y;
                        }
                    }

                    if(bDeleteCap)
                    {
                        listlistCapPolygonPoints.RemoveAt(nCap);
                        nCap--;
                    }
                }
            }

            if(listlistCapPolygonPoints.Count == 0)
            {
                return;
            }

            // Search if one of the caps is contained in the other. If this happens we will mark the big one as the polygon and the rest as holes

            int nSuperPolygon = -1;
            Poly2Tri.Polygon polygonContainer = null;

            if(bForceVertexSoup == false)
            {
                for(int i = 0; i < listlistCapPolygonPoints.Count; i++)
                {
                    for(int j = 0; j < listlistCapPolygonPoints.Count; j++)
                    {
                        if(i != j && listlistCapPoints[i].Count >= 3 && listlistCapPoints[j].Count >= 3)
                        {
                            if(Poly2Tri.PolygonUtil.PolygonContainsPolygon(listlistCapPoints[i], listCapPolygons[i].Bounds, listlistCapPoints[j], listCapPolygons[j].Bounds, true))
                            {
                                nSuperPolygon = i;
                                break;
                            }
                            else if(Poly2Tri.PolygonUtil.PolygonContainsPolygon(listlistCapPoints[j], listCapPolygons[j].Bounds, listlistCapPoints[i], listCapPolygons[i].Bounds, true))
                            {
                                nSuperPolygon = j;
                                break;
                            }
                        }
                    }
                }

                // Add holes if this is a cap with holes

                if(nSuperPolygon != -1)
                {
                    polygonContainer = listCapPolygons[nSuperPolygon];

                    for(int i = 0; i < listlistCapPolygonPoints.Count; i++)
                    {
                        if(i != nSuperPolygon && listCapPolygons[i].Count >= 3)
                        {
                            polygonContainer.AddHole(listCapPolygons[i]);
                        }
                    }
                }
            }

            // Triangulate

            bool bTriangulatedWithHoles = false;

            if(polygonContainer != null && bForceVertexSoup == false)
            {
                // Polygon with holes

                try
                {
                    Poly2Tri.P2T.Triangulate(polygonContainer);

                    if(polygonContainer.Triangles != null)
                    {
                        List<Vector3> listMeshVertices = new List<Vector3>();
                        List<int>     listMeshIndices  = new List<int>();

                        CreateIndexedMesh(polygonContainer.Triangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                        Triangulate(    listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                        bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                        nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                        aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                    }

                    bTriangulatedWithHoles = true;
                }
                catch(System.Exception e)
                {
                    if(fracturedComponent.Verbose) Debug.LogWarning("Exception (" + e.GetType() + ") using hole triangulation (holes = " + listlistCapPolygonPoints.Count + "). Trying to use constrained delaunay.");
                    bTriangulatedWithHoles = false;
                }
            }

            if(bTriangulatedWithHoles == false)
            {
                if(bForceVertexSoup)
                {
                    // Vertex soup

                    List<Poly2Tri.TriangulationPoint> listPoints = new List<Poly2Tri.TriangulationPoint>();

                    if(listlistCapPolygonPoints.Count > 0)
                    {
                        foreach(Poly2Tri.PolygonPoint polyPoint in listlistCapPolygonPoints[0])
                        {
                            listPoints.Add(polyPoint);
                        }

                        try
                        {
                            if(listPoints.Count >= 3)
                            {
                                Poly2Tri.PointSet ps = new Poly2Tri.PointSet(listPoints);
                                Poly2Tri.P2T.Triangulate(ps);

                                if(ps.Triangles != null)
                                {
                                    List<Vector3> listMeshVertices = new List<Vector3>();
                                    List<int>     listMeshIndices  = new List<int>();

                                    CreateIndexedMesh(ps.Triangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                                    Triangulate(    listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                                    bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                                    nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                                    aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                                }
                            }
                        }
                        catch(System.Exception e)
                        {
                            if(fracturedComponent.Verbose) Debug.LogWarning("Exception (" + e.GetType() + ") using vertex soup triangulation.");
                        }
                    }
                }
                else
                {
                    // Use constrained delaunay triangulation

                    int nPoly = 0;

                    foreach(List<Poly2Tri.PolygonPoint> listPolyPoints in listlistCapPolygonPoints)
                    {
                        IList<Poly2Tri.DelaunayTriangle> listTriangles = null;

                        Poly2Tri.Polygon polygon = null;

                        try
                        {
                            if(listPolyPoints.Count >= 3)
                            {
                                polygon = new Poly2Tri.Polygon(listPolyPoints);
                                Poly2Tri.P2T.Triangulate(polygon);
                                listTriangles = polygon.Triangles;
                            }
                        }
                        catch(System.Exception e)
                        {
                            if(fracturedComponent.Verbose) Debug.LogWarning("Exception (" + e.GetType() + ") using polygon triangulation of cap polygon " + nPoly + ". Trying to use non constrained");
                            listTriangles = null;
                        }

                        if(listTriangles == null)
                        {
                            List<Poly2Tri.TriangulationPoint> listPoints = new List<Poly2Tri.TriangulationPoint>();

                            foreach(Poly2Tri.PolygonPoint polyPoint in listPolyPoints)
                            {
                                listPoints.Add(polyPoint);
                            }

                            try
                            {
                                if(listPoints.Count >= 3)
                                {
                                    Poly2Tri.PointSet ps = new Poly2Tri.PointSet(listPoints);
                                    Poly2Tri.P2T.Triangulate(ps);
                                    listTriangles = ps.Triangles;
                                }
                            }
                            catch(System.Exception e)
                            {
                                if(fracturedComponent.Verbose) Debug.LogWarning("Exception (" + e.GetType() + ") using non constrained triangulation of cap polygon " + nPoly + ". Skipping");
                            }
                        }

                        if(listTriangles != null)
                        {
                            List<Vector3> listMeshVertices = new List<Vector3>();
                            List<int>     listMeshIndices  = new List<int>();

                            CreateIndexedMesh(listTriangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                            Triangulate(    listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                            bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                            nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                            aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                        }

                        nPoly++;
                    }
                }
            }
        }
示例#2
0
        static void TriangulateConstrainedDelaunay(List <List <Vector3> > listlistPointsConstrainedDelaunay, List <List <int> > listlistHashValuesConstrainedDelaunay, bool bForceVertexSoup, FracturedObject fracturedComponent,
                                                   bool bConnectivityPostprocess, MeshFaceConnectivity faceConnectivityPos, MeshFaceConnectivity faceConnectivityNeg, MeshDataConnectivity meshConnectivityPos, MeshDataConnectivity meshConnectivityNeg, int nForceMeshConnectivityHash,
                                                   int nSplitCloseSubMesh, Matrix4x4 mtxPlane, Matrix4x4 mtxToLocalPos, Matrix4x4 mtxToLocalNeg, Vector3 v3CenterPos, Vector3 v3CenterNeg,
                                                   List <int>[] aListIndicesPosInOut, List <VertexData> listVertexDataPosInOut, List <int>[] aListIndicesNegInOut, List <VertexData> listVertexDataNegInOut)
        {
            // Pass to two dimensional plane:

            Matrix4x4 mtxPlaneInverse = mtxPlane.inverse;
            List <List <Poly2Tri.Point2D> >      listlistCapPoints        = new List <List <Poly2Tri.Point2D> >();
            List <List <Poly2Tri.PolygonPoint> > listlistCapPolygonPoints = new List <List <Poly2Tri.PolygonPoint> >();
            List <Poly2Tri.Polygon> listCapPolygons = new List <Poly2Tri.Polygon>();

            for (int i = 0; i < listlistPointsConstrainedDelaunay.Count; i++)
            {
                List <Poly2Tri.Point2D>      listCapPoints         = new List <Poly2Tri.Point2D>();
                List <Poly2Tri.PolygonPoint> listCapPolygonsPoints = new List <Poly2Tri.PolygonPoint>();

                foreach (Vector3 v3Vertex in listlistPointsConstrainedDelaunay[i])
                {
                    Vector3 v3VertexInPlane = mtxPlaneInverse.MultiplyPoint3x4(v3Vertex);
                    listCapPoints.Add(new Poly2Tri.Point2D(v3VertexInPlane.x, v3VertexInPlane.z));
                    listCapPolygonsPoints.Add(new Poly2Tri.PolygonPoint(v3VertexInPlane.x, v3VertexInPlane.z));
                }

                listlistCapPoints.Add(listCapPoints);
                listlistCapPolygonPoints.Add(listCapPolygonsPoints);
                listCapPolygons.Add(new Poly2Tri.Polygon(listCapPolygonsPoints));
            }

            // Remove close vertices

            float fPrecisionFix = Mathf.Max(Parameters.EPSILONCAPPRECISIONMIN, fracturedComponent.CapPrecisionFix);

            if (fPrecisionFix > 0.0f)
            {
                for (int nCap = 0; nCap < listlistCapPolygonPoints.Count; nCap++)
                {
                    double lastX = listlistCapPolygonPoints[nCap][listlistCapPolygonPoints[nCap].Count - 1].X;
                    double lastY = listlistCapPolygonPoints[nCap][listlistCapPolygonPoints[nCap].Count - 1].Y;

                    bool bDeleteCap = false;

                    for (int nVertex = 0; nVertex < listlistCapPolygonPoints[nCap].Count; nVertex++)
                    {
                        double vecX = listlistCapPolygonPoints[nCap][nVertex].X - lastX;
                        double vecY = listlistCapPolygonPoints[nCap][nVertex].Y - lastY;

                        if (System.Math.Sqrt(vecX * vecX + vecY * vecY) < fPrecisionFix)
                        {
                            listlistCapPolygonPoints[nCap].RemoveAt(nVertex);
                            nVertex--;

                            if (listlistCapPolygonPoints[nCap].Count < 3)
                            {
                                bDeleteCap = true;
                                break;
                            }
                        }
                        else
                        {
                            lastX = listlistCapPolygonPoints[nCap][nVertex].X;
                            lastY = listlistCapPolygonPoints[nCap][nVertex].Y;
                        }
                    }

                    if (bDeleteCap)
                    {
                        listlistCapPolygonPoints.RemoveAt(nCap);
                        nCap--;
                    }
                }
            }

            if (listlistCapPolygonPoints.Count == 0)
            {
                return;
            }

            // Search if one of the caps is contained in the other. If this happens we will mark the big one as the polygon and the rest as holes

            int nSuperPolygon = -1;

            Poly2Tri.Polygon polygonContainer = null;

            if (bForceVertexSoup == false)
            {
                for (int i = 0; i < listlistCapPolygonPoints.Count; i++)
                {
                    for (int j = 0; j < listlistCapPolygonPoints.Count; j++)
                    {
                        if (i != j && listlistCapPoints[i].Count >= 3 && listlistCapPoints[j].Count >= 3)
                        {
                            if (Poly2Tri.PolygonUtil.PolygonContainsPolygon(listlistCapPoints[i], listCapPolygons[i].Bounds, listlistCapPoints[j], listCapPolygons[j].Bounds, true))
                            {
                                nSuperPolygon = i;
                                break;
                            }
                            else if (Poly2Tri.PolygonUtil.PolygonContainsPolygon(listlistCapPoints[j], listCapPolygons[j].Bounds, listlistCapPoints[i], listCapPolygons[i].Bounds, true))
                            {
                                nSuperPolygon = j;
                                break;
                            }
                        }
                    }
                }

                // Add holes if this is a cap with holes

                if (nSuperPolygon != -1)
                {
                    polygonContainer = listCapPolygons[nSuperPolygon];

                    for (int i = 0; i < listlistCapPolygonPoints.Count; i++)
                    {
                        if (i != nSuperPolygon && listCapPolygons[i].Count >= 3)
                        {
                            polygonContainer.AddHole(listCapPolygons[i]);
                        }
                    }
                }
            }

            // Triangulate

            bool bTriangulatedWithHoles = false;

            if (polygonContainer != null && bForceVertexSoup == false)
            {
                // Polygon with holes

                try
                {
                    Poly2Tri.P2T.Triangulate(polygonContainer);

                    if (polygonContainer.Triangles != null)
                    {
                        List <Vector3> listMeshVertices = new List <Vector3>();
                        List <int>     listMeshIndices  = new List <int>();

                        CreateIndexedMesh(polygonContainer.Triangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                        Triangulate(listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                    bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                    nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                    aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                    }

                    bTriangulatedWithHoles = true;
                }
                catch (System.Exception e)
                {
                    if (fracturedComponent.Verbose)
                    {
                        Debug.LogWarning("Exception (" + e.GetType() + ") using hole triangulation (holes = " + listlistCapPolygonPoints.Count + "). Trying to use constrained delaunay.");
                    }
                    bTriangulatedWithHoles = false;
                }
            }

            if (bTriangulatedWithHoles == false)
            {
                if (bForceVertexSoup)
                {
                    // Vertex soup

                    List <Poly2Tri.TriangulationPoint> listPoints = new List <Poly2Tri.TriangulationPoint>();

                    if (listlistCapPolygonPoints.Count > 0)
                    {
                        foreach (Poly2Tri.PolygonPoint polyPoint in listlistCapPolygonPoints[0])
                        {
                            listPoints.Add(polyPoint);
                        }

                        try
                        {
                            if (listPoints.Count >= 3)
                            {
                                Poly2Tri.PointSet ps = new Poly2Tri.PointSet(listPoints);
                                Poly2Tri.P2T.Triangulate(ps);

                                if (ps.Triangles != null)
                                {
                                    List <Vector3> listMeshVertices = new List <Vector3>();
                                    List <int>     listMeshIndices  = new List <int>();

                                    CreateIndexedMesh(ps.Triangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                                    Triangulate(listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                                bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                                nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                                aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                                }
                            }
                        }
                        catch (System.Exception e)
                        {
                            if (fracturedComponent.Verbose)
                            {
                                Debug.LogWarning("Exception (" + e.GetType() + ") using vertex soup triangulation.");
                            }
                        }
                    }
                }
                else
                {
                    // Use constrained delaunay triangulation

                    int nPoly = 0;

                    foreach (List <Poly2Tri.PolygonPoint> listPolyPoints in listlistCapPolygonPoints)
                    {
                        IList <Poly2Tri.DelaunayTriangle> listTriangles = null;

                        Poly2Tri.Polygon polygon = null;

                        try
                        {
                            if (listPolyPoints.Count >= 3)
                            {
                                polygon = new Poly2Tri.Polygon(listPolyPoints);
                                Poly2Tri.P2T.Triangulate(polygon);
                                listTriangles = polygon.Triangles;
                            }
                        }
                        catch (System.Exception e)
                        {
                            if (fracturedComponent.Verbose)
                            {
                                Debug.LogWarning("Exception (" + e.GetType() + ") using polygon triangulation of cap polygon " + nPoly + ". Trying to use non constrained");
                            }
                            listTriangles = null;
                        }

                        if (listTriangles == null)
                        {
                            List <Poly2Tri.TriangulationPoint> listPoints = new List <Poly2Tri.TriangulationPoint>();

                            foreach (Poly2Tri.PolygonPoint polyPoint in listPolyPoints)
                            {
                                listPoints.Add(polyPoint);
                            }

                            try
                            {
                                if (listPoints.Count >= 3)
                                {
                                    Poly2Tri.PointSet ps = new Poly2Tri.PointSet(listPoints);
                                    Poly2Tri.P2T.Triangulate(ps);
                                    listTriangles = ps.Triangles;
                                }
                            }
                            catch (System.Exception e)
                            {
                                if (fracturedComponent.Verbose)
                                {
                                    Debug.LogWarning("Exception (" + e.GetType() + ") using non constrained triangulation of cap polygon " + nPoly + ". Skipping");
                                }
                            }
                        }

                        if (listTriangles != null)
                        {
                            List <Vector3> listMeshVertices = new List <Vector3>();
                            List <int>     listMeshIndices  = new List <int>();

                            CreateIndexedMesh(listTriangles, listMeshVertices, listMeshIndices, mtxPlane, true);

                            Triangulate(listMeshVertices, listMeshIndices, fracturedComponent, listlistPointsConstrainedDelaunay, listlistHashValuesConstrainedDelaunay,
                                        bConnectivityPostprocess, faceConnectivityPos, faceConnectivityNeg, meshConnectivityPos, meshConnectivityNeg, nForceMeshConnectivityHash,
                                        nSplitCloseSubMesh, mtxPlane, mtxToLocalPos, mtxToLocalNeg, v3CenterPos, v3CenterNeg,
                                        aListIndicesPosInOut, listVertexDataPosInOut, aListIndicesNegInOut, listVertexDataNegInOut);
                        }

                        nPoly++;
                    }
                }
            }
        }