private void GenerateBridges(Vector3[] points, Vector3[] nextSegmentPoints, Vector3 previousPoint, Transform previousSegment) { if (generateSimpleBridge == true || generateCustomBridge == true) { float startExtraWidthLeft = bridgeSettings.extraWidth; float endExtraWidthLeft = bridgeSettings.extraWidth; float startExtraWidthRight = bridgeSettings.extraWidth; float endExtraWidthRight = bridgeSettings.extraWidth; for (int i = 0; i < extraMeshes.Count; i++) { if (extraMeshes[i].left == true) { startExtraWidthLeft += extraMeshes[i].startWidth; endExtraWidthLeft += extraMeshes[i].endWidth; } else { startExtraWidthRight += extraMeshes[i].startWidth; endExtraWidthRight += extraMeshes[i].endWidth; } } PrefabLineCreator customBridge = null; if (generateSimpleBridge == true) { BridgeGeneration.GenerateSimpleBridge(points, nextSegmentPoints, previousPoint, this, previousSegment, startExtraWidthLeft, endExtraWidthLeft, startExtraWidthRight, endExtraWidthRight, bridgeSettings.bridgeMaterials, transform.GetChild(0).GetChild(0).transform.position, transform.GetChild(0).GetChild(1).transform.position, transform.GetChild(0).GetChild(2).transform.position); } if (generateCustomBridge == true) { customBridge = BridgeGeneration.GenerateCustomBridge(this, startExtraWidthLeft + startRoadWidth, startExtraWidthRight + startRoadWidth, endExtraWidthLeft + endRoadWidth, endExtraWidthRight + endRoadWidth); } if (placePillars == true) { if (generateSimpleBridge == true) { BridgeGeneration.GeneratePillars(points, transform.GetChild(0).GetChild(0).transform.position, transform.GetChild(0).GetChild(1).transform.position, transform.GetChild(0).GetChild(2).transform.position, this, transform.Find("Bridge").gameObject, true, customBridge, startExtraWidthLeft, startExtraWidthRight, endExtraWidthLeft, endExtraWidthRight); } else if (generateCustomBridge == true) { BridgeGeneration.GeneratePillars(points, transform.GetChild(0).GetChild(0).transform.position, transform.GetChild(0).GetChild(1).transform.position, transform.GetChild(0).GetChild(2).transform.position, this, transform.Find("Custom Bridge").gameObject, false, customBridge, startExtraWidthLeft, startExtraWidthRight, endExtraWidthLeft, endExtraWidthRight); } } } }
private void GenerateMesh() { List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); List <Vector2> uvs = new List <Vector2>(); List <int> firstVertexIndexes = new List <int>(); List <Vector3> mainRoadsVertices = new List <Vector3>(); List <List <int> > mainRoadsTriangles = new List <List <int> >(); List <Vector2> mainRoadsUvs = new List <Vector2>(); List <float> lengths = new List <float>(); CreateMainMesh(ref vertices, ref triangles, ref uvs, ref firstVertexIndexes); float[] startWidths = new float[firstVertexIndexes.Count]; float[] endWidths = new float[firstVertexIndexes.Count]; float[] heights = new float[firstVertexIndexes.Count]; CreateExtraMeshes(firstVertexIndexes, vertices, ref startWidths, ref endWidths, ref heights); CreateMainRoadsMeshes(ref mainRoadsVertices, ref mainRoadsTriangles, ref mainRoadsUvs, ref vertices, ref uvs, ref lengths); SetupMesh(vertices, triangles, uvs, mainRoadsTriangles, lengths); for (int i = transform.childCount - 1; i >= 0; i--) { if (transform.GetChild(i).name == "Bridge") { DestroyImmediate(transform.GetChild(i).gameObject); break; } } if (generateBridge == true) { BridgeGeneration.GenerateSimpleBridgeIntersection(GetComponent <MeshFilter>().sharedMesh.vertices, this, bridgeSettings.bridgeMaterials, startWidths, endWidths, firstVertexIndexes.ToArray()); } CreateCurvePoints(); }
public void CreateRoadMesh(Vector3[] points, Vector3[] nextSegmentPoints, Vector3 previousPoint, Vector3[] previousVertices, float heightOffset, Transform segment, Transform previousSegment, int smoothnessAmount, RoadCreator roadCreator) { if (baseRoadMaterial == null) { baseRoadMaterial = Resources.Load("Materials/Low Poly/Roads/2 Lane Roads/2L Road") as Material; } if (bridgeMaterials == null || bridgeMaterials.Length == 0 || bridgeMaterials[0] == null) { bridgeMaterials = new Material[] { Resources.Load("Materials/Low Poly/Concrete") as Material }; } if (pillarPrefab == null || pillarPrefab.GetComponent <MeshFilter>() == null) { pillarPrefab = Resources.Load("Prefabs/Low Poly/Bridges/Oval Bridge Pillar") as GameObject; } for (int i = 0; i < extraMeshOpen.Count; i++) { if (extraMeshMaterial[i] == null) { extraMeshMaterial[i] = Resources.Load("Materials/Low Poly/Asphalt") as Material; } } if (segment.GetSiblingIndex() == 0) { SetGuidelines(points, nextSegmentPoints, true); } else { SetGuidelines(points, nextSegmentPoints, false); } GenerateMesh(points, nextSegmentPoints, previousPoint, previousVertices, heightOffset, segment, previousSegment, transform.GetChild(1).GetChild(0), "Road", baseRoadMaterial, overlayRoadMaterial, smoothnessAmount, roadCreator, roadPhysicsMaterial); for (int i = 0; i < extraMeshOpen.Count; i++) { float leftYOffset = extraMeshYOffset[i]; float xOffset = 0; float yOffset = heightOffset; if (i > 0) { bool foundLast = false; for (int j = i - 1; j > -1; j -= 1) { if (extraMeshLeft[j] == extraMeshLeft[i] && j != i) { if (foundLast == false) { leftYOffset = extraMeshYOffset[j]; foundLast = true; } xOffset += extraMeshWidth[j]; yOffset += extraMeshYOffset[j]; } } } float currentHeight = heightOffset; for (int j = i - 1; j > -1; j -= 1) { if (extraMeshLeft[j] == extraMeshLeft[i] && j != i) { currentHeight += extraMeshYOffset[j]; } } GenerateMesh(points, nextSegmentPoints, previousPoint, previousVertices, heightOffset, segment, previousSegment, transform.GetChild(1).GetChild(i + 1), "Extra Mesh", extraMeshMaterial[i], null, smoothnessAmount, roadCreator, extraMeshPhysicMaterial[i], xOffset, extraMeshWidth[i], currentHeight + extraMeshYOffset[i], currentHeight, extraMeshLeft[i]); } if (transform.childCount == 3) { DestroyImmediate(transform.GetChild(2).gameObject); } if (bridgeGenerator == BridgeGenerator.simple) { float extraWidthLeft = 0; float extraWidthRight = 0; for (int i = 0; i < extraMeshLeft.Count; i++) { if (extraMeshLeft[i] == true) { extraWidthLeft += extraMeshWidth[i]; } else { extraWidthRight += extraMeshWidth[i]; } } extraWidthLeft += extraWidth; extraWidthRight += extraWidth; BridgeGeneration.GenerateSimpleBridge(points, nextSegmentPoints, previousPoint, this, extraWidthLeft, extraWidthRight, bridgeMaterials); } }
public static void GenerateSimpleBridgeIntersection(Vector3[] inputVertices, Intersection intersection, Material[] materials, float[] startWidths, float[] endWidths, int[] startVertices) { List <Vector3> vertices = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <int> triangles = new List <int>(); int verticeIndex = 0; int currentSegment = 0; Vector3 lastVertexPosition = inputVertices[0]; float currentDistance = 0f; float[] totalDistances = new float[startWidths.Length]; GameObject bridge = new GameObject("Bridge"); for (int i = 0; i < inputVertices.Length; i += 2) { if (currentSegment < startVertices.Length - 1 && i > (startVertices[currentSegment + 1] - 2)) { currentSegment += 1; currentDistance = 0; lastVertexPosition = inputVertices[i]; } totalDistances[currentSegment] += Vector3.Distance(lastVertexPosition, inputVertices[i]); lastVertexPosition = inputVertices[i]; } lastVertexPosition = inputVertices[0]; currentSegment = 0; for (int i = 0; i < inputVertices.Length; i += 2) { if (currentSegment < startVertices.Length - 1 && i > (startVertices[currentSegment + 1] - 2)) { currentSegment += 1; currentDistance = 0; lastVertexPosition = inputVertices[i]; } Vector3 verticeDifference = inputVertices[i + 1] - inputVertices[i]; currentDistance += Vector3.Distance(lastVertexPosition, inputVertices[i]); float currentWidth = Mathf.Lerp(startWidths[currentSegment], endWidths[currentSegment], currentDistance / totalDistances[currentSegment]); // _| // _/ vertices.Add(inputVertices[i] - verticeDifference.normalized * (intersection.bridgeSettings.extraWidth + currentWidth)); vertices[verticeIndex] = new Vector3(vertices[verticeIndex].x, inputVertices[i].y - inputVertices[i].y, vertices[verticeIndex].z); vertices.Add(inputVertices[i] - verticeDifference.normalized * (intersection.bridgeSettings.extraWidth + currentWidth)); vertices[verticeIndex + 1] = new Vector3(vertices[verticeIndex + 1].x, inputVertices[i].y - intersection.bridgeSettings.yOffsetFirstStep - inputVertices[i].y, vertices[verticeIndex + 1].z); vertices.Add(inputVertices[i + 1] - verticeDifference * intersection.bridgeSettings.widthPercentageFirstStep - verticeDifference.normalized * (intersection.bridgeSettings.extraWidth + currentWidth)); vertices[verticeIndex + 2] = new Vector3(vertices[verticeIndex + 2].x, inputVertices[i].y - intersection.bridgeSettings.yOffsetFirstStep - inputVertices[i].y, vertices[verticeIndex + 2].z); vertices.Add(inputVertices[i + 1] - verticeDifference.normalized * (intersection.bridgeSettings.extraWidth + currentWidth) - verticeDifference * intersection.bridgeSettings.widthPercentageFirstStep * intersection.bridgeSettings.widthPercentageSecondStep); vertices[verticeIndex + 3] = new Vector3(vertices[verticeIndex + 3].x, inputVertices[i].y - intersection.bridgeSettings.yOffsetFirstStep - intersection.bridgeSettings.yOffsetSecondStep - inputVertices[i].y, vertices[verticeIndex + 3].z); vertices.Add(inputVertices[i + 1]); vertices[verticeIndex + 4] = new Vector3(vertices[verticeIndex + 4].x, inputVertices[i].y - intersection.bridgeSettings.yOffsetFirstStep - intersection.bridgeSettings.yOffsetSecondStep - inputVertices[i].y, vertices[verticeIndex + 4].z); vertices.Add(inputVertices[i + 1]); vertices[verticeIndex + 5] = new Vector3(vertices[verticeIndex + 5].x, inputVertices[i].y - inputVertices[i].y, vertices[verticeIndex + 5].z); uvs.Add(new Vector2(0, currentDistance / totalDistances[currentSegment])); uvs.Add(new Vector2(1, currentDistance / totalDistances[currentSegment])); uvs.Add(new Vector2(0, currentDistance / totalDistances[currentSegment])); uvs.Add(new Vector2(1, currentDistance / totalDistances[currentSegment])); uvs.Add(new Vector2(0, currentDistance / totalDistances[currentSegment])); uvs.Add(new Vector2(1, currentDistance / totalDistances[currentSegment])); if (i < inputVertices.Length) { if (i < inputVertices.Length - 2) { for (int j = 0; j < 4; j += 1) { triangles.Add(verticeIndex + 1 + j); triangles.Add(verticeIndex + 6 + j); triangles.Add(verticeIndex + j); triangles.Add(verticeIndex + 1 + j); triangles.Add(verticeIndex + 7 + j); triangles.Add(verticeIndex + 6 + j); } // Top cover triangles.Add(verticeIndex + 0); triangles.Add(verticeIndex + 6); triangles.Add(verticeIndex + 5); triangles.Add(verticeIndex + 6); triangles.Add(verticeIndex + 11); triangles.Add(verticeIndex + 5); } else { for (int j = 0; j < 4; j += 1) { triangles.Add(verticeIndex + 1 + j); triangles.Add(j); triangles.Add(verticeIndex + j); triangles.Add(verticeIndex + 1 + j); triangles.Add(j + 1); triangles.Add(j); } } } verticeIndex += 6; lastVertexPosition = inputVertices[i]; } if (intersection.placePillars == true) { CreatePillarIntersection(bridge.transform, intersection.pillarPrefab, intersection.transform.position - new Vector3(0, intersection.bridgeSettings.yOffsetFirstStep + intersection.bridgeSettings.yOffsetSecondStep, 0), intersection); } BridgeGeneration.CreateBridge(bridge, intersection.transform, vertices.ToArray(), triangles.ToArray(), uvs.ToArray(), null, materials, intersection.settings); }
public static GameObject GenerateSimpleBridge(Vector3[] points, Vector3[] nextPoints, Vector3 previousPoint, RoadSegment segment, Transform previousSegment, float startExtraWidthLeft, float endExtraWidthLeft, float startExtraWidthRight, float endExtraWidthRight, Material[] materials, Vector3 startPoint, Vector3 controlPoint, Vector3 endPoint) { List <Vector3> vertices = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <Vector2> extraUvs = new List <Vector2>(); List <int> triangles = new List <int>(); int verticeIndex = 0; float totalDistance = 0; float currentDistance = 0; GameObject bridge = new GameObject("Bridge Base"); for (int i = 1; i < points.Length; i++) { totalDistance += Vector3.Distance(points[i - 1], points[i]); } for (int i = 0; i < points.Length; i++) { Vector3 left = Misc.CalculateLeft(points, nextPoints, Misc.MaxVector3, i); if (i > 0) { currentDistance += Vector3.Distance(points[i - 1], points[i]); } float roadWidth = Mathf.Lerp(segment.startRoadWidth, segment.endRoadWidth, currentDistance / totalDistance); if (i == 0 && previousSegment != null) { roadWidth = previousSegment.GetComponent <RoadSegment>().endRoadWidth; } float roadWidthLeft = roadWidth + Mathf.Lerp(startExtraWidthLeft, endExtraWidthLeft, currentDistance / totalDistance); float roadWidthRight = roadWidth + Mathf.Lerp(startExtraWidthRight, endExtraWidthRight, currentDistance / totalDistance); float heightOffset = 0; if (i == 0 && previousPoint != Misc.MaxVector3) { heightOffset = previousPoint.y - points[i].y; } else if (i == points.Length - 1 && nextPoints != null && nextPoints.Length == 1) { heightOffset = nextPoints[0].y - points[i].y; } // |_ _| // \_/ vertices.Add((points[i] - left * roadWidthRight) - segment.transform.position); vertices[verticeIndex] = new Vector3(vertices[verticeIndex].x, points[i].y + heightOffset - segment.transform.position.y, vertices[verticeIndex].z); vertices.Add((points[i] - left * roadWidthRight) - segment.transform.position); vertices[verticeIndex + 1] = new Vector3(vertices[verticeIndex + 1].x, points[i].y - segment.bridgeSettings.yOffsetFirstStep + heightOffset - segment.transform.position.y, vertices[verticeIndex + 1].z); vertices.Add((points[i] - left * roadWidthRight * segment.bridgeSettings.widthPercentageFirstStep) - segment.transform.position); vertices[verticeIndex + 2] = new Vector3(vertices[verticeIndex + 2].x, points[i].y - segment.bridgeSettings.yOffsetFirstStep + heightOffset - segment.transform.position.y, vertices[verticeIndex + 2].z); vertices.Add((points[i] - left * roadWidthRight * segment.bridgeSettings.widthPercentageFirstStep * segment.bridgeSettings.widthPercentageSecondStep) - segment.transform.position); vertices[verticeIndex + 3] = new Vector3(vertices[verticeIndex + 3].x, points[i].y - segment.bridgeSettings.yOffsetFirstStep - segment.bridgeSettings.yOffsetSecondStep + heightOffset - segment.transform.position.y, vertices[verticeIndex + 3].z); vertices.Add((points[i] + left * roadWidthLeft * segment.bridgeSettings.widthPercentageFirstStep * segment.bridgeSettings.widthPercentageSecondStep) - segment.transform.position); vertices[verticeIndex + 4] = new Vector3(vertices[verticeIndex + 4].x, points[i].y - segment.bridgeSettings.yOffsetFirstStep - segment.bridgeSettings.yOffsetSecondStep + heightOffset - segment.transform.position.y, vertices[verticeIndex + 4].z); vertices.Add((points[i] + left * roadWidthLeft * segment.bridgeSettings.widthPercentageFirstStep) - segment.transform.position); vertices[verticeIndex + 5] = new Vector3(vertices[verticeIndex + 5].x, points[i].y - segment.bridgeSettings.yOffsetFirstStep + heightOffset - segment.transform.position.y, vertices[verticeIndex + 5].z); vertices.Add((points[i] + left * roadWidthLeft) - segment.transform.position); vertices[verticeIndex + 6] = new Vector3(vertices[verticeIndex + 6].x, points[i].y - segment.bridgeSettings.yOffsetFirstStep + heightOffset - segment.transform.position.y, vertices[verticeIndex + 6].z); vertices.Add((points[i] + left * roadWidthLeft) - segment.transform.position); vertices[verticeIndex + 7] = new Vector3(vertices[verticeIndex + 7].x, points[i].y - segment.transform.position.y + heightOffset, vertices[verticeIndex + 7].z); uvs.Add(new Vector2(0, currentDistance / totalDistance)); uvs.Add(new Vector2(1, currentDistance / totalDistance)); uvs.Add(new Vector2(0, currentDistance / totalDistance)); uvs.Add(new Vector2(1, currentDistance / totalDistance)); uvs.Add(new Vector2(0, currentDistance / totalDistance)); uvs.Add(new Vector2(1, currentDistance / totalDistance)); uvs.Add(new Vector2(0, currentDistance / totalDistance)); uvs.Add(new Vector2(1, currentDistance / totalDistance)); if (i < points.Length - 1) { for (int j = 0; j < 7; j += 1) { triangles.Add(verticeIndex + 1 + j); triangles.Add(verticeIndex + j); triangles.Add(verticeIndex + 9 + j); triangles.Add(verticeIndex + 0 + j); triangles.Add(verticeIndex + 8 + j); triangles.Add(verticeIndex + 9 + j); } triangles.Add(verticeIndex); triangles.Add(verticeIndex + 15); triangles.Add(verticeIndex + 8); triangles.Add(verticeIndex); triangles.Add(verticeIndex + 7); triangles.Add(verticeIndex + 15); if (i == points.Length - 2) { // Start cap triangles.Add(0); triangles.Add(1); triangles.Add(7); triangles.Add(1); triangles.Add(6); triangles.Add(7); triangles.Add(2); triangles.Add(3); triangles.Add(5); triangles.Add(3); triangles.Add(4); triangles.Add(5); for (int j = 0; j < 2; j++) { extraUvs.Add(new Vector2(1, 0)); extraUvs.Add(new Vector2(0, 0)); extraUvs.Add(new Vector2(1, 1)); extraUvs.Add(new Vector2(0, 0)); extraUvs.Add(new Vector2(0, 1)); extraUvs.Add(new Vector2(1, 1)); } // End cap triangles.Add(verticeIndex + 15); triangles.Add(verticeIndex + 9); triangles.Add(verticeIndex + 8); triangles.Add(verticeIndex + 15); triangles.Add(verticeIndex + 14); triangles.Add(verticeIndex + 9); triangles.Add(verticeIndex + 13); triangles.Add(verticeIndex + 11); triangles.Add(verticeIndex + 10); triangles.Add(verticeIndex + 13); triangles.Add(verticeIndex + 12); triangles.Add(verticeIndex + 11); for (int j = 0; j < 2; j++) { extraUvs.Add(new Vector2(1, 0)); extraUvs.Add(new Vector2(0, 1)); extraUvs.Add(new Vector2(1, 1)); extraUvs.Add(new Vector2(1, 0)); extraUvs.Add(new Vector2(0, 0)); extraUvs.Add(new Vector2(0, 1)); } } } verticeIndex += 8; } return(BridgeGeneration.CreateBridge(bridge, segment.transform, vertices.ToArray(), triangles.ToArray(), uvs.ToArray(), extraUvs.ToArray(), materials, segment.settings)); }
public static void AddRoadSegmentBridgeVertices(Intersection intersection, ref List <Vector3> bridgeVertices, ref List <int> bridgeTriangles, ref List <Vector2> bridgeUvs, Vector3 centerPoint, float leftWidth, float rightWidth, Vector3 left, float progress, float textureRepeations) { // |_ _| // \_/ bridgeVertices.Add(centerPoint + left * (intersection.bridgeSettings.extraWidth + leftWidth)); bridgeVertices.Add(centerPoint + left * (intersection.bridgeSettings.extraWidth + leftWidth) - new Vector3(0, intersection.bridgeSettings.yOffsetFirstStep, 0)); bridgeVertices.Add(centerPoint + left * (intersection.bridgeSettings.extraWidth + leftWidth * intersection.bridgeSettings.widthPercentageFirstStep) - new Vector3(0, intersection.bridgeSettings.yOffsetFirstStep, 0)); bridgeVertices.Add(centerPoint + left * (intersection.bridgeSettings.extraWidth + leftWidth * intersection.bridgeSettings.widthPercentageFirstStep * intersection.bridgeSettings.widthPercentageSecondStep) - new Vector3(0, intersection.bridgeSettings.yOffsetFirstStep + intersection.bridgeSettings.yOffsetSecondStep, 0)); bridgeVertices.Add(centerPoint - left * (intersection.bridgeSettings.extraWidth + rightWidth * intersection.bridgeSettings.widthPercentageFirstStep * intersection.bridgeSettings.widthPercentageSecondStep) - new Vector3(0, intersection.bridgeSettings.yOffsetFirstStep + intersection.bridgeSettings.yOffsetSecondStep, 0)); bridgeVertices.Add(centerPoint - left * (intersection.bridgeSettings.extraWidth + rightWidth * intersection.bridgeSettings.widthPercentageFirstStep) - new Vector3(0, intersection.bridgeSettings.yOffsetFirstStep, 0)); bridgeVertices.Add(centerPoint - left * (intersection.bridgeSettings.extraWidth + rightWidth) - new Vector3(0, intersection.bridgeSettings.yOffsetFirstStep, 0)); bridgeVertices.Add(centerPoint - left * (intersection.bridgeSettings.extraWidth + rightWidth)); bridgeUvs = BridgeGeneration.AddBridgeUvs(bridgeUvs, progress * textureRepeations); if (progress > 0) { for (int j = 0; j < 7; j++) { bridgeTriangles.Add(bridgeVertices.Count - 8 + j); bridgeTriangles.Add(bridgeVertices.Count - 16 + j); bridgeTriangles.Add(bridgeVertices.Count - 7 + j); bridgeTriangles.Add(bridgeVertices.Count - 7 + j); bridgeTriangles.Add(bridgeVertices.Count - 16 + j); bridgeTriangles.Add(bridgeVertices.Count - 15 + j); } // Top part bridgeTriangles.Add(bridgeVertices.Count - 8); bridgeTriangles.Add(bridgeVertices.Count - 1); bridgeTriangles.Add(bridgeVertices.Count - 9); bridgeTriangles.Add(bridgeVertices.Count - 16); bridgeTriangles.Add(bridgeVertices.Count - 8); bridgeTriangles.Add(bridgeVertices.Count - 9); // End cap if (progress == 1) { bridgeTriangles.Add(bridgeVertices.Count - 7); bridgeTriangles.Add(bridgeVertices.Count - 2); bridgeTriangles.Add(bridgeVertices.Count - 1); bridgeTriangles.Add(bridgeVertices.Count - 8); bridgeTriangles.Add(bridgeVertices.Count - 7); bridgeTriangles.Add(bridgeVertices.Count - 1); bridgeTriangles.Add(bridgeVertices.Count - 5); bridgeTriangles.Add(bridgeVertices.Count - 4); bridgeTriangles.Add(bridgeVertices.Count - 3); bridgeTriangles.Add(bridgeVertices.Count - 3); bridgeTriangles.Add(bridgeVertices.Count - 6); bridgeTriangles.Add(bridgeVertices.Count - 5); } } else { // Start cap bridgeTriangles.Add(bridgeVertices.Count - 7); bridgeTriangles.Add(bridgeVertices.Count - 1); bridgeTriangles.Add(bridgeVertices.Count - 2); bridgeTriangles.Add(bridgeVertices.Count - 8); bridgeTriangles.Add(bridgeVertices.Count - 1); bridgeTriangles.Add(bridgeVertices.Count - 7); bridgeTriangles.Add(bridgeVertices.Count - 5); bridgeTriangles.Add(bridgeVertices.Count - 3); bridgeTriangles.Add(bridgeVertices.Count - 4); bridgeTriangles.Add(bridgeVertices.Count - 3); bridgeTriangles.Add(bridgeVertices.Count - 5); bridgeTriangles.Add(bridgeVertices.Count - 6); } }
private void GenerateNormalMesh() { List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); List <Vector2> uvs = new List <Vector2>(); List <int> firstVertexIndexes = new List <int>(); float[] totalLengths = new float[connections.Count]; float[] exactLengths = new float[connections.Count]; int vertexIndex = 0; Vector3 lastVertexPosition = Misc.MaxVector3; for (int i = 0; i < connections.Count; i++) { Vector3 firstPoint = connections[i].leftPoint; Vector3 firstCenterPoint = connections[i].lastPoint; Vector3 nextPoint; Vector3 nextCenterPoint; totalLengths[i] = connections[i].length; firstVertexIndexes.Add(vertexIndex); if (i == connections.Count - 1) { nextPoint = connections[0].rightPoint; nextCenterPoint = connections[0].lastPoint; totalLengths[i] += connections[0].length; } else { nextPoint = connections[i + 1].rightPoint; nextCenterPoint = connections[i + 1].lastPoint; totalLengths[i] += connections[i + 1].length; } if (connections[i].curvePoint == null) { return; } float segments = totalLengths[i] * settings.FindProperty("resolution").floatValue * 5; segments = Mathf.Max(3, segments); float distancePerSegment = 1f / segments; for (float t = 0; t <= 1; t += 0.1f) { Vector3 pos = Misc.Lerp3(Vector3.zero, new Vector3(0.5f, 0.5f, 0.5f), Vector3.one, t); } for (float t = 0; t <= 1 + distancePerSegment; t += distancePerSegment) { float modifiedT = t; if (Mathf.Abs(0.5f - t) < distancePerSegment && t > 0.5f) { modifiedT = 0.5f; } if (t > 1) { modifiedT = 1; } vertices.Add(Misc.Lerp3CenterHeight(firstPoint, connections[i].curvePoint, nextPoint, modifiedT) + new Vector3(0, yOffset, 0) - transform.position); if (t > 0) { exactLengths[i] += Vector3.Distance(lastVertexPosition, vertices[vertices.Count - 1]); lastVertexPosition = vertices[vertices.Count - 1]; } else { lastVertexPosition = vertices[vertices.Count - 1]; } if (modifiedT < 0.5f) { Vector3 point = Vector3.Lerp(firstCenterPoint, transform.position, modifiedT * 2) - transform.position; point.y = Mathf.Lerp(firstPoint.y, nextPoint.y, modifiedT) - transform.position.y + yOffset; vertices.Add(point); } else { Vector3 point = Vector3.Lerp(transform.position, nextCenterPoint, 2 * (modifiedT - 0.5f)) - transform.position; point.y = Mathf.Lerp(firstPoint.y, nextPoint.y, modifiedT) - transform.position.y + yOffset; vertices.Add(point); } uvs.Add(new Vector2(0, modifiedT)); if (stretchTexture == true) { uvs.Add(new Vector2(1, modifiedT)); } else { uvs.Add(new Vector2(Vector3.Distance(vertices[vertices.Count - 1], vertices[vertices.Count - 2]), modifiedT)); } if (t < 1) { triangles = AddTriangles(triangles, vertexIndex); } vertexIndex += 2; } Mesh mesh = new Mesh(); mesh.vertices = vertices.ToArray(); mesh.triangles = triangles.ToArray(); mesh.uv = uvs.ToArray(); mesh.RecalculateNormals(); GetComponent <MeshFilter>().sharedMesh = mesh; GetComponent <MeshCollider>().sharedMesh = mesh; GetComponent <MeshCollider>().sharedMaterial = physicMaterial; if (overlayMaterial == null) { GetComponent <MeshRenderer>().sharedMaterials = new Material[] { baseMaterial }; } else { GetComponent <MeshRenderer>().sharedMaterials = new Material[] { baseMaterial, overlayMaterial }; } } float[] startWidths = new float[firstVertexIndexes.Count]; float[] endWidths = new float[firstVertexIndexes.Count]; float[] heights = new float[firstVertexIndexes.Count]; GenerateIntersectionExtraMeshes(firstVertexIndexes, vertices, exactLengths, totalLengths, ref startWidths, ref endWidths, ref heights); for (int i = transform.childCount - 1; i >= 0; i--) { if (transform.GetChild(i).name == "Bridge") { DestroyImmediate(transform.GetChild(i).gameObject); break; } } if (generateBridge == true) { BridgeGeneration.GenerateSimpleBridgeIntersection(GetComponent <MeshFilter>().sharedMesh.vertices, this, bridgeSettings.bridgeMaterials, startWidths, endWidths, firstVertexIndexes.ToArray()); } CreateCurvePoints(); }
public static void GenerateSimpleBridge(Vector3[] points, Vector3[] nextPoints, Vector3 previousPoint, RoadSegment segment, float extraWidthLeft, float extraWidthRight, Material[] materials) { Vector3[] vertices = new Vector3[points.Length * 8]; Vector2[] uvs = new Vector2[vertices.Length]; int numberTriangles = 4 * (points.Length - 1); int[] triangles = new int[numberTriangles * 24]; int verticeIndex = 0; int triangleIndex = 0; float totalDistance = 0; float currentDistance = 0; bool placedFirstPillar = false; float lastDistance = 0; GameObject bridge = new GameObject("Bridge"); for (int i = 1; i < points.Length; i++) { totalDistance += Vector3.Distance(points[i - 1], points[i]); } for (int i = 0; i < points.Length; i++) { Vector3 left = Misc.CalculateLeft(points, nextPoints, Misc.MaxVector3, i); if (i > 0) { currentDistance += Vector3.Distance(points[i - 1], points[i]); } float roadWidth = Mathf.Lerp(segment.startRoadWidth, segment.endRoadWidth, currentDistance / totalDistance); float roadWidthLeft = roadWidth + extraWidthLeft; float roadWidthRight = roadWidth + extraWidthRight; float heightOffset = 0; if (i == 0 && previousPoint != Misc.MaxVector3) { heightOffset = previousPoint.y - points[i].y; } else if (i == points.Length - 1 && nextPoints != null && nextPoints.Length == 1) { heightOffset = nextPoints[0].y - points[i].y; } // |_ _| // \_/ vertices[verticeIndex] = (points[i] - left * roadWidthLeft) - segment.transform.position; vertices[verticeIndex].y = points[i].y + heightOffset - segment.transform.position.y; vertices[verticeIndex + 1] = (points[i] - left * roadWidthLeft) - segment.transform.position; vertices[verticeIndex + 1].y = points[i].y - segment.yOffsetFirstStep + heightOffset - segment.transform.position.y; vertices[verticeIndex + 2] = (points[i] - left * roadWidthLeft * segment.widthPercentageFirstStep) - segment.transform.position; vertices[verticeIndex + 2].y = points[i].y - segment.yOffsetFirstStep + heightOffset - segment.transform.position.y; vertices[verticeIndex + 3] = (points[i] - left * roadWidthLeft * segment.widthPercentageFirstStep * segment.widthPercentageSecondStep) - segment.transform.position; vertices[verticeIndex + 3].y = points[i].y - segment.yOffsetFirstStep - segment.yOffsetSecondStep + heightOffset - segment.transform.position.y; vertices[verticeIndex + 4] = (points[i] + left * roadWidthRight * segment.widthPercentageFirstStep * segment.widthPercentageSecondStep) - segment.transform.position; vertices[verticeIndex + 4].y = points[i].y - segment.yOffsetFirstStep - segment.yOffsetSecondStep + heightOffset - segment.transform.position.y; vertices[verticeIndex + 5] = (points[i] + left * roadWidthRight * segment.widthPercentageFirstStep) - segment.transform.position; vertices[verticeIndex + 5].y = points[i].y - segment.yOffsetFirstStep + heightOffset - segment.transform.position.y; vertices[verticeIndex + 6] = (points[i] + left * roadWidthRight) - segment.transform.position; vertices[verticeIndex + 6].y = points[i].y - segment.yOffsetFirstStep + heightOffset - segment.transform.position.y; vertices[verticeIndex + 7] = (points[i] + left * roadWidthRight) - segment.transform.position; vertices[verticeIndex + 7].y = points[i].y - segment.transform.position.y + heightOffset; int uvY = 0; if (i % 2 == 0) { uvY = 1; } uvs[verticeIndex] = new Vector2(0, uvY); uvs[verticeIndex + 1] = new Vector2(1, uvY); uvs[verticeIndex + 2] = new Vector2(0, uvY); uvs[verticeIndex + 3] = new Vector2(1, uvY); uvs[verticeIndex + 4] = new Vector2(0, uvY); uvs[verticeIndex + 5] = new Vector2(1, uvY); uvs[verticeIndex + 6] = new Vector2(0, uvY); uvs[verticeIndex + 7] = new Vector2(1, uvY); if (i < points.Length - 1) { for (int j = 0; j < 7; j += 1) { triangles[triangleIndex + j * 6] = verticeIndex + 1 + j; triangles[triangleIndex + 1 + j * 6] = verticeIndex + j; triangles[triangleIndex + 2 + j * 6] = verticeIndex + 9 + j; triangles[triangleIndex + 3 + j * 6] = verticeIndex + 0 + j; triangles[triangleIndex + 4 + j * 6] = verticeIndex + 8 + j; triangles[triangleIndex + 5 + j * 6] = verticeIndex + 9 + j; } triangles[triangleIndex + 42] = verticeIndex + 0; triangles[triangleIndex + 43] = verticeIndex + 7; triangles[triangleIndex + 44] = verticeIndex + 8; triangles[triangleIndex + 45] = verticeIndex + 8; triangles[triangleIndex + 46] = verticeIndex + 7; triangles[triangleIndex + 47] = verticeIndex + 15; // Pillars if (placedFirstPillar == false && currentDistance >= segment.pillarPlacementOffset) { CreatePillar(bridge.transform, segment.pillarPrefab, points[i] - new Vector3(0, segment.yOffsetFirstStep + segment.yOffsetSecondStep, 0), segment, points[i + 1] - points[i]); placedFirstPillar = true; lastDistance = currentDistance; } else if (placedFirstPillar == true && (currentDistance - lastDistance) > segment.pillarGap) { CreatePillar(bridge.transform, segment.pillarPrefab, points[i] - new Vector3(0, segment.yOffsetFirstStep + segment.yOffsetSecondStep, 0), segment, points[i + 1] - points[i]); lastDistance = currentDistance; } } verticeIndex += 8; triangleIndex += 54; } BridgeGeneration.CreateBridge(bridge, segment.transform, vertices, triangles, uvs, materials); }
public static void GenerateSimpleBridgeIntersection(Vector3[] inputVertices, Intersection intersection, Material[] materials) { Vector3[] vertices = new Vector3[inputVertices.Length * 3]; Vector2[] uvs = new Vector2[vertices.Length]; int[] triangles = new int[inputVertices.Length * 30]; int verticeIndex = 0; int triangleIndex = 0; GameObject bridge = new GameObject("Bridge"); for (int i = 0; i < inputVertices.Length; i += 2) { Vector3 verticeDifference = inputVertices[i + 1] - inputVertices[i]; // |_ _| // \_/ vertices[verticeIndex] = inputVertices[i] - verticeDifference.normalized * intersection.extraWidth; vertices[verticeIndex].y = inputVertices[i].y - inputVertices[i].y; vertices[verticeIndex + 1] = inputVertices[i] - verticeDifference.normalized * intersection.extraWidth; vertices[verticeIndex + 1].y = inputVertices[i].y - intersection.yOffsetFirstStep - inputVertices[i].y; vertices[verticeIndex + 2] = inputVertices[i + 1] - verticeDifference * intersection.widthPercentageFirstStep - verticeDifference.normalized * intersection.extraWidth; vertices[verticeIndex + 2].y = inputVertices[i].y - intersection.yOffsetFirstStep - inputVertices[i].y; vertices[verticeIndex + 3] = inputVertices[i + 1] - verticeDifference.normalized * intersection.extraWidth - verticeDifference * intersection.widthPercentageFirstStep * intersection.widthPercentageSecondStep; vertices[verticeIndex + 3].y = inputVertices[i].y - intersection.yOffsetFirstStep - intersection.yOffsetSecondStep - inputVertices[i].y; vertices[verticeIndex + 4] = inputVertices[i + 1]; vertices[verticeIndex + 4].y = inputVertices[i].y - intersection.yOffsetFirstStep - intersection.yOffsetSecondStep - inputVertices[i].y; vertices[verticeIndex + 5] = inputVertices[i + 1]; vertices[verticeIndex + 5].y = inputVertices[i].y - inputVertices[i].y; int uvY = 0; if (i % 4 == 0) { uvY = 1; } uvs[verticeIndex] = new Vector2(0, uvY); uvs[verticeIndex + 1] = new Vector2(1, uvY); uvs[verticeIndex + 2] = new Vector2(0, uvY); uvs[verticeIndex + 3] = new Vector2(1, uvY); uvs[verticeIndex + 4] = new Vector2(0, uvY); uvs[verticeIndex + 5] = new Vector2(1, uvY); if (i < inputVertices.Length - 2) { for (int j = 0; j < 4; j += 1) { triangles[triangleIndex + j * 6] = verticeIndex + 1 + j; triangles[triangleIndex + 1 + j * 6] = verticeIndex + 6 + j; triangles[triangleIndex + 2 + j * 6] = verticeIndex + j; triangles[triangleIndex + 3 + j * 6] = verticeIndex + 1 + j; triangles[triangleIndex + 4 + j * 6] = verticeIndex + 7 + j; triangles[triangleIndex + 5 + j * 6] = verticeIndex + 6 + j; } triangles[triangleIndex + 24] = verticeIndex + 0; triangles[triangleIndex + 25] = verticeIndex + 6; triangles[triangleIndex + 26] = verticeIndex + 5; triangles[triangleIndex + 27] = verticeIndex + 6; triangles[triangleIndex + 28] = verticeIndex + 11; triangles[triangleIndex + 29] = verticeIndex + 5; } verticeIndex += 6; triangleIndex += 30; } CreatePillarIntersection(bridge.transform, intersection.pillarPrefab, intersection.transform.position - new Vector3(0, intersection.yOffsetFirstStep + intersection.yOffsetSecondStep, 0), intersection); BridgeGeneration.CreateBridge(bridge, intersection.transform, vertices, triangles, uvs, materials); }
public void CreateMesh(bool fromRoad = false) { if (globalSettings == null) { globalSettings = GameObject.FindObjectOfType <GlobalSettings>(); } for (int i = 0; i < connections.Count; i++) { if (connections[i].road == null) { connections.RemoveAt(i); } } if (connections.Count < 2) { RoadCreator[] roads = GameObject.FindObjectsOfType <RoadCreator>(); for (int i = 0; i < roads.Length; i++) { if (roads[i].startIntersection == this) { roads[i].startIntersection = null; break; } else if (roads[i].endIntersection == this) { roads[i].endIntersection = this; break; } } GameObject.DestroyImmediate(gameObject); } else { if (baseMaterial == null) { baseMaterial = Resources.Load("Materials/Low Poly/Intersections/Asphalt Intersection") as Material; } if (bridgeMaterials == null || bridgeMaterials.Length == 0 || bridgeMaterials[0] == null) { bridgeMaterials = new Material[] { Resources.Load("Materials/Low Poly/Concrete") as Material }; } if (pillarPrefab == null || pillarPrefab.GetComponent <MeshFilter>() == null) { pillarPrefab = Resources.Load("Prefabs/Low Poly/Bridges/Cylinder Bridge Pillar") as GameObject; } List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); List <Vector2> uvs = new List <Vector2>(); int vertexIndex = 0; for (int i = 0; i < connections.Count; i++) { Vector3 firstPoint = connections[i].leftPoint.ToNormalVector3(); Vector3 firstCenterPoint = connections[i].lastPoint.ToNormalVector3(); Vector3 nextPoint; Vector3 nextCenterPoint; float totalLength = connections[i].length; if (i == connections.Count - 1) { nextPoint = connections[0].rightPoint.ToNormalVector3(); nextCenterPoint = connections[0].lastPoint.ToNormalVector3(); totalLength += connections[0].length; } else { nextPoint = connections[i + 1].rightPoint.ToNormalVector3(); nextCenterPoint = connections[i + 1].lastPoint.ToNormalVector3(); totalLength += connections[i + 1].length; } if (connections[i].curvePoint == null) { return; } float segments = totalLength * globalSettings.resolution * 5; segments = Mathf.Max(3, segments); float distancePerSegment = 1f / segments; for (float t = 0; t <= 1 + distancePerSegment; t += distancePerSegment) { float modifiedT = t; if (Mathf.Abs(0.5f - t) < distancePerSegment) { modifiedT = 0.5f; } if (modifiedT > 1) { modifiedT = 1; } vertices.Add(Misc.Lerp3(firstPoint, connections[i].curvePoint.ToNormalVector3(), nextPoint, modifiedT) + new Vector3(0, yOffset, 0) - transform.position); if (modifiedT < 0.5f) { Vector3 point = Vector3.Lerp(firstCenterPoint, transform.position, modifiedT * 2) + new Vector3(0, yOffset, 0) - transform.position; point.y = Mathf.Lerp(firstPoint.y, nextPoint.y, modifiedT) - transform.position.y + yOffset; vertices.Add(point); } else { Vector3 point = Vector3.Lerp(transform.position, nextCenterPoint, 2 * (modifiedT - 0.5f)) + new Vector3(0, yOffset, 0) - transform.position; point.y = Mathf.Lerp(firstPoint.y, nextPoint.y, modifiedT) - transform.position.y + yOffset; vertices.Add(point); } uvs.Add(new Vector2(0, modifiedT)); if (stretchTexture == true) { uvs.Add(new Vector2(1, modifiedT)); } else { uvs.Add(new Vector2(Vector3.Distance(vertices[vertices.Count - 1], vertices[vertices.Count - 2]), modifiedT)); } if (t < 1) { triangles = AddTriangles(triangles, vertexIndex); } vertexIndex += 2; } Mesh mesh = new Mesh(); mesh.vertices = vertices.ToArray(); mesh.triangles = triangles.ToArray(); mesh.uv = uvs.ToArray(); GetComponent <MeshFilter>().sharedMesh = mesh; GetComponent <MeshCollider>().sharedMesh = mesh; GetComponent <MeshCollider>().sharedMaterial = physicMaterial; if (overlayMaterial == null) { GetComponent <MeshRenderer>().sharedMaterials = new Material[] { baseMaterial }; } else { GetComponent <MeshRenderer>().sharedMaterials = new Material[] { baseMaterial, overlayMaterial }; } } for (int i = transform.childCount - 1; i >= 0; i--) { if (transform.GetChild(i).name == "Bridge") { DestroyImmediate(transform.GetChild(i).gameObject); break; } } if (bridgeGenerator == RoadSegment.BridgeGenerator.simple) { BridgeGeneration.GenerateSimpleBridgeIntersection(GetComponent <MeshFilter>().sharedMesh.vertices, this, bridgeMaterials); } CreateCurvePoints(); } if (fromRoad == false) { for (int i = 0; i < connections.Count; i++) { connections[i].road.transform.parent.parent.parent.parent.GetComponent <RoadCreator>().CreateMesh(true); } } }