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++; } } } }
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++; } } } }