public static GeneratedTrack GenerateTrack(float length, float width, long seed) { float anglePeriod = param_AnglePeriod; float angleAmplitude = param_AngleAmplitude; float radiusPeriod = param_RadiusPeriod; float radiusAmplitude = param_RadiusAmplitude; float radiusOffset = param_RadiusOffset; // Segment Decider // // Decider works like this: // If noise returns < -1, the segment is a straight // If noise returns > 1, the segment is a turn // Else, it is a combination of both // float segDecMin = param_SegDecMin; float segDecMax = param_SegDecMax; float segDecPeriod = param_SegDecPeriod; float modePeriod = param_ModePeriod; perlinNoise = new PerlinNoise(seed); GeneratedTrack track = new GeneratedTrack(); track.Faulty = false; List <Circle> circles = new List <Circle>(); circles.Add(new Circle(new Vector2(0f, 150f), 250f, true)); circles.Add(new Circle(new Vector2(150f, -100f), 250f, true)); circles.Add(new Circle(new Vector2(-150f, -100f), 250f, true)); List <float> circleDirections = new List <float>(); for (int i = 0; i < circles.Count; i++) { int i2 = (i + 1) % circles.Count; Vector2 c1Toc2 = circles[i2].Midpoint - circles[i].Midpoint; Vector2 c1ToLeft = (new Vector2(-c1Toc2.y, c1Toc2.x)).normalized * circles[i].Radius; Vector2 c2ToLeft = (new Vector2(-c1Toc2.y, c1Toc2.x)).normalized * circles[i2].Radius; Vector2 c1Outs = circles[i].Midpoint + c1ToLeft; Vector2 c2Outs = circles[i2].Midpoint + c2ToLeft; Vector2 vec = c2Outs - c1Outs; float zAngle = Vector2.Angle(new Vector2(0f, 1f), vec); float xAngle = Vector2.Angle(new Vector2(1f, 0f), vec); float circleDirection = zAngle; if (xAngle > 90f) { circleDirection = 360f - zAngle; } circleDirection = circleDirection - 90f; if (circleDirection < 0f) { circleDirection = 360f - circleDirection; } circleDirections.Add(circleDirection); } int angleStep = 0; int radiusStep = 0; int segmentStep = 0; int circleIndex = 0; float currentAngle = 0f; float startRadius = perlinNoise.noise1(radiusStep * radiusPeriod) * radiusAmplitude + radiusOffset; Vector2 startPoint = new Vector2(Mathf.Sin((currentAngle * Mathf.PI) / 180f) * startRadius, Mathf.Cos((currentAngle * Mathf.PI) / 180f) * startRadius); while (true) { angleStep++; radiusStep++; segmentStep++; // Segment Decider is between [-1, 1] float segDec = perlinNoise.noise1(segmentStep * segDecPeriod) * ((Mathf.Abs(segDecMin) + Mathf.Abs(segDecMax)) / 2f); segDec = segDec + ((segDecMin + segDecMax) / 2f); segDec = segDec > 1f ? 1f : (segDec < -1f ? -1f : segDec); // Angle Delta between [0, angleAmplitude] float angleDelta = (perlinNoise.noise1(angleStep * anglePeriod) * 0.5f + 0.5f) * angleAmplitude; currentAngle += angleDelta; // Radius between [0, 2 * radiusAmplitude] float radius = perlinNoise.noise1(radiusStep * radiusPeriod) * radiusAmplitude + radiusOffset; // Mode is either PERFECT_PART_CIRCLES or BEZIER_SPLINES bool takeBezierSpline = false; if (generationMode == DiscreteGenerationMode.BEZIER_SPLINES) { takeBezierSpline = true; } else if (generationMode == DiscreteGenerationMode.PERFECT_PART_CIRCLES) { takeBezierSpline = false; } else { takeBezierSpline = perlinNoise.noise1(angleStep * modePeriod) >= 0f; } if (currentAngle >= circleDirections[circleIndex]) { circleIndex++; if (circleIndex >= circles.Count) { circleIndex = 0; } } //Debug.Log("TAKESPLINE: " + takeBezierSpline.ToString()); Vector2 point = new Vector2(Mathf.Sin((currentAngle * Mathf.PI) / 180f) * radius, Mathf.Cos((currentAngle * Mathf.PI) / 180f) * radius); point += circles[circleIndex].Midpoint; //Debug.Log("Iteration: " + angleStep); //Debug.Log("CurrentAngle: " + currentAngle); //Debug.Log("Radius: " + radius); //Debug.Log("SegDec: " + segDec); bool fixedEndpointDirection = false; float endpointDirection = Mathf.PI * 0.5f; float endpointWidth = width; if (currentAngle >= 360f) { fixedEndpointDirection = true; point = new Vector2(track.Elements[0].Position.x, track.Elements[0].Position.z); endpointDirection = track.Elements[0].Direction; endpointWidth = track.Elements[0].WidthStart; } Vector2 oldPoint; float oldDirection; if (track.Elements.Length == 0) { oldPoint = startPoint; oldDirection = Mathf.PI * 0.5f; } else { oldPoint = new Vector2(track.Elements[track.Elements.Length - 1].EndPosition.x, track.Elements[track.Elements.Length - 1].EndPosition.z); oldDirection = track.Elements[track.Elements.Length - 1].EndDirection; } if (fixedEndpointDirection == false) { // Completely a turn if (segDec >= 1f) { if (takeBezierSpline == false) { float[] radiusAndDegree = makeTurn(oldPoint, point, oldDirection); float circleRadius = radiusAndDegree[0]; float circleDegree = radiusAndDegree[1]; int splinesAmount = (int)(Mathf.Abs(circleDegree) / 90f) + 1; float degreeOneSpline = circleDegree / splinesAmount; float tanValue = 360f / degreeOneSpline; tanValue = Mathf.Abs((4f / 3f) * Mathf.Tan(Mathf.PI / (2f * tanValue)) * circleRadius); Vector2 prevSplinePoint = oldPoint; Debug.Log("Gonna do new"); for (int i = 0; i < splinesAmount; i++) { float tempStartDir = oldDirection + i * degreeOneSpline * (Mathf.PI / 180f); Vector2 midToPoint = (new Vector2(Mathf.Cos(tempStartDir) * Mathf.Sign(circleDegree), -Mathf.Sin(tempStartDir) * Mathf.Sign(circleDegree))).normalized * circleRadius; float tempEndDir = oldDirection + (i + 1) * degreeOneSpline * (Mathf.PI / 180f); Vector2 midToEndpoint = (new Vector2(Mathf.Cos(tempEndDir) * Mathf.Sign(circleDegree), -Mathf.Sin(tempEndDir) * Mathf.Sign(circleDegree))).normalized * circleRadius; Vector2 tempEndpoint = (prevSplinePoint + midToPoint) - midToEndpoint; GeneratedBezSpline spline = new GeneratedBezSpline(new Vector3(prevSplinePoint.x, 0f, prevSplinePoint.y), tempStartDir, new Vector3(tempEndpoint.x, 0f, tempEndpoint.y), tempEndDir, width, width, tanValue, tanValue); track.AddElement(spline); prevSplinePoint = tempEndpoint; //Debug.Log("Spline[" + i + "]"); } /*GeneratedTurn turn = new GeneratedTurn(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, circleRadius, circleDegree, width); * * Vector2 turnEndPoint = new Vector2(turn.EndPosition.x, turn.EndPosition.z); * if (Vector2.Distance(turnEndPoint, point) > 1f) * { * track.Faulty = true; * Debug.LogError("Too big distance"); * } * * track.AddElement(turn);*/ } else { /*float[] radiusAndDegree = makeTurn(oldPoint, point, oldDirection); * * float circleRadius = radiusAndDegree[0]; * float circleDegree = radiusAndDegree[1]; * * int splinesAmount = (int)(circleDegree / 90f) + 1; * * float degreeOneSpline = circleDegree / splinesAmount; * * float tanValue = 360f / degreeOneSpline; * tanValue = Mathf.Abs((4f / 3f) * Mathf.Tan(Mathf.PI / (2f * tanValue)) * circleRadius); * * Vector2 prevSplinePoint = oldPoint; * * Debug.Log("Gonna do new"); * * for (int i = 0; i < splinesAmount; i++) * { * float tempStartDir = oldDirection + i * degreeOneSpline * (Mathf.PI / 180f); * Vector2 midToPoint = (new Vector2(Mathf.Cos(tempStartDir), -Mathf.Sin(tempStartDir))).normalized * circleRadius; * * float tempEndDir = oldDirection + (i + 1) * degreeOneSpline * (Mathf.PI / 180f); * Vector2 midToEndpoint = (new Vector2(Mathf.Cos(tempEndDir), -Mathf.Sin(tempEndDir))).normalized * circleRadius; * * Vector2 tempEndpoint = (prevSplinePoint + midToPoint) - midToEndpoint; * * GeneratedBezSpline spline = new GeneratedBezSpline(new Vector3(prevSplinePoint.x, 0f, prevSplinePoint.y), tempStartDir, new Vector3(tempEndpoint.x, 0f, tempEndpoint.y), tempEndDir, width, width, tanValue, tanValue); * * track.AddElement(spline); * * prevSplinePoint = tempEndpoint; * * Debug.Log("Spline[" + i + "]"); * } */ Debug.Log("Did normal spline"); float[] radiusAndDegree = makeTurn(oldPoint, point, oldDirection); float circleRadius = radiusAndDegree[0]; float circleDegree = radiusAndDegree[1]; GeneratedTurn turn = new GeneratedTurn(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, circleRadius, circleDegree, width); float turnEndDirection = turn.EndDirection; float maxAngleToBeDoneBySpline = 90f; if (Mathf.Abs(turnEndDirection) > maxAngleToBeDoneBySpline * Mathf.PI / 180f) { turnEndDirection = Mathf.Sign(turnEndDirection) * (Mathf.PI * maxAngleToBeDoneBySpline / 180f); } float interDirection = (perlinNoise.noise1(angleStep * anglePeriod) * 0.5f + 0.5f) * (oldDirection - turnEndDirection) + turnEndDirection; GeneratedBezSpline turnSpline = new GeneratedBezSpline(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, new Vector3(point.x, 0f, point.y), interDirection, width, width); track.AddElement(turnSpline); } } // Part straight part turn else { if (false && takeBezierSpline == false) { float maxWidth = width; //TODO not only one width all the time float minRadius = maxWidth + 0.8f; float[] radiusAndDegree = makeTurn(oldPoint, point, oldDirection); float circleRadius = radiusAndDegree[0]; float circleDegree = radiusAndDegree[1]; float maxRadius = circleRadius; float circlePartRadius = (maxRadius - minRadius) * ((segDec + 1f) * 0.5f) + minRadius; Vector2 circleMiddle = Vector2.zero; float[] partcircleRadiusAndDegree = makeTurnFixedRadius(oldPoint, circlePartRadius, oldDirection, (circleDegree >= 0f), point); float partcircleDegree = partcircleRadiusAndDegree[0]; float partstraightLength = partcircleRadiusAndDegree[1]; GeneratedTurn turn = new GeneratedTurn(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, circlePartRadius, partcircleDegree, width); track.AddElement(turn); GeneratedStraight straight = new GeneratedStraight(turn.EndPosition, turn.EndDirection, partstraightLength, width); //straight.AddCurb(new GeneratedCurb(0.1f, 0.9f, true, true, true)); track.AddElement(straight); Vector2 bothEndPoint = new Vector2(straight.EndPosition.x, straight.EndPosition.z); if (Vector2.Distance(bothEndPoint, point) > 1f) { Debug.LogError("Too big distance"); track.Faulty = true; } } else { // Only straight if (false && segDec <= -1f && track.Elements.Length > 0 && track.Elements[track.Elements.Length - 1].GetType() == typeof(GeneratedBezSpline)) { float angleBetween = Vector2.Angle(new Vector2(0f, 1f), point - oldPoint); float angleRight = Vector2.Angle(new Vector2(1f, 0f), point - oldPoint); if (angleRight > 90f) { angleBetween = 360f - angleBetween; } float radianOldEndDirection = (angleBetween * Mathf.PI) / 180f; track.Elements[track.Elements.Length - 1].ForceEndDirection(radianOldEndDirection); GeneratedStraight straight = new GeneratedStraight(new Vector3(oldPoint.x, 0f, oldPoint.y), radianOldEndDirection, Vector2.Distance(oldPoint, point), width); track.AddElement(straight); } // Really part turn part straight else { float maxWidth = width; //TODO not only one width all the time float minRadius = maxWidth + 0.8f; float[] radiusAndDegree = makeTurn(oldPoint, point, oldDirection); float circleRadius = radiusAndDegree[0]; float circleDegree = radiusAndDegree[1]; float maxRadius = Mathf.Max(circleRadius * 0.4f, minRadius); float circlePartRadius = (maxRadius - minRadius) * ((segDec + 1f) * 0.5f) + minRadius; float[] partcircleRadiusAndDegree = makeTurnFixedRadius(oldPoint, circlePartRadius, oldDirection, (circleDegree >= 0f), point); float partcircleDegree = partcircleRadiusAndDegree[0]; float partstraightLength = partcircleRadiusAndDegree[1]; int splinesAmount = (int)(Mathf.Abs(partcircleDegree) / 90f) + 1; float degreeOneSpline = partcircleDegree / splinesAmount; float tanValue = 360f / degreeOneSpline; tanValue = Mathf.Abs((4f / 3f) * Mathf.Tan(Mathf.PI / (2f * tanValue)) * circlePartRadius); Vector2 prevSplinePoint = oldPoint; Debug.Log("Gonna do new"); for (int i = 0; i < splinesAmount; i++) { float tempStartDir = oldDirection + i * degreeOneSpline * (Mathf.PI / 180f); Vector2 midToPoint = (new Vector2(Mathf.Cos(tempStartDir) * Mathf.Sign(partcircleDegree), -Mathf.Sin(tempStartDir) * Mathf.Sign(partcircleDegree))).normalized * circlePartRadius; float tempEndDir = oldDirection + (i + 1) * degreeOneSpline * (Mathf.PI / 180f); Vector2 midToEndpoint = (new Vector2(Mathf.Cos(tempEndDir) * Mathf.Sign(partcircleDegree), -Mathf.Sin(tempEndDir) * Mathf.Sign(partcircleDegree))).normalized * circlePartRadius; Vector2 tempEndpoint = (prevSplinePoint + midToPoint) - midToEndpoint; GeneratedBezSpline spline = new GeneratedBezSpline(new Vector3(prevSplinePoint.x, 0f, prevSplinePoint.y), tempStartDir, new Vector3(tempEndpoint.x, 0f, tempEndpoint.y), tempEndDir, width, width, tanValue, tanValue); track.AddElement(spline); prevSplinePoint = tempEndpoint; //Debug.Log("Spline[" + i + "]"); } GeneratedStraight straight = new GeneratedStraight(track.Elements[track.Elements.Length - 1].EndPosition, track.Elements[track.Elements.Length - 1].EndDirection, Vector2.Distance(point, new Vector2(track.Elements[track.Elements.Length - 1].EndPosition.x, track.Elements[track.Elements.Length - 1].EndPosition.z)), width); //straight.AddCurb(new GeneratedCurb(0.1f, 0.9f, true, true, true)); track.AddElement(straight); Vector2 bothEndPoint = new Vector2(straight.EndPosition.x, straight.EndPosition.z); if (Vector2.Distance(bothEndPoint, point) > 1f) { track.Faulty = true; Debug.LogError("Too big distance"); } } } } } // Drive to a fixed endpoint else { // Two turns one straight if (false) { float[] angleStraightAndAngle = makeTwoTurnsOneStraight(oldPoint, point, oldDirection, endpointDirection, 1f, 0.5f, Mathf.Max(endpointWidth, width)); float circle1Radius = angleStraightAndAngle[0]; float circle1Degree = angleStraightAndAngle[1]; float straightLegnth = angleStraightAndAngle[2]; float circle2Radius = angleStraightAndAngle[3]; float circle2Degree = angleStraightAndAngle[4]; if (circle1Radius == 0f && circle1Degree == 0f && straightLegnth == 0f && circle2Degree == 0f && circle2Radius == 0f) { track.Faulty = true; } else { GeneratedTurn turn = new GeneratedTurn(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, circle1Radius, circle1Degree, width); track.AddElement(turn); GeneratedStraight straight = new GeneratedStraight(turn.EndPosition, turn.EndDirection, straightLegnth, width); track.AddElement(straight); GeneratedTurn turn2 = new GeneratedTurn(straight.EndPosition, straight.EndDirection, circle2Radius, circle2Degree, width); track.AddElement(turn2); } } // Do it with Beziers else { GeneratedBezSpline turnSpline = new GeneratedBezSpline(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, new Vector3(point.x, 0f, point.y), endpointDirection, width, width); track.AddElement(turnSpline); } } if (currentAngle >= 360f) { break; } } return(track); }
public CurvatureAnalyzer(GeneratedTrack track, int sampleRate) { curvatureValues = new float[sampleRate]; trackPartIndices = new float[sampleRate]; for (int i = 0; i < sampleRate; i++) { curvatureValues[i] = float.MaxValue; } float walkedDistance = 0f; for (int i = 0; i < track.Elements.Length; i++) { if (track.Elements[i].GetType() == typeof(GeneratedStraight)) { GeneratedStraight straight = (GeneratedStraight)track.Elements[i]; int startIndex = (int)((walkedDistance / track.TrackLength) * sampleRate); int endIndex = (int)(((walkedDistance + straight.Length) / track.TrackLength) * sampleRate); for (int j = startIndex; j < endIndex; j++) { curvatureValues[j] = 0f; trackPartIndices[j] = i + ((float)(j - startIndex)) / ((float)(endIndex - startIndex)); } walkedDistance += straight.Length; } else if (track.Elements[i].GetType() == typeof(GeneratedTurn)) { GeneratedTurn turn = (GeneratedTurn)track.Elements[i]; int startIndex = (int)((walkedDistance / track.TrackLength) * sampleRate); int endIndex = (int)(((walkedDistance + turn.Length) / track.TrackLength) * sampleRate); for (int j = startIndex; j < endIndex; j++) { curvatureValues[j] = (1f / turn.Radius) * Mathf.Sign(turn.Degree); } walkedDistance += turn.Length; } else if (track.Elements[i].GetType() == typeof(GeneratedBezSpline)) { GeneratedBezSpline spline = (GeneratedBezSpline)track.Elements[i]; int startIndex = (int)((walkedDistance / track.TrackLength) * sampleRate); int endIndex = (int)(((walkedDistance + spline.Length) / track.TrackLength) * sampleRate); for (int j = startIndex; j < endIndex; j++) { Vector3 tangent1 = spline.Spline.TangentAt(((((float)j) - startIndex + 0f)) / (endIndex - startIndex))[1] - spline.Spline.TangentAt(((((float)j) - startIndex + 0f)) / (endIndex - startIndex))[0]; Vector3 tangent2 = spline.Spline.TangentAt(((((float)j) - startIndex + 1f)) / (endIndex - startIndex))[1] - spline.Spline.TangentAt(((((float)j) - startIndex + 1f)) / (endIndex - startIndex))[0]; Vector2 pos1 = new Vector2(spline.Spline.At(((((float)j) - startIndex + 0f)) / (endIndex - startIndex)).x, spline.Spline.At(((((float)j) - startIndex + 0f)) / (endIndex - startIndex)).z); Vector2 pos2 = new Vector2(spline.Spline.At(((((float)j) - startIndex + 1f)) / (endIndex - startIndex)).x, spline.Spline.At(((((float)j) - startIndex + 1f)) / (endIndex - startIndex)).z); Vector2 dir1 = new Vector2(tangent1.z, -tangent1.x); Vector2 dir2 = new Vector2(tangent2.z, -tangent2.x); Ray2D ray1 = new Ray2D(pos1, dir1); Ray2D ray2 = new Ray2D(pos2, dir2); Ray2D straightRay = new Ray2D(pos1, tangent1); bool parallel; Vector2 intersect = Utils.Intersect2D(ray1, ray2, out parallel); if (parallel) { curvatureValues[j] = 0f; } else { float radius = (Vector2.Distance(intersect, pos1) + Vector2.Distance(intersect, pos2)) * 0.5f; curvatureValues[j] = (1f / radius) * (Utils.PointRightTo(straightRay, intersect) ? 1f : -1f); } trackPartIndices[j] = i + ((float)(j - startIndex)) / ((float)(endIndex - startIndex)); } walkedDistance += spline.Length; } } int notSet = 0; for (int i = 0; i < sampleRate; i++) { if (curvatureValues[i] == float.MaxValue) { notSet++; } } Debug.Log("NotSet: " + notSet); }
public DiscreteTrack(GeneratedTrack track, TerrainModifier terrainModifier) { List <Vector3> lefts = new List <Vector3>(); List <Vector3> rights = new List <Vector3>(); List <Vector3> leftsCurv = new List <Vector3>(); List <Vector3> rightsCurv = new List <Vector3>(); List <int> indcs = new List <int>(); int indcsCounter = 0; List <float> idealLineMeshList = new List <float>(); int idLineMeshCounter = 0; for (int i = 0; i < track.Elements.Length; i++) { if (track.Elements[i].GetType() == typeof(GeneratedStraight)) { Vector3 middle = track.Elements[i].Position; Vector3 toRight = (new Vector3(Mathf.Cos(track.Elements[i].Direction), 0f, -Mathf.Sin(track.Elements[i].Direction))).normalized; Vector3 toFront = (new Vector3(Mathf.Sin(track.Elements[i].Direction), 0f, Mathf.Cos(track.Elements[i].Direction))).normalized; lefts.Add(middle - toRight * track.Elements[i].WidthStart); rights.Add(middle + toRight * track.Elements[i].WidthStart); indcsCounter = -1; GeneratedStraight straight = (GeneratedStraight)track.Elements[i]; int segsAmount = (int)(straight.Length / straightSegmentingFactorIdealline); int segmentsAmountMesh = (int)(straight.Length / straightSegmentingFactorMesh); for (int j = 0; j < segmentsAmountMesh; j++) { //idealLineMesh[idLineMeshCounter] = 1f; idealLineMeshList.Add(1f); idLineMeshCounter++; } for (int j = 0; j < segsAmount; j++) { leftsCurv.Add(middle - toRight * track.Elements[i].WidthStart + toFront * straight.Length * (((float)j) / ((float)segsAmount))); rightsCurv.Add(middle + toRight * track.Elements[i].WidthStart + toFront * straight.Length * (((float)j) / segsAmount)); indcsCounter++; } indcs.Add(indcsCounter); } else if (track.Elements[i].GetType() == typeof(GeneratedTurn)) { GeneratedTurn turn = (GeneratedTurn)track.Elements[i]; bool rightTurn = turn.Degree >= 0f; Vector3 toRight = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(1f, 0f, 0f)); Vector3 toFront = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(0f, 0f, 1f)); Vector3 middlePoint = toRight * turn.Radius * (rightTurn ? 1f : -1f); int segmentsAmount = ((int)(Mathf.Abs(turn.Degree) / 30f)) + 1; for (int j = 0; j < segmentsAmount; j++) { Vector3 toRightTurned = (Quaternion.Euler(0f, (turn.Degree / ((float)segmentsAmount)) * j, 0f)) * toRight; Vector3 segmentPos = middlePoint + (toRightTurned * (rightTurn ? -1f : 1f) * turn.Radius); float currentWidth = (turn.WidthEnd - turn.WidthStart) * (float)((float)j / (float)segmentsAmount) + turn.WidthStart; lefts.Add(segmentPos + toRightTurned * currentWidth * -1f + turn.Position); rights.Add(segmentPos + toRightTurned * currentWidth + turn.Position); leftsCurv.Add(segmentPos + toRightTurned * currentWidth * -1f + turn.Position); rightsCurv.Add(segmentPos + toRightTurned * currentWidth + turn.Position); indcs.Add(0); } } else if (track.Elements[i].GetType() == typeof(GeneratedBezSpline)) { GeneratedBezSpline bezierSpline = (GeneratedBezSpline)track.Elements[i]; for (int j = 0; j < bezierSpline.RenderVertsLeft.Length - 1; j++) { if (j == 0) { //idealLineMesh[idLineMeshCounter] = 2f; idealLineMeshList.Add(2f); } else { //idealLineMesh[idLineMeshCounter] = 0f; idealLineMeshList.Add(0f); } idLineMeshCounter++; if (j % 3 == 0) { lefts.Add(bezierSpline.RenderVertsLeft[j]); rights.Add(bezierSpline.RenderVertsRight[j]); leftsCurv.Add(bezierSpline.RenderVertsLeft[j]); rightsCurv.Add(bezierSpline.RenderVertsRight[j]); indcs.Add(0); } } } } idealLineMesh = idealLineMeshList.ToArray(); leftPoints = lefts.ToArray(); rightPoints = rights.ToArray(); leftPointsCurv = leftsCurv.ToArray(); rightPointsCurv = rightsCurv.ToArray(); indcsFromPathIntoCurvature = indcs.ToArray(); shortestPathTrajectory = minimizePathTrajectory(); if (false) { for (int i = 0; i < leftPoints.Length; i++) { int i2 = (i + 1) % leftPoints.Length; Debug.DrawLine(leftPoints[i], leftPoints[i2], Color.white, 10000f); Debug.DrawLine(rightPoints[i], rightPoints[i2], Color.white, 10000f); Debug.DrawLine(leftPoints[i], rightPoints[i], Color.white, 10000f); Debug.DrawLine(shortestPathTrajectory[i] * (leftPoints[i] - rightPoints[i]) + rightPoints[i], shortestPathTrajectory[i2] * (leftPoints[i2] - rightPoints[i2]) + rightPoints[i2], Color.green, 10000f); } } minimumCurvatureTrajectory = minimizeCurvatureTrajectory(); if (false) { for (int i = 0; i < leftPointsCurv.Length; i++) { int i2 = (i + 1) % leftPointsCurv.Length; Debug.DrawLine(leftPointsCurv[i], leftPointsCurv[i2], Color.white, 10000f); Debug.DrawLine(rightPointsCurv[i], rightPointsCurv[i2], Color.white, 10000f); Debug.DrawLine(leftPointsCurv[i], rightPointsCurv[i], Color.white, 10000f); Debug.DrawLine(minimumCurvatureTrajectory[i] * (leftPointsCurv[i] - rightPointsCurv[i]) + rightPointsCurv[i], minimumCurvatureTrajectory[i2] * (leftPointsCurv[i2] - rightPointsCurv[i2]) + rightPointsCurv[i2], Color.green, 10000f); } } float epsilon = 0.1f; idealLine = applyEpsilon(shortestPathTrajectory, minimumCurvatureTrajectory, epsilon, indcsFromPathIntoCurvature); /*for (int i = 0; i < idealLine.Length; i++) * { * Debug.Log("IL [" + i + "]: " + idealLine[i]); * }*/ Debug.Log("cnter: " + idLineMeshCounter); transferToMeshIdealLine(track, idealLine, idealLineMesh); List <float> cpsBankAngles = new List <float>(); List <Vector3> cpsMinDistance = new List <Vector3>(); float minDistance = 15f; Vector3[] cps = new Vector3[idealLine.Length]; float[] cpsBank = new float[idealLine.Length]; cpsMinDistance.Add(idealLine[0] * (leftPointsCurv[0] - rightPointsCurv[0]) + rightPointsCurv[0]); for (int i = 1; i < idealLine.Length; i++) { Vector3 point = idealLine[i] * (leftPointsCurv[i] - rightPointsCurv[i]) + rightPointsCurv[i]; //cps[i] = point; if (Vector3.Distance(cpsMinDistance[cpsMinDistance.Count - 1], point) > minDistance) { cpsBankAngles.Add(Vector3.Angle(new Vector3(rightPointsCurv[i].x - leftPointsCurv[i].x, terrainModifier.GetTensorHeight(rightPointsCurv[i].x, rightPointsCurv[i].z) - terrainModifier.GetTensorHeight(leftPointsCurv[i].x, leftPointsCurv[i].z), rightPointsCurv[i].z - leftPointsCurv[i].z), new Vector3((rightPointsCurv[i] - leftPointsCurv[i]).x, 0f, (rightPointsCurv[i] - leftPointsCurv[i]).z)) * Mathf.Sign((rightPointsCurv[i] - leftPointsCurv[i]).y)); cpsMinDistance.Add(point); } } cps = cpsMinDistance.ToArray(); cpsBank = cpsBankAngles.ToArray(); for (int i = 0; i < cps.Length; i++) { cps[i] = new Vector3(cps[i].x, terrainModifier.GetTensorHeight(cps[i].x, cps[i].z), cps[i].z); } idealLineSpline = new ClosedSpline <Vector3>(cps); ClosedSpline <float> bankSpline = new ClosedSpline <float>(cpsBank); curvatureAnalyzer = new CurvatureAnalyzer(idealLineSpline, 300); speedAnalyzer = new SpeedAnalyzer(idealLineSpline, bankSpline, curvatureAnalyzer, 300); curvatureAnalyzerTrack = new CurvatureAnalyzer(track, 300); curvatureIdealLineAnalyzer = new CurvatureIdeallineAnalyzer(idealLineSpline); float startFinishLength = 500f; float partStartFinish = startFinishLength / track.TrackLength; int elementsStartFinishAmount = (int)(idealLineSpline.ControlPointsAmount * partStartFinish); elementsStartFinishAmount = (int)(partStartFinish * 300f); int startFinishIndex = minCurvatureForAmount(curvatureAnalyzerTrack.Curvature, elementsStartFinishAmount); float partpart = curvatureAnalyzerTrack.trackPartIndices[startFinishIndex]; //Vector3 beginStartFinishPoint = idealLineSpline.controlPoints[startFinishIndex]; Debug.Log("Start Finish point: " + partpart); int elementStartFinishBeginIndex = (int)partpart; Vector3 elementStartPos = track.Elements[elementStartFinishBeginIndex].Position; startFinishLineIndex = partpart; //Debug.Log("Start Finish point: " + elementStartPos); }
public void GenerateMesh() { // right Track Vertices List <Vector2> rT = new List <Vector2>(); // left Track Vertices List <Vector2> lT = new List <Vector2>(); // right Grass Vertices List <Vector2> rG = new List <Vector2>(); // right Grass Vertices List <Vector2> lG = new List <Vector2>(); /*if (Elements[0].GetType() == typeof(GeneratedStraight)) * { * GeneratedStraight straight = (GeneratedStraight)Elements[0]; * * Vector3 toRight = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(straight.WidthStart, 0f, 0f)); * * lT.Add(new Vector2((straight.Position - toRight).x, (straight.Position - toRight).z)); * rT.Add(new Vector2((straight.Position + toRight).x, (straight.Position + toRight).z)); * * } * else if (Elements[0].GetType() == typeof(GeneratedTurn)) * { * GeneratedTurn turn = (GeneratedTurn)Elements[0]; * * Vector3 toRight = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(turn.WidthStart, 0f, 0f)); * * lT.Add(new Vector2((turn.Position - toRight).x, (turn.Position - toRight).z)); * rT.Add(new Vector2((turn.Position + toRight).x, (turn.Position + toRight).z)); * } * else if (Elements[0].GetType() == typeof(GeneratedBezSpline)) * { * GeneratedBezSpline bezSpline = (GeneratedBezSpline)Elements[0]; * * lT.Add(new Vector2((bezSpline.RenderVertsLeft[0]).x, (bezSpline.RenderVertsLeft[0]).z)); * rT.Add(new Vector2((bezSpline.RenderVertsRight[0]).x, (bezSpline.RenderVertsRight[0]).z)); * }*/ for (int i = 0; i < Elements.Length; i++) { if (Elements[i].GetType() == typeof(GeneratedStraight)) { GeneratedStraight straight = (GeneratedStraight)Elements[i]; Vector3 toRight = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(straight.WidthEnd, 0f, 0f)); Vector3 toFront = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(0f, 0f, straight.Length)); int segmentsAmount = (int)(straight.Length / DiscreteTrack.straightSegmentingFactorMesh); for (int j = 1; j <= segmentsAmount; j++) { float s = ((float)j) / segmentsAmount; lT.Add(new Vector2((straight.Position + (toFront * s) - toRight).x, (straight.Position + (toFront * s) - toRight).z)); rT.Add(new Vector2((straight.Position + (toFront * s) + toRight).x, (straight.Position + (toFront * s) + toRight).z)); /* * -2 -1 * x-----x * |\ | * | \ | / \ * | \ | | Drive Direction * | \ | | * | \| * x-----x * -4 -3 * * */ } } else if (Elements[i].GetType() == typeof(GeneratedTurn)) { GeneratedTurn turn = (GeneratedTurn)Elements[i]; bool rightTurn = turn.Degree >= 0f; Vector3 toRight = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(1f, 0f, 0f)); Vector3 toFront = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(0f, 0f, 1f)); Vector3 middlePoint = toRight * turn.Radius * (rightTurn ? 1f : -1f); int segmentsAmount = ((int)(Mathf.Abs(turn.Degree) / maxTurnDegreeResolution)) + 1; for (int j = 1; j <= segmentsAmount; j++) { Vector3 toRightTurned = (Quaternion.Euler(0f, (turn.Degree / ((float)segmentsAmount)) * j, 0f)) * toRight; Vector3 segmentPos = middlePoint + (toRightTurned * (rightTurn ? -1f : 1f) * turn.Radius); float currentWidth = (turn.WidthEnd - turn.WidthStart) * (float)((float)j / (float)segmentsAmount) + turn.WidthStart; lT.Add(new Vector2((segmentPos + toRightTurned * currentWidth * -1f + turn.Position).x, (segmentPos + toRightTurned * currentWidth * -1f + turn.Position).z)); rT.Add(new Vector2((segmentPos + toRightTurned * currentWidth + turn.Position).x, (segmentPos + toRightTurned * currentWidth + turn.Position).z)); } } else if (Elements[i].GetType() == typeof(GeneratedBezSpline)) { GeneratedBezSpline bezierSpline = (GeneratedBezSpline)Elements[i]; for (int j = 1; j < bezierSpline.RenderVertsLeft.Length; j++) { lT.Add(new Vector2((bezierSpline.RenderVertsLeft[j]).x, (bezierSpline.RenderVertsLeft[j]).z)); rT.Add(new Vector2((bezierSpline.RenderVertsRight[j]).x, (bezierSpline.RenderVertsRight[j]).z)); } } } // Cutting of the overlapping segments List <RenderVertexShortcut> lSCs = calculateShortcuts(lT); List <RenderVertexShortcut> rSCs = calculateShortcuts(rT); for (int i = 0; i < lSCs.Count; i++) { RenderVertexShortcut rvs = lSCs[i]; for (int j = rvs.indexBefore + 1; j < (rvs.indexAfter < rvs.indexBefore ? lT.Count : rvs.indexAfter); j++) { lT[j] = rvs.intersectPoint; } for (int j = 0; j < (rvs.indexAfter < rvs.indexBefore ? rvs.indexAfter : 0); j++) { lT[j] = rvs.intersectPoint; } } for (int i = 0; i < rSCs.Count; i++) { RenderVertexShortcut rvs = rSCs[i]; for (int j = rvs.indexBefore + 1; j < (rvs.indexAfter < rvs.indexBefore ? rT.Count : rvs.indexAfter); j++) { rT[j] = rvs.intersectPoint; } for (int j = 0; j < (rvs.indexAfter < rvs.indexBefore ? rvs.indexAfter : 0); j++) { rT[j] = rvs.intersectPoint; } } float grassWidth = 8f; List <Vector2> lGFull = new List <Vector2>(); List <Vector2> rGFull = new List <Vector2>(); for (int i = 0; i < lT.Count; i++) { int i0 = (i - 1) < 0 ? lT.Count - 1 : i - 1; int i2 = (i + 1) % lT.Count; Vector2 tangentLeft = lT[i2] - lT[i0]; Vector2 newVLeft = (new Vector2(-tangentLeft.y, tangentLeft.x)).normalized * grassWidth + lT[i]; Vector2 tangentRight = rT[i2] - rT[i0]; Vector2 newVRight = (new Vector2(tangentRight.y, -tangentRight.x)).normalized * grassWidth + rT[i]; Vector2 vLeft = (lT[i] - rT[i]).normalized * grassWidth + lT[i]; Vector2 vRight = (rT[i] - lT[i]).normalized * grassWidth + rT[i]; lG.Add(newVLeft); rG.Add(newVRight); lGFull.Add(newVLeft); rGFull.Add(newVRight); } int grassPlanesNewStartIndex = -1; if (discreteTrack != null) { Vector2 startFinishPos = new Vector2(elements[(int)discreteTrack.startFinishLineIndex].Position.x, elements[(int)discreteTrack.startFinishLineIndex].Position.z); float minDistance = float.MaxValue; for (int i = 0; i < lGFull.Count; i++) { if (Vector2.Distance(lGFull[i], startFinishPos) < minDistance) { grassPlanesNewStartIndex = i; minDistance = Vector2.Distance(lGFull[i], startFinishPos); } } Debug.Log("Grass start index: " + grassPlanesNewStartIndex); List <Vector2> lGFullNew = new List <Vector2>(); List <Vector2> rGFullNew = new List <Vector2>(); List <Vector2> rTNew = new List <Vector2>(); List <Vector2> lTNew = new List <Vector2>(); List <Vector2> rGNew = new List <Vector2>(); List <Vector2> lGNew = new List <Vector2>(); for (int i = 0; i < lGFull.Count; i++) { lGFullNew.Add(lGFull[(i + grassPlanesNewStartIndex) % lGFull.Count]); lTNew.Add(lT[(i + grassPlanesNewStartIndex) % lGFull.Count]); lGNew.Add(lG[(i + grassPlanesNewStartIndex) % lGFull.Count]); rGFullNew.Add(rGFull[(i + grassPlanesNewStartIndex) % lGFull.Count]); rTNew.Add(rT[(i + grassPlanesNewStartIndex) % lGFull.Count]); rGNew.Add(rG[(i + grassPlanesNewStartIndex) % lGFull.Count]); } lGFull = lGFullNew; rGFull = rGFullNew; rT = rTNew; lT = lTNew; lG = lGNew; rG = rGNew; } // Curbs curbsGenerator = new CurbsGenerator(lT.ToArray(), rT.ToArray(), grassPlanesNewStartIndex); curbsGenerator.CalculateCurbs(discreteTrack); /*lGFull.Add(lGFull[0]); * rGFull.Add(rGFull[0]); * lG.Add(lG[0]); * rG.Add(rG[0]); * lT.Add(lT[0]); * rT.Add(rT[0]);*/ // Generating the grass zones on the sides List <GeneratedGrassPlane> grassplanes = new List <GeneratedGrassPlane>(); GeneratedPlaneElement[] leftGrassPlanes = generateGrassplanes(lGFull, lG, lT, 0, 0, 0); GeneratedPlaneElement[] rightGrassPlanes = generateGrassplanes(rGFull, rG, rT, 0, 0, 0); GeneratedPlaneElement[] combinedPlanes = new GeneratedPlaneElement[leftGrassPlanes.Length + rightGrassPlanes.Length]; for (int i = 0; i < leftGrassPlanes.Length; i++) { combinedPlanes[i] = leftGrassPlanes[i]; } for (int i = 0; i < rightGrassPlanes.Length; i++) { combinedPlanes[i + leftGrassPlanes.Length] = rightGrassPlanes[i]; } // Track vertices List <Vector3> vertices = new List <Vector3>(); List <int> triangles = new List <int>(); List <Vector2> uvs = new List <Vector2>(); float rightUvCounter = 0f; float leftUvCounter = 0f; vertices.Add(new Vector3(lT[0].x, 0f, lT[0].y)); uvs.Add(new Vector2(0f, leftUvCounter)); vertices.Add(new Vector3(rT[0].x, 0f, rT[0].y)); uvs.Add(new Vector2(1f, rightUvCounter)); for (int i = 1; i < lT.Count; i++) { vertices.Add(new Vector3(lT[i].x, 0f, lT[i].y)); leftUvCounter += (Vector3.Distance(vertices[vertices.Count - 3], vertices[vertices.Count - 1])) * (1f / 16f); uvs.Add(new Vector2(0f, leftUvCounter)); vertices.Add(new Vector3(rT[i].x, 0f, rT[i].y)); rightUvCounter += (Vector3.Distance(vertices[vertices.Count - 3], vertices[vertices.Count - 1])) * (1f / 16f); uvs.Add(new Vector2(1f, rightUvCounter)); triangles.Add(vertices.Count - 4); triangles.Add(vertices.Count - 2); triangles.Add(vertices.Count - 3); triangles.Add(vertices.Count - 2); triangles.Add(vertices.Count - 1); triangles.Add(vertices.Count - 3); } vertices.Add(new Vector3(lT[0].x, 0f, lT[0].y)); leftUvCounter += (Vector3.Distance(vertices[vertices.Count - 3], vertices[vertices.Count - 1])) * (1f / 16f); uvs.Add(new Vector2(0f, leftUvCounter)); vertices.Add(new Vector3(rT[0].x, 0f, rT[0].y)); rightUvCounter += (Vector3.Distance(vertices[vertices.Count - 3], vertices[vertices.Count - 1])) * (1f / 16f); uvs.Add(new Vector2(1f, rightUvCounter)); triangles.Add(vertices.Count - 4); triangles.Add(vertices.Count - 2); triangles.Add(vertices.Count - 3); triangles.Add(vertices.Count - 2); triangles.Add(vertices.Count - 1); triangles.Add(vertices.Count - 3); RenderVerticesTrack = vertices.ToArray(); RenderTrianglesTrack = triangles.ToArray(); RenderUVsTrack = uvs.ToArray(); // Grass vertices List <GeneratedGrassPlane> leftGrass = new List <GeneratedGrassPlane>(); for (int i = 0; i < leftGrassPlanes.Length; i++) { GeneratedGrassPlane plane = new GeneratedGrassPlane(); List <Vector3> verticesOutside = new List <Vector3>(); List <Vector3> directionsOutside = new List <Vector3>(); List <Vector3> verticesGrassLeft = new List <Vector3>(); List <int> trianglesGrassLeft = new List <int>(); List <Vector2> uvsGrassLeft = new List <Vector2>(); if (leftGrassPlanes[i].GetType() == typeof(GeneratedGrassPlane2D)) { GeneratedGrassPlane2D ggp2d = (GeneratedGrassPlane2D)leftGrassPlanes[i]; verticesOutside.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y)); verticesGrassLeft.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y)); uvsGrassLeft.Add(ggp2d.vertices[0]); verticesGrassLeft.Add(new Vector3(lT[ggp2d.trackStartIndex + 0].x, 0f, lT[ggp2d.trackStartIndex + 0].y)); verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.LeftWidths[ggp2d.trackStartIndex + 0])); uvsGrassLeft.Add(lT[ggp2d.trackStartIndex + 0]); directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized); for (int j = 1; j < ggp2d.vertices.Count; j++) { bool locked = false; for (int k = 0; k < ggp2d.jumpIndices.Count; k++) { if (j + ggp2d.trackStartIndex >= ggp2d.jumpIndices[k] && j + ggp2d.trackStartIndex < ggp2d.jumpIndices[k] + ggp2d.jumpWidths[k]) { locked = true; } } if (!locked) { verticesOutside.Add(new Vector3(ggp2d.vertices[j].x, 0f, ggp2d.vertices[j].y)); verticesGrassLeft.Add(new Vector3(ggp2d.vertices[j].x, 0f, ggp2d.vertices[j].y)); uvsGrassLeft.Add(ggp2d.vertices[j]); verticesGrassLeft.Add(new Vector3(lT[ggp2d.trackStartIndex + j].x, 0f, lT[ggp2d.trackStartIndex + j].y)); verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.LeftWidths[ggp2d.trackStartIndex + j])); uvsGrassLeft.Add(lT[ggp2d.trackStartIndex + j]); directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized); trianglesGrassLeft.Add(verticesGrassLeft.Count - 4); trianglesGrassLeft.Add(verticesGrassLeft.Count - 2); trianglesGrassLeft.Add(verticesGrassLeft.Count - 3); trianglesGrassLeft.Add(verticesGrassLeft.Count - 2); trianglesGrassLeft.Add(verticesGrassLeft.Count - 1); trianglesGrassLeft.Add(verticesGrassLeft.Count - 3); } } verticesOutside.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y)); verticesGrassLeft.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y)); uvsGrassLeft.Add(ggp2d.vertices[0]); verticesGrassLeft.Add(new Vector3(lT[ggp2d.trackStartIndex + 0].x, 0f, lT[ggp2d.trackStartIndex + 0].y)); verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.LeftWidths[ggp2d.trackStartIndex + 0])); uvsGrassLeft.Add(lT[ggp2d.trackStartIndex + 0]); directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized); trianglesGrassLeft.Add(verticesGrassLeft.Count - 4); trianglesGrassLeft.Add(verticesGrassLeft.Count - 2); trianglesGrassLeft.Add(verticesGrassLeft.Count - 3); trianglesGrassLeft.Add(verticesGrassLeft.Count - 2); trianglesGrassLeft.Add(verticesGrassLeft.Count - 1); trianglesGrassLeft.Add(verticesGrassLeft.Count - 3); plane.vertices = verticesGrassLeft.ToArray(); plane.triangles = trianglesGrassLeft.ToArray(); plane.uvs = uvsGrassLeft.ToArray(); plane.AllowBordercross = true; plane.verticesOutside = verticesOutside.ToArray(); plane.directionsOutside = directionsOutside.ToArray(); leftGrass.Add(plane); } else { GeneratedPlaneBetween gpb = (GeneratedPlaneBetween)leftGrassPlanes[i]; for (int j = 0; j < gpb.vertices.Count; j++) { verticesGrassLeft.Add(new Vector3(gpb.vertices[j].x, 0f, gpb.vertices[j].y)); uvsGrassLeft.Add(gpb.vertices[j]); } plane.vertices = verticesGrassLeft.ToArray(); plane.triangles = gpb.triangles.ToArray(); plane.uvs = uvsGrassLeft.ToArray(); leftGrass.Add(plane); } } for (int i = 0; i < rightGrassPlanes.Length; i++) { GeneratedGrassPlane plane = new GeneratedGrassPlane(); List <Vector3> verticesOutside = new List <Vector3>(); List <Vector3> directionsOutside = new List <Vector3>(); List <Vector3> verticesGrassLeft = new List <Vector3>(); List <int> trianglesGrassLeft = new List <int>(); List <Vector2> uvsGrassLeft = new List <Vector2>(); if (rightGrassPlanes[i].GetType() == typeof(GeneratedGrassPlane2D)) { GeneratedGrassPlane2D ggp2d = (GeneratedGrassPlane2D)rightGrassPlanes[i]; verticesOutside.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y)); verticesGrassLeft.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y)); uvsGrassLeft.Add(ggp2d.vertices[0]); verticesGrassLeft.Add(new Vector3(rT[ggp2d.trackStartIndex + 0].x, 0f, rT[ggp2d.trackStartIndex + 0].y)); verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.RightWidths[ggp2d.trackStartIndex + 0])); uvsGrassLeft.Add(rT[ggp2d.trackStartIndex + 0]); directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized); for (int j = 1; j < ggp2d.vertices.Count; j++) { bool locked = false; for (int k = 0; k < ggp2d.jumpIndices.Count; k++) { if (j + ggp2d.trackStartIndex >= ggp2d.jumpIndices[k] && j + ggp2d.trackStartIndex < ggp2d.jumpIndices[k] + ggp2d.jumpWidths[k]) { locked = true; } } if (!locked) { verticesOutside.Add(new Vector3(ggp2d.vertices[j].x, 0f, ggp2d.vertices[j].y)); verticesGrassLeft.Add(new Vector3(ggp2d.vertices[j].x, 0f, ggp2d.vertices[j].y)); uvsGrassLeft.Add(ggp2d.vertices[j]); verticesGrassLeft.Add(new Vector3(rT[ggp2d.trackStartIndex + j].x, 0f, rT[ggp2d.trackStartIndex + j].y)); verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.RightWidths[ggp2d.trackStartIndex + j])); uvsGrassLeft.Add(rT[ggp2d.trackStartIndex + j]); directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized); trianglesGrassLeft.Add(verticesGrassLeft.Count - 4); trianglesGrassLeft.Add(verticesGrassLeft.Count - 3); trianglesGrassLeft.Add(verticesGrassLeft.Count - 2); trianglesGrassLeft.Add(verticesGrassLeft.Count - 2); trianglesGrassLeft.Add(verticesGrassLeft.Count - 3); trianglesGrassLeft.Add(verticesGrassLeft.Count - 1); } } verticesOutside.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y)); verticesGrassLeft.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y)); uvsGrassLeft.Add(ggp2d.vertices[0]); verticesGrassLeft.Add(new Vector3(rT[ggp2d.trackStartIndex + 0].x, 0f, rT[ggp2d.trackStartIndex + 0].y)); verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.RightWidths[ggp2d.trackStartIndex + 0])); uvsGrassLeft.Add(rT[ggp2d.trackStartIndex + 0]); directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized); trianglesGrassLeft.Add(verticesGrassLeft.Count - 4); trianglesGrassLeft.Add(verticesGrassLeft.Count - 3); trianglesGrassLeft.Add(verticesGrassLeft.Count - 2); trianglesGrassLeft.Add(verticesGrassLeft.Count - 2); trianglesGrassLeft.Add(verticesGrassLeft.Count - 3); trianglesGrassLeft.Add(verticesGrassLeft.Count - 1); plane.vertices = verticesGrassLeft.ToArray(); plane.triangles = trianglesGrassLeft.ToArray(); plane.uvs = uvsGrassLeft.ToArray(); plane.AllowBordercross = true; plane.verticesOutside = verticesOutside.ToArray(); plane.directionsOutside = directionsOutside.ToArray(); leftGrass.Add(plane); } else { GeneratedPlaneBetween gpb = (GeneratedPlaneBetween)rightGrassPlanes[i]; for (int j = 0; j < gpb.vertices.Count; j++) { verticesGrassLeft.Add(new Vector3(gpb.vertices[j].x, 0f, gpb.vertices[j].y)); uvsGrassLeft.Add(gpb.vertices[j]); } for (int j = 0; j < gpb.triangles.Count; j += 3) { trianglesGrassLeft.Add(gpb.triangles[j]); trianglesGrassLeft.Add(gpb.triangles[j + 2]); trianglesGrassLeft.Add(gpb.triangles[j + 1]); } plane.vertices = verticesGrassLeft.ToArray(); plane.triangles = trianglesGrassLeft.ToArray(); plane.uvs = uvsGrassLeft.ToArray(); plane.AllowBordercross = false; leftGrass.Add(plane); } } GrassPlanes = leftGrass.ToArray(); }
public BorderGenerator(TerrainModifier terrainModifier, List <GeneratedElement> elements, float startFinishLineIndex) { leftWall = new List <Vector3>(); rightWall = new List <Vector3>(); List <Vector2> left = new List <Vector2>(); List <Vector2> right = new List <Vector2>(); int startIndex = (int)startFinishLineIndex; for (int i = 0; i < elements.Count; i++) { if (elements[(i + startIndex) % elements.Count].GetType() == typeof(GeneratedStraight)) { GeneratedStraight straight = (GeneratedStraight)elements[(i + startIndex) % elements.Count]; Vector3 toRight = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(straight.WidthEnd, 0f, 0f)); Vector3 toFront = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(0f, 0f, straight.Length)); int segmentsAmount = (int)(straight.Length / 4f); for (int j = 1; j <= segmentsAmount; j++) { float s = ((float)j) / segmentsAmount; left.Add(new Vector2((straight.Position + (toFront * s) - toRight - (toRight.normalized * fixDistance)).x, (straight.Position + (toFront * s) - toRight - (toRight.normalized * fixDistance)).z)); right.Add(new Vector2((straight.Position + (toFront * s) + toRight + (toRight.normalized * fixDistance)).x, (straight.Position + (toFront * s) + toRight + (toRight.normalized * fixDistance)).z)); } } else if (elements[(i + startIndex) % elements.Count].GetType() == typeof(GeneratedTurn)) { GeneratedTurn turn = (GeneratedTurn)elements[(i + startIndex) % elements.Count]; bool rightTurn = turn.Degree >= 0f; Vector3 toRight = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(1f, 0f, 0f)); Vector3 toFront = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(0f, 0f, 1f)); Vector3 middlePoint = toRight * turn.Radius * (rightTurn ? 1f : -1f); int segmentsAmount = ((int)(Mathf.Abs(turn.Degree) / maxTurnDegreeResolution)) + 1; for (int j = 1; j <= segmentsAmount; j++) { Vector3 toRightTurned = (Quaternion.Euler(0f, (turn.Degree / ((float)segmentsAmount)) * j, 0f)) * toRight; Vector3 segmentPos = middlePoint + (toRightTurned * (rightTurn ? -1f : 1f) * turn.Radius); float currentWidth = (turn.WidthEnd - turn.WidthStart) * (float)((float)j / (float)segmentsAmount) + turn.WidthStart; left.Add(new Vector2((segmentPos + toRightTurned * currentWidth * -1f + (toRightTurned.normalized * fixDistance * -1f) + turn.Position).x, (segmentPos + toRightTurned * currentWidth * -1f + (toRightTurned.normalized * fixDistance * -1f) + turn.Position).z)); right.Add(new Vector2((segmentPos + toRightTurned * currentWidth + (toRightTurned.normalized * fixDistance) + turn.Position).x, (segmentPos + toRightTurned * currentWidth + (toRightTurned.normalized * fixDistance) + turn.Position).z)); } } else if (elements[(i + startIndex) % elements.Count].GetType() == typeof(GeneratedBezSpline)) { GeneratedBezSpline bezierSpline = (GeneratedBezSpline)elements[(i + startIndex) % elements.Count]; for (int j = 1; j < bezierSpline.RenderVertsLeft.Length; j++) { Vector3 toRight = (bezierSpline.RenderVertsRight[j] - bezierSpline.RenderVertsLeft[j]).normalized; left.Add(new Vector2((bezierSpline.RenderVertsLeft[j] + (toRight * -fixDistance)).x, (bezierSpline.RenderVertsLeft[j] + (toRight * -fixDistance)).z)); right.Add(new Vector2((bezierSpline.RenderVertsRight[j] + (toRight * fixDistance)).x, (bezierSpline.RenderVertsRight[j] + (toRight * fixDistance)).z)); } } } bool[] leftIgnores = new bool[left.Count]; bool[] rightIgnores = new bool[right.Count]; for (int i = 0; i < leftIgnores.Length; i++) { leftIgnores[i] = false; } for (int i = 0; i < rightIgnores.Length; i++) { rightIgnores[i] = false; } for (int i = 0; i < left.Count; i++) { int i2 = (i + 1) % left.Count; Line lineToTest = new Line(left[i % left.Count], left[i2]); int jumpIndex = -1; for (int jT = 0 + 2; jT < left.Count - 40; jT++) { int j = (jT + i) % left.Count; int j2 = (j + 1) % left.Count; if (leftIgnores[j] == false) { Line other = new Line(left[j], left[j2]); Vector2 intersectPoint; if (lineToTest.Intersects(other, out intersectPoint)) { jumpIndex = (j < i ? j + left.Count : j); break; } } } leftWall.Add(new Vector3(left[i].x, terrainModifier.GetTensorHeight(left[i].x, left[i].y), left[i].y)); if (jumpIndex != -1) { for (int k = i; k < jumpIndex; k++) { leftIgnores[k % leftIgnores.Length] = true; } i = jumpIndex; leftWall.Add(new Vector3(left[i % left.Count].x, terrainModifier.GetTensorHeight(left[i % left.Count].x, left[i % left.Count].y), left[i % left.Count].y)); } } for (int i = 0; i < right.Count; i++) { int i2 = (i + 1) % right.Count; Line lineToTest = new Line(right[i], right[i2]); int jumpIndex = -1; for (int jT = 0 + 2; jT < right.Count - 40; jT++) { int j = (jT + i) % right.Count; int j2 = (j + 1) % right.Count; if (rightIgnores[j] == false) { Line other = new Line(right[j], right[j2]); Vector2 intersectPoint; if (lineToTest.Intersects(other, out intersectPoint)) { jumpIndex = (j < i ? j + right.Count : j); break; } } } rightWall.Add(new Vector3(right[i].x, terrainModifier.GetTensorHeight(right[i].x, right[i].y), right[i].y)); if (jumpIndex != -1) { for (int k = i; k < jumpIndex; k++) { rightIgnores[k % rightIgnores.Length] = true; } i = jumpIndex; rightWall.Add(new Vector3(right[i % right.Count].x, terrainModifier.GetTensorHeight(right[i % right.Count].x, right[i % right.Count].y), right[i % right.Count].y)); } } }
public override GeneratedElement Copy() { GeneratedTurn copy = new GeneratedTurn(position, direction, radius, degree, widthStart, widthEnd); return(copy); }