/// <summary> /// Calculates the Kerb positions for the segments leading up to the controlpoint /// <para>Ascertains if its possible first so it never crashes</para> /// </summary> public static void CalcXSecs(int CtrlPtIdx, int RoadWidth, bool FrstHlf = true, bool SecndHlf = true) { BezierLine Bez = BezierLine.Instance; Road Rd = Road.Instance; //If this is Idx1 then calculate the last visible one if (CtrlPtIdx == 1 && Rd.IsCircular) { CtrlPtIdx = Bez.CtrlPts.Count - 2; } //if (CtrlPtIdx == Bez.CtrlPts.Count-1 && Rd.IsCircular) CtrlPtIdx = 1; //doesnt work if (CtrlPtIdx < 2) { return; } if (CtrlPtIdx > Bez.CtrlPts.Count - 2) { return; } int CP1XId = Bez.CtrlPts[CtrlPtIdx - 2].SegStartIdx; int CP2XId = Bez.CtrlPts[CtrlPtIdx - 1].SegStartIdx; int CP3XId = Bez.CtrlPts[CtrlPtIdx].SegStartIdx; int CP4XId = Bez.CtrlPts[CtrlPtIdx + 1].SegStartIdx; if (Bez.CtrlPts[CtrlPtIdx - 1].SegCount == 0) { CP2XId = CP3XId; } if (Bez.CtrlPts[CtrlPtIdx - 2].SegCount == 0) { CP1XId = CP2XId; } if (Rd.IsCircular && CP2XId == Rd.XSecs.Count) { CP2XId = Bez.CtrlPts[2].SegStartIdx; CP3XId = Bez.CtrlPts[2].SegStartIdx; CP4XId = Bez.CtrlPts[3].SegStartIdx; } //because of the overlap if (Rd.IsCircular && CP3XId == Rd.XSecs.Count) { CP3XId = Bez.CtrlPts[1].SegStartIdx; CP4XId = Bez.CtrlPts[2].SegStartIdx; } //because of the overlap if (Rd.IsCircular && CtrlPtIdx == 2) { CP1XId = Bez.CtrlPts[Rd.Sectns.Count - 2].SegStartIdx; } //if (Bez.CtrlPts[CtrlPtIdx + 1].SegCount == 0) CP4XId = CP3XId; XSec XSec1 = CalcXSecPerp(CP1XId, RoadWidth); XSec XSec2 = CalcXSecPerp(CP2XId, RoadWidth); XSec XSec3 = CalcXSecPerp(CP3XId, RoadWidth); XSec XSec4 = CalcXSecPerp(CP4XId, RoadWidth); Vector3 RKerb1; Vector3 RKerb2; Vector3 RKerb3; Vector3 RKerb4; Vector3 LKerb1; Vector3 LKerb2; Vector3 LKerb3; Vector3 LKerb4; RKerb1 = XSec1.KerbR; RKerb2 = XSec2.KerbR; RKerb3 = XSec3.KerbR; RKerb4 = XSec4.KerbR; LKerb1 = XSec1.KerbL; LKerb2 = XSec2.KerbL; LKerb3 = XSec3.KerbL; LKerb4 = XSec4.KerbL; //this worked on the flat road. Now we have to bank the road Vector3 _bankDirection; try { //This will fail at some point if you are moving a cone at the end - its OK tho _bankDirection = (Bez.PathPlusOne(CP1XId) - Bez.Path[CP1XId]).normalized * Bez.CtrlPts[CtrlPtIdx - 2].BankAngle; if (Bez.CtrlPts[CtrlPtIdx - 2].BankAngle < 0) { LKerb1 = VectGeom.RotatePointAroundPivot(LKerb1, Bez.Path[CP1XId], _bankDirection); } else { RKerb1 = VectGeom.RotatePointAroundPivot(RKerb1, Bez.Path[CP1XId], _bankDirection); } _bankDirection = (Bez.PathPlusOne(CP2XId) - Bez.Path[CP2XId]).normalized * Bez.CtrlPts[CtrlPtIdx - 1].BankAngle; if (Bez.CtrlPts[CtrlPtIdx - 1].BankAngle < 0) { LKerb2 = VectGeom.RotatePointAroundPivot(LKerb2, Bez.Path[CP2XId], _bankDirection); } else { RKerb2 = VectGeom.RotatePointAroundPivot(RKerb2, Bez.Path[CP2XId], _bankDirection); } _bankDirection = (Bez.PathPlusOne(CP3XId) - Bez.Path[CP3XId]).normalized * Bez.CtrlPts[CtrlPtIdx].BankAngle; if (Bez.CtrlPts[CtrlPtIdx].BankAngle < 0) { LKerb3 = VectGeom.RotatePointAroundPivot(LKerb3, Bez.Path[CP3XId], _bankDirection); } else { RKerb3 = VectGeom.RotatePointAroundPivot(RKerb3, Bez.Path[CP3XId], _bankDirection); } _bankDirection = (Bez.PathPlusOne(CP4XId) - Bez.Path[CP4XId]).normalized * Bez.CtrlPts[CtrlPtIdx + 1].BankAngle; if (Bez.CtrlPts[CtrlPtIdx + 1].BankAngle < 0) { LKerb4 = VectGeom.RotatePointAroundPivot(LKerb4, Bez.Path[CP4XId], _bankDirection); } else { RKerb4 = VectGeom.RotatePointAroundPivot(RKerb4, Bez.Path[CP4XId], _bankDirection); } } catch (System.Exception e) { Debug.Log(e.ToString()); } int NumXSecsToAdjust; //Catmull Rom up to the control pt //RIGHT KERB try { NumXSecsToAdjust = Bez.CtrlPts[CtrlPtIdx - 1].SegCount; } catch (System.Exception e) { NumXSecsToAdjust = 0; } int AdjustStartIdx = CP2XId; Vector3 a = RKerb1; Vector3 b = RKerb2; Vector3 c = RKerb3; Vector3 d = RKerb4; float t = 0.5f; //if (Vector3.Angle(c - b, d - c) > 135 || Vector3.Angle(b - a, c - b) > 135) t = 2.5f; for (int p = 0; p < NumXSecsToAdjust; p++) { float u = (float)p / NumXSecsToAdjust; //Coeffs for the catmullrom equation Vector3 c0 = b; Vector3 c1 = -t * a + t * c; Vector3 c2 = 2f * t * a + (t - 3f) * b + (3f - 2f * t) * c - t * d; Vector3 c3 = -t * a + (2f - t) * b + (t - 2f) * c + t * d; Vector3 temp = c0 + c1 * u + c2 * u * u + c3 * u * u * u; //Vector3 temp = .5f * ((-a + 3f * b - 3f * c + d) * (u * u * u) + (2f * a - 5f * b + 4f * c - d) * (u * u) + (-a + c) * u + 2f * b); Vector3 newKerb = temp; //PlaceMarker(temp); Rd.XSecs[AdjustStartIdx + p].KerbR = temp; } //Catmull Rom up to the control pt //LEFT KERB a = LKerb1; b = LKerb2; c = LKerb3; d = LKerb4; //if (Vector3.Angle(c - b, d - c) > 135 || Vector3.Angle(b - a, c - b) > 135) t = 2.5f; for (int p = 0; p < NumXSecsToAdjust; p++) { float u = (float)p / NumXSecsToAdjust; //Coeffs for the catmullrom equation Vector3 c0 = b; Vector3 c1 = -t * a + t * c; Vector3 c2 = 2f * t * a + (t - 3f) * b + (3f - 2f * t) * c - t * d; Vector3 c3 = -t * a + (2f - t) * b + (t - 2f) * c + t * d; Vector3 temp = c0 + c1 * u + c2 * u * u + c3 * u * u * u; //Vector3 temp = .5f * ((-a + 3f * b - 3f * c + d) * (u * u * u) + (2f * a - 5f * b + 4f * c - d) * (u * u) + (-a + c) * u + 2f * b); Vector3 newKerb = temp; //PlaceMarker(temp); Rd.XSecs[AdjustStartIdx + p].KerbL = temp; Rd.XSecs[AdjustStartIdx + p].TerrainL = (Rd.XSecs[AdjustStartIdx + p].KerbL - Bez.Path[AdjustStartIdx + p]) * 1.3f + Bez.Path[AdjustStartIdx + p]; Rd.XSecs[AdjustStartIdx + p].TerrainR = (Rd.XSecs[AdjustStartIdx + p].KerbR - Bez.Path[AdjustStartIdx + p]) * 1.3f + Bez.Path[AdjustStartIdx + p]; Rd.XSecs[AdjustStartIdx + p].MidPt = (Rd.XSecs[AdjustStartIdx + p].KerbL + Rd.XSecs[AdjustStartIdx + p].KerbR) / 2; Rd.XSecs[AdjustStartIdx + p].MidPt = new Vector3(Rd.XSecs[AdjustStartIdx + p].MidPt.x, Bez.Path[AdjustStartIdx + p].y, Rd.XSecs[AdjustStartIdx + p].MidPt.z); } }