Ejemplo n.º 1
0
    /// <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);
        }
    }