public void GenerateMeshes(JSONPuzzle puzzle) { foreach (var piece in puzzle.pieces) { var mesh = new Mesh(); var vertices = new Vector3[piece.corners.Length]; var idx = 0; foreach (var corner in piece.corners) { vertices[idx].x = corner.coord.x; vertices[idx].y = corner.coord.y; idx++; } mesh.vertices = vertices; mesh.uv = GetComponent <MeshModel>().newUV; var verticesList = new List <Vector3>(); foreach (var vertex in vertices) { verticesList.Add(vertex); } var triangles = PolygonTriangulation.TriangulateConcavePolygon(verticesList); var trianglesAsIntArray = new int[triangles.Count * 3]; idx = 0; foreach (var triangle in triangles) { trianglesAsIntArray[idx] = Array.IndexOf(vertices, triangle.vertex1.GetXY()); trianglesAsIntArray[idx + 1] = Array.IndexOf(vertices, triangle.vertex2.GetXY()); trianglesAsIntArray[idx + 2] = Array.IndexOf(vertices, triangle.vertex3.GetXY()); idx += 3; } mesh.triangles = trianglesAsIntArray; GetComponent <MeshModel>().meshes.Add(mesh); } }
[OvldGenCallTarget] public static void Polygon([OvldDefault(nameof(BlendMode))] ShapesBlendMode blendMode, PolygonPath path, [OvldDefault(nameof(PolygonTriangulation))] PolygonTriangulation triangulation, [OvldDefault(nameof(Color))] Color color, [OvldDefault(nameof(PolygonShapeFill))] ShapeFill fill) { if (path.EnsureMeshIsReadyToRender(triangulation, out Mesh mesh) == false) { return; // no points defined in the mesh } switch (path.Count) { case 0: Debug.LogWarning("Tried to draw polygon with no points"); return; case 1: Debug.LogWarning("Tried to draw polygon with only one point"); return; case 2: Debug.LogWarning("Tried to draw polygon with only two points"); return; } Material matPolygon = ShapesMaterialUtils.matPolygon[blendMode]; ApplyGlobalProperties(matPolygon); TryApplyFillAndColor(matPolygon, fill, color); DrawMesh(Vector3.zero, Quaternion.identity, mesh, matPolygon); }
[OvldGenCallTarget] static void Polygon_Internal(PolygonPath path, [OvldDefault(nameof(PolygonTriangulation))] PolygonTriangulation triangulation, [OvldDefault(nameof(Color))] Color color) { if (path.EnsureMeshIsReadyToRender(triangulation, out Mesh mesh) == false) { return; // no points defined in the mesh } switch (path.Count) { case 0: Debug.LogWarning("Tried to draw polygon with no points"); return; case 1: Debug.LogWarning("Tried to draw polygon with only one point"); return; case 2: Debug.LogWarning("Tried to draw polygon with only two points"); return; } if (DrawCommand.IsAddingDrawCommandsToBuffer) // mark as used by this command to prevent destroy in dispose { path.RegisterToCommandBuffer(DrawCommand.CurrentWritingCommandBuffer); } using (new IMDrawer(mpbPolygon, ShapesMaterialUtils.matPolygon[Draw.BlendMode], mesh)) { MetaMpb.ApplyColorOrFill(mpbPolygon, color); } }
[OvldGenCallTarget] static void Polygon([OvldDefault(nameof(BlendMode))] ShapesBlendMode blendMode, PolygonPath path, [OvldDefault(nameof(PolygonTriangulation))] PolygonTriangulation triangulation, [OvldDefault(nameof(Color))] Color color, [OvldDefault(nameof(PolygonShapeFill))] ShapeFill fill) { if (path.EnsureMeshIsReadyToRender(triangulation, out Mesh mesh) == false) { return; // no points defined in the mesh } switch (path.Count) { case 0: Debug.LogWarning("Tried to draw polygon with no points"); return; case 1: Debug.LogWarning("Tried to draw polygon with only one point"); return; case 2: Debug.LogWarning("Tried to draw polygon with only two points"); return; } using (new IMDrawer(mpbPolygon, ShapesMaterialUtils.matPolygon[blendMode], mesh)) { MetaMpb.ApplyColorOrFill(mpbPolygon, fill, color); } }
public static bool IsVertexContainedInPiece(Vector3 vertexToCheck, Vector3[] vertices, int[] triangles) { for (int i = 0; i < triangles.Length; i += 3) { var p1 = vertices[triangles[i]]; var p2 = vertices[triangles[i + 1]]; var p3 = vertices[triangles[i + 2]]; if (PolygonTriangulation.IsPointInTriangle(p1, p2, p3, vertexToCheck, 0.05f)) { Debug.Log("point is in triangle."); return(true); } } Debug.Log("point is NOT in triangle."); return(false); }
static bool generatingClockwisePolygon; // assigned in GenPolygonMesh, used by EarClipPoint public static void GenPolygonMesh(Mesh mesh, List <Vector2> path, PolygonTriangulation triangulation) { // kinda have to do this, the algorithm relies on knowing this generatingClockwisePolygon = ShapesMath.PolygonSignedArea(path) > 0; mesh.Clear(); // todo maybe not always do this you know? int pointCount = path.Count; if (pointCount < 2) { return; } int triangleCount = pointCount - 2; int triangleIndexCount = triangleCount * 3; int[] meshTriangles = new int[triangleIndexCount]; if (triangulation == PolygonTriangulation.FastConvexOnly) { int tri = 0; for (int i = 0; i < triangleCount; i++) { meshTriangles[tri++] = i + 2; meshTriangles[tri++] = i + 1; meshTriangles[tri++] = 0; } } else { List <EarClipPoint> pointsLeft = new List <EarClipPoint>(pointCount); for (int i = 0; i < pointCount; i++) { pointsLeft.Add(new EarClipPoint(i, new Vector2(path[i].x, path[i].y))); } for (int i = 0; i < pointCount; i++) // update prev/next connections { EarClipPoint p = pointsLeft[i]; p.prev = pointsLeft[(i + pointCount - 1) % pointCount]; p.next = pointsLeft[(i + 1) % pointCount]; } int tri = 0; int countLeft; int safeguard = 1000000; while ((countLeft = pointsLeft.Count) >= 3 && (safeguard-- > 0)) { //for( int k = 0; k < pointsLeft.Count * 2; k++ ) { if (countLeft == 3) { // final triangle meshTriangles[tri++] = pointsLeft[2].vertIndex; meshTriangles[tri++] = pointsLeft[1].vertIndex; meshTriangles[tri++] = pointsLeft[0].vertIndex; break; } // iterate until we find a convex vertex bool foundConvex = false; for (int i = 0; i < countLeft; i++) { EarClipPoint p = pointsLeft[i]; if (p.ReflexState == ReflexState.Convex) { // it's convex! now make sure there are no reflex points inside bool canClipEar = true; int idPrev = (i + countLeft - 1) % countLeft; int idNext = (i + 1) % countLeft; for (int j = 0; j < countLeft; j++) { if (j == i) { continue; // skip self } if (j == idPrev) { continue; // skip next } if (j == idNext) { continue; // skip prev } if (pointsLeft[j].ReflexState == ReflexState.Reflex) { // found a reflex point, make sure it's outside the triangle if (ShapesMath.PointInsideTriangle(p.next.pt, p.pt, p.prev.pt, pointsLeft[j].pt, 0f, -0.0001f, 0f)) { canClipEar = false; // it's inside, rip break; } } } if (canClipEar) { meshTriangles[tri++] = p.next.vertIndex; meshTriangles[tri++] = p.vertIndex; meshTriangles[tri++] = p.prev.vertIndex; p.next.MarkReflexUnknown(); p.prev.MarkReflexUnknown(); (p.next.prev, p.prev.next) = (p.prev, p.next); // update prev/next pointsLeft.RemoveAt(i); foundConvex = true; break; // stop search for more convex edges, restart loop } } } // no convex found?? if (foundConvex == false) { Debug.LogError("Invalid polygon triangulation - no convex edges found. Your polygon is likely self-intersecting"); goto breakBoth; } } breakBoth: if (safeguard < 1) { Debug.LogError("Polygon triangulation failed, please report a bug (Shapes/Report Bug) with this exact case included"); } } // assign to segments mesh List <Vector3> verts3D = new List <Vector3>(pointCount); for (int i = 0; i < pointCount; i++) { verts3D.Add(path[i]); } mesh.SetVertices(verts3D); mesh.subMeshCount = 1; mesh.SetTriangles(meshTriangles, 0); }
public float[] CalculateAnglesFromMesh(Mesh mesh) { //moving clockwise around the piece int n = mesh.vertices.Length; float[] angles = new float[n]; int i = 0; Vector3 a = new Vector3(mesh.vertices[n - 1].x, mesh.vertices[n - 1].y, 0); Vector3 b = new Vector3(mesh.vertices[i].x, mesh.vertices[i].y, 0); Vector3 c = new Vector3(mesh.vertices[i + 1].x, mesh.vertices[i + 1].y, 0); Vector3 temp1 = b - a; Vector3 temp2 = b - c; float angle = Vector3.SignedAngle(temp1, temp2, Vector3.up); Vertex vertex = new Vertex(b); Vertex prev = new Vertex(a); Vertex next = new Vertex(c); vertex.previousVertex = prev; vertex.nextVertex = next; PolygonTriangulation.CheckIfReflexOrConvex(vertex); if (vertex.isReflex == true) { angle = 360 - angle; } angles[i] = angle; i++; while (i < n) { if (i < n - 1) { a = new Vector3(mesh.vertices[i - 1].x, mesh.vertices[i - 1].y, 0); b = new Vector3(mesh.vertices[i].x, mesh.vertices[i].y, 0); c = new Vector3(mesh.vertices[i + 1].x, mesh.vertices[i + 1].y, 0); temp1 = b - a; temp2 = b - c; angle = Vector3.SignedAngle(temp1, temp2, Vector3.up); vertex = new Vertex(b); prev = new Vertex(a); next = new Vertex(c); vertex.previousVertex = prev; vertex.nextVertex = next; PolygonTriangulation.CheckIfReflexOrConvex(vertex); if (vertex.isReflex == true) { angle = 360 - angle; } angles[i] = angle; } else { a = new Vector3(mesh.vertices[i - 1].x, mesh.vertices[i - 1].y, 0); b = new Vector3(mesh.vertices[i].x, mesh.vertices[i].y, 0); c = new Vector3(mesh.vertices[0].x, mesh.vertices[0].y, 0); temp1 = b - a; temp2 = b - c; angle = Vector3.SignedAngle(temp1, temp2, Vector3.up); vertex = new Vertex(b); prev = new Vertex(a); next = new Vertex(c); vertex.previousVertex = prev; vertex.nextVertex = next; PolygonTriangulation.CheckIfReflexOrConvex(vertex); if (vertex.isReflex == true) { angle = 360 - angle; } angles[i] = angle; } i++; } return(angles); }