Utility.Polygon SetOuterQuadsAndTris(List <LineSegment> lines) { Utility.Polygon mesh = new Utility.Polygon(); for (int i = 0; i < lines.Count - 1; i++) { if (lines[i].v1 == lines[i + 1].v1) { mesh.AddTri(lines[i].v1, lines[i + 1].v2, lines[i].v2, ToUV(lines[i].v1), ToUV(lines[i + 1].v2), ToUV(lines[i].v2), flipMesh); } else if (lines[i].v2 == lines[i + 1].v2) { mesh.AddTri(lines[i].v1, lines[i + 1].v1, lines[i].v2, ToUV(lines[i].v1), ToUV(lines[i + 1].v1), ToUV(lines[i].v2), flipMesh); } else { mesh.AddQuad(lines[i].v1, lines[i + 1].v1, lines[i].v2, lines[i + 1].v2, ToUV(lines[i].v1), ToUV(lines[i + 1].v1), ToUV(lines[i].v2), ToUV(lines[i + 1].v2), flipMesh); } } if (lines[lines.Count - 1].v1 == lines[0].v1 && lines[lines.Count - 1].v2 != lines[0].v2) { mesh.AddTri(lines[lines.Count - 1].v1, lines[0].v2, lines[lines.Count - 1].v2, ToUV(lines[lines.Count - 1].v1), ToUV(lines[0].v2), ToUV(lines[lines.Count - 1].v2), flipMesh); } else if (lines[lines.Count - 1].v2 == lines[0].v2 && lines[lines.Count - 1].v1 != lines[0].v1) { mesh.AddTri(lines[lines.Count - 1].v1, lines[0].v1, lines[lines.Count - 1].v2, ToUV(lines[lines.Count - 1].v1), ToUV(lines[0].v1), ToUV(lines[lines.Count - 1].v2), flipMesh); } return(mesh); }
Utility.Polygon GetRidgeBounded(Vector3[] edge1, Vector3[] edge2, Vector3[] startEdge, Vector3[] endEdge) { Utility.Polygon mesh = new Utility.Polygon(); List <List <Vector3> > rows = new List <List <Vector3> >(); if (startEdge != null) { rows.Add(new List <Vector3>(startEdge)); } for (int i = 0; i <= edge1.Length - 1; i++) { int rowI = rows.Count; rows.Add(GetBoundedRow(edge1[i], i != edge1.Length - 1 ? edge1[i + 1] : edge1[i] * 2 - edge1[i - 1], edge2[i], i / (edge1.Length - 1f), 1 / (edge1.Length - 1f))); if (rowI > 0) { AddToMesh(mesh, rows[rowI - 1], rows[rowI], rowI, edge1.Length); } } if (endEdge != null) { AddToMesh(mesh, rows[rows.Count - 1], new List <Vector3>(endEdge), rows.Count, (rows.Count + .5f) / (rows.Count + 1), true); } return(mesh); }
Utility.Polygon GetRidgeWalkway(Vector3[] center, Vector3[] normals, Vector3[] startEdge, Vector3[] endEdge) { Utility.Polygon mesh = new Utility.Polygon(); List <List <Vector3> > rows = new List <List <Vector3> >(); if (startEdge != null) { rows.Add(new List <Vector3>(startEdge)); } for (int i = 0; i < center.Length; i++) { int rowI = rows.Count; rows.Add(GetWalkwayRow(center[i], i != center.Length - 1 ? center[i + 1] : center[i] * 2 - center[i - 1], normals[i], i / (center.Length - 1f), 1 / (center.Length - 1f))); if (rowI > 0 && rows[rowI - 1].Count > 0) { AddToMesh(mesh, rows[rowI - 1], rows[rowI], rowI, center.Length); } } if (endEdge != null && endEdge.Length > 0) { AddToMesh(mesh, rows[rows.Count - 1], new List <Vector3>(endEdge), rows.Count, (rows.Count + .5f) / (rows.Count + 1), true); } return(mesh); }
Utility.Polygon AddInnerQuadsAndTris(List <Vector3> validQuads, List <Vector3> validTris) { Utility.Polygon poly = new Utility.Polygon(); foreach (Vector3 quad in validQuads) { bool xEven = Mathf.Round(quad.x * gridScale) % 2 == 0; bool zEven = Mathf.Round(quad.z * gridScale) % 2 == 0; Vector3 quadR = Vector3.right * gridScale; Vector3 quadF = Vector3.forward * gridScale; if (!IsHole(quad, quad + quadF, quad + quadR, quad + quadR + quadF)) { if (xEven == zEven) { poly.AddQuad(quad, quad + quadF, quad + quadR, quad + quadR + quadF, ToUV(quad), ToUV(quad + quadF), ToUV(quad + quadR), ToUV(quad + quadR + quadF), flipMesh); } else { poly.AddQuad(quad + quadF, quad + quadR + quadF, quad, quad + quadR, ToUV(quad + quadF), ToUV(quad + quadR + quadF), ToUV(quad), ToUV(quad + quadR), flipMesh); } } } for (int t = 0; t < validTris.Count; t += 3) { if (Vector3.Cross(validTris[t + 1] - validTris[t], validTris[t + 2] - validTris[t]).normalized == Vector3.up) { poly.AddTri(validTris[t], validTris[t + 1], validTris[t + 2], ToUV(validTris[t]), ToUV(validTris[t + 1]), ToUV(validTris[t + 2]), flipMesh); } else { poly.AddTri(validTris[t], validTris[t + 2], validTris[t + 1], ToUV(validTris[t]), ToUV(validTris[t + 2]), ToUV(validTris[t + 1]), flipMesh); } } return(poly); }
public override Mesh CreateMesh() { if (gridCount < 1) { gridCount = 1; } debugList1 = new List <LineSegment>(); ClearOutput(); if (pathCreator != null) { Utility.Polygon poly = GetRidgeWalkway(pathCreator.path.vertices, pathCreator.path.normals, CheckConnection(0) ? inputs[0].Edge : null, CheckConnection(1) ? inputs[1].Edge : null); Mesh mesh = new Mesh() { vertices = poly.verts.ToArray(), triangles = poly.tris.ToArray(), uv = poly.uvs.Select(u => new Vector2(u.y, u.x)).ToArray() }; mesh.RecalculateNormals(); FinishOutputs(null); return(mesh); } else if (inputs != null) { List <List <Vector3> > edges = new List <List <Vector3> >(); for (int i = 0; i < inputs.Length; i++) { if (CheckConnection(i)) { edges.Add(new List <Vector3>(inputs[i].Edge)); } else { edges.Add(null); } } if (edges.Count < 2 || edges[0] == null || edges[0].Count < 2 || edges[1] == null || edges[1].Count < 2) { return(new Mesh()); } int minLength = Mathf.Min(edges[0].Count, edges[1].Count); edges[0] = edges[0].GetRange(0, minLength); edges[1] = edges[1].GetRange(0, minLength); Utility.Polygon poly = GetRidgeBounded(edges[0].ToArray(), edges[1].ToArray(), edges.Count > 2 && edges[2] != null ? edges[2].ToArray() : null, edges.Count > 3 && edges[3] != null ? edges[3].ToArray() : null); Mesh mesh = new Mesh() { vertices = poly.verts.ToArray(), triangles = poly.tris.ToArray(), uv = poly.uvs.ToArray() }; mesh.RecalculateNormals(); FinishOutputs(null); return(mesh); } return(new Mesh()); }
/* * private void OnDrawGizmos() { * if (debug) { * if (debugSegList != null) { * for (int i = 0; i < debugSegList.Count; i++) { * Gizmos.color = Color.magenta; * Gizmos.DrawLine(debugSegList[i].v1, debugSegList[i].v2); * } * } * } * } */ public override Mesh CreateMesh() { //print("Updating " + typeof(PathGroundCreator)); debugSegList = new List <LineSegment>(); leaveHeightsUnchanged = new List <Vector3>(); if (gridScale <= 0) { gridScale = 1f; } ClearOutput(); if (pathCreator != null) { pathHeight = pathCreator.bezierPath.HeightOffset; if (!pathCreator.bezierPath.IsClosed && CheckConnection(0)) { outerRing = new List <Vector3>(pathCreator.path.vertices); for (int i = 0; i < inputs.Length; i++) { if (CheckConnection(i)) { List <Vector3> edgeList = new List <Vector3>(inputs[i].Edge); leaveHeightsUnchanged.AddRange(edgeList); AddEdge(outerRing, edgeList); } } ClosePath(outerRing, gridScale, pathHeight); bounds = GetBounds(outerRing); } else { outerRing = new List <Vector3>(pathCreator.path.vertices); bounds = pathCreator.path.bounds; } } else if (CheckConnection(0)) { outerRing = new List <Vector3>(); for (int i = 0; i < inputs.Length; i++) { if (CheckConnection(i)) { if (outerRing.Count == 0) { outerRing.AddRange(new List <Vector3>(inputs[i].Edge)); } else { AddEdge(outerRing, new List <Vector3>(inputs[i].Edge)); } } } if (outerRing.Count == 0) { print("Failed Ground Build"); return(new Mesh()); } leaveHeightsUnchanged.AddRange(outerRing); if (closed) { outerRing.Add(outerRing[0]); } else { ClosePath(outerRing, gridScale, 0); } bounds = GetBounds(outerRing); } else { return(new Mesh()); } if (flipBorder) { outerRing.Reverse(); } List <Vector3> validQuads = new List <Vector3>(); List <Vector3> validTris = new List <Vector3>(); SetInnerRing(outerRing.ToArray(), validQuads, validTris); lineRing = SetLineSegmentRing(outerRing, innerRing); Utility.Polygon poly = SetOuterQuadsAndTris(lineRing); poly.Combine(AddInnerQuadsAndTris(validQuads, validTris)); poly.verts = ModifyGroundHeights(poly.verts); Mesh mesh = new Mesh() { vertices = poly.verts.ToArray(), triangles = poly.tris.ToArray(), uv = poly.uvs.ToArray() }; mesh.RecalculateNormals(); FinishOutputs(ModifyGroundHeights(outerRing)); return(mesh); }
protected void AddToMesh(Utility.Polygon mesh, List <Vector3> row1, List <Vector3> row2, int rowI, float widthMax, bool end = false) { float widthDelta = 1f / widthMax * .5f; float heightDelta = 1f / row1.Count * .5f; float width1 = (rowI - 1) / widthMax; float width2 = (rowI) / widthMax; if (row1.Count == row2.Count) { for (int j = 0; j < row2.Count - 1 && j < row1.Count - 1; j++) { float height1 = (float)(j) / (row1.Count); float height2 = (float)(j + 1) / (row2.Count); if (!CheckQuadInHole(row1[j], row1[j + 1], row2[j], row2[j + 1], width1, width2, widthDelta, height2, height2, heightDelta)) { if ((rowI + j) % 2 == 0) { mesh.AddQuad(row1[j], row1[j + 1], row2[j], row2[j + 1], new Vector2(width1, height1), new Vector2(width1, height2), new Vector2(width2, height1), new Vector2(width2, height2), flipMesh); } else { mesh.AddQuad(row1[j + 1], row2[j + 1], row1[j], row2[j], new Vector2(width1, height2), new Vector2(width2, height2), new Vector2(width1, height1), new Vector2(width2, height1), flipMesh); } } } } else { if (end) { if (Vector3.Distance(row1[0], row2[0]) > Vector3.Distance(row1[0], row2[row2.Count - 1])) { row2.Reverse(); } } else { if (Vector3.Distance(row1[0], row2[0]) > Vector3.Distance(row1[row1.Count - 1], row2[0])) { row1.Reverse(); } } int i = 0, j = 0; Vector3 start1 = row1[0], start2 = row2[0]; while (i < row1.Count - 1 && j < row2.Count - 1) { float height1 = (float)(i + 1) / (row1.Count); float height2 = (float)(j + 1) / (row2.Count); if (!CheckQuadInHole(row1[i], row1[i + 1], row2[j], row2[j + 1], width1, width2, widthDelta, height1, height2, heightDelta)) { if (Vector3.Distance(row1[i], row2[j + 1]) < Vector3.Distance(row2[j], row1[i + 1])) { ++j; mesh.AddTri(start1, row2[j], start2, new Vector2(width1, height1), new Vector2(width2, height2), new Vector2(width2, height1), flipMesh); start2 = row2[j]; } else { ++i; mesh.AddTri(start1, row1[i], start2, new Vector2(width1, height1), new Vector2(width1, height2), new Vector2(width2, height1), flipMesh); start1 = row1[i]; } } else { ++j; ++i; } } if (i < row1.Count - 1) { while (i < row1.Count - 1) { ++i; float height1 = (float)(i + 1) / (row1.Count); float height2 = (float)(j + 1) / (row2.Count); if (!CheckQuadInHole(row1[i - 1], row1[i], row2[j], row2[j], width1, width2, widthDelta, height1, height2, heightDelta)) { mesh.AddTri(start1, row1[i], start2, new Vector2(width1, height1), new Vector2(width1, height2), new Vector2(width2, height1), flipMesh); } start1 = row1[i]; } } else if (j < row2.Count - 1) { while (j < row2.Count - 1) { ++j; float height1 = (float)(i + 1) / (row1.Count); float height2 = (float)(j + 1) / (row2.Count); if (!CheckQuadInHole(row1[i], row1[i], row2[j - 1], row2[j], width1, width2, widthDelta, height1, height2, heightDelta)) { mesh.AddTri(start1, row2[j], start2, new Vector2(width1, height1), new Vector2(width2, height2), new Vector2(width2, height1), flipMesh); } start2 = row2[j]; } } } }
public override Mesh CreateMesh() { //print("Updating " + typeof(PathWallCreator)); ClearOutput(); List <Vector3[]> setWall = new List <Vector3[]>(); Vector3[] setNorm = new Vector3[0]; if (closed) { List <Vector3> edgeList = new List <Vector3>(); List <Vector3> normList = new List <Vector3>(); if (pathCreator != null) { edgeList.AddRange(pathCreator.path.vertices); normList.AddRange(pathCreator.path.normals); } for (int i = 0; i < inputs.Length; i++) { if (CheckConnection(i)) { AddEdge(edgeList, normList, inputs[i].Edge, inputs[i].Norm); } } if (pathCreator != null && edgeList.Count > pathCreator.path.NumVertices) { edgeList.Add(edgeList[0]); normList.Add(normList[0]); } if (pathClosed = Vector3.Distance(edgeList[0], edgeList[edgeList.Count - 1]) <= .001f) { edgeList[edgeList.Count - 1] = edgeList[0]; } setWall.Add(edgeList.ToArray()); setNorm = normList.ToArray(); } else { if (pathCreator != null) { setWall.Add(pathCreator.path.vertices); setNorm = pathCreator.path.normals; pathClosed = pathCreator.bezierPath.IsClosed; } for (int i = 0; i < inputs.Length; i++) { if (CheckConnection(i)) { setWall.Add(inputs[i].Edge); if (setWall.Count == 1) { setNorm = inputs[i].Norm; if (setWall[0].Length == setNorm.Length + 1) { setWall[0] = new List <Vector3>(setWall[0]).GetRange(1, setNorm.Length).ToArray(); } } } else { setWall.Add(null); } } } if (wallHeight != 0 && gridScale > 0.01f && setWall.Count > 0 && setWall[0] != null) { if (pathClosed = setWall[0][0] == setWall[0][setWall[0].Length - 1]) { setNorm[0] = ((setNorm[0] + setNorm[setNorm.Length - 1]) * .5f).normalized; setNorm[setNorm.Length - 1] = setNorm[0]; } } else { print("No path: " + typeof(PathWallCreator)); return(new Mesh()); } Utility.Polygon poly = GetWall(setWall[0], setNorm, setWall.Count > 1 ? setWall[1] : null, setWall.Count > 2 ? setWall[2] : null, setWall.Count > 3 ? setWall[3] : null); Mesh mesh = new Mesh() { vertices = poly.verts.ToArray(), triangles = poly.tris.ToArray(), uv = poly.uvs.ToArray() }; mesh.RecalculateNormals(); FinishOutputs(new List <Vector3>(setWall[0])); return(mesh); }
Utility.Polygon GetWall(Vector3[] wallBase, Vector3[] normals, Vector3[] startEdge, Vector3[] endEdge, Vector3[] topEdge) { Utility.Polygon mesh = new Utility.Polygon(); float maxVerts = (wallBase.Length - 1) * density; List <List <Vector3> > rows = new List <List <Vector3> > { GetWallRow(wallBase[0], Vector3.zero, normals[0], 0, 1 / maxVerts) }; if (topEdge != null) { if (heightCurve.Evaluate(0) == 0) { rows[0].Add(CheckAddOutput(topEdge[0], 0, 1 / maxVerts, 1.1f, 0)); } else { rows[0].Add(CheckAddOutput(Utility.GetClosest(topEdge, rows[0][rows[0].Count - 1]), 0, 1 / maxVerts, 1.1f, gridScale / Mathf.Abs(wallHeight * heightCurve.Evaluate(0)) * .5f)); } } if (startEdge != null && startEdge.Length > 0) { if (startEdge[0] == rows[0][0]) { EditOutput(rows[0][rows[0].Count - 1], startEdge[startEdge.Length - 1]); rows[0][rows[0].Count - 1] = startEdge[startEdge.Length - 1]; } AddToMesh(mesh, new List <Vector3>(startEdge), rows[0], 0, maxVerts); } for (int i = 0; i < wallBase.Length - 1; i++) { for (float d = 1; d <= density; d++) { int rowIndex = rows.Count; if (rowIndex == maxVerts && pathClosed) { rows.Add(rows[0]); } else { float rowDelta = d / density; Vector3 edgeNorm = Vector3.Lerp(normals[i], normals[i + 1], rowDelta).normalized; Vector3 normOffset = edgeNorm * (1 - Mathf.Pow(2 * (rowDelta - .5f), 2)) * Mathf.Clamp(Vector3.SignedAngle(edgeNorm, normals[i], Vector3.up), -10, 10) * Mathf.Deg2Rad * edgeNormMult; Vector3 edgeVert = Vector3.Lerp(wallBase[i], wallBase[i + 1], rowDelta); rows.Add(GetWallRow(edgeVert, normOffset, edgeNorm, rowIndex / maxVerts, 1 / maxVerts)); if (topEdge != null) { rows[rowIndex].Add(CheckAddOutput(Utility.GetClosest(topEdge, rows[rowIndex][rows[rowIndex].Count - 1]), rowIndex / maxVerts, 1 / maxVerts, 1.1f, gridScale / Mathf.Abs(wallHeight * heightCurve.Evaluate(rowIndex / maxVerts)) * .5f)); } } if (rowIndex > 0) { if (rowIndex == maxVerts && endEdge != null && endEdge.Length > 0 && endEdge[0] == rows[rows.Count - 1][0]) { EditOutput(rows[rows.Count - 1][rows[rows.Count - 1].Count - 1], endEdge[endEdge.Length - 1]); rows[rows.Count - 1][rows[rows.Count - 1].Count - 1] = endEdge[endEdge.Length - 1]; } AddToMesh(mesh, rows[rowIndex - 1], rows[rowIndex], rowIndex, maxVerts); } } } if (endEdge != null && endEdge.Length > 0) { AddToMesh(mesh, rows[rows.Count - 1], new List <Vector3>(endEdge), (int)maxVerts + 1, maxVerts, true); } return(mesh); }