예제 #1
0
    public void RemoveLastControlPoint()
    {
        int       IdxToRemove = CtrlPts.Count - 2;
        BezCtrlPt CPToRemove  = CtrlPts[IdxToRemove];
        BezCtrlPt PrevCP      = CtrlPts[IdxToRemove - 1];

        //This isnt quite right but it'll do
        //I hope it doesn't cause a memory leak
        //DO we have to remove the Section and Segments and the gameobjects?
        int PrevCtrlPtId = -1;
        int NxtCtrlPtId  = -1;

        try
        {
            PrevCtrlPtId = CPToRemove.CtrlPtId - 1;
            NxtCtrlPtId  = CPToRemove.CtrlPtId + 1;
        }
        catch (Exception e) { Debug.Log(e.Message); }
        //not needed ? //if(Road.Instance.IsCircular) Path.RemoveRange(Path.Count - 20, 20);
        Path.RemoveRange(PrevCP.SegStartIdx, PrevCP.SegCount);
        CtrlPts.Remove(CPToRemove);
        PrevCP.SegCount = 0;
        PrevCP.Select();
        SetCtrlPtIds();
        SetSegStartIds();
        DrawLine();
    }
예제 #2
0
    public BezierLine Decode()
    {
        BezierLine Bez = BezierLine.Instance;

        Bez.LineId = 0;
        Bez.Path.Clear();
        Bez.CtrlPts.Clear();
        if (Path != null)   //in case we are loading a blank track
        {
            foreach (BezCtrlPtSerial BCPS in CtrlPts)
            {
                BezCtrlPt BCP = BCPS.Decode();
                Bez.CtrlPts.Add(BCP);
            }


            foreach (Vector3Serial PS in Path)
            {
                Bez.Path.Add(PS.V3);
            }
        }
        else
        {
            Bez.Init();
        }                       //blank track - put in the 2 dummies
        return(Bez);
    }
예제 #3
0
 public void Encode(BezCtrlPt CtrlPt)
 {
     CtrlPtId    = CtrlPt.CtrlPtId;
     LineId      = CtrlPt.Line.LineId;
     Pos         = new Vector3Serial(CtrlPt.Pos);
     BankAngle   = CtrlPt.BankAngle;
     SegStartIdx = CtrlPt.SegStartIdx;
     SegCount    = CtrlPt.SegCount;
 }
예제 #4
0
    public void TakePlanViewScreenshot()
    {
        UnityEngine.Object o = Resources.Load("prefabs/ScreenshotCam");
        goPlanCam = (GameObject)GameObject.Instantiate(o);
        Camera PlanCam = goPlanCam.GetComponent <Camera>();

        PlanCam.orthographic = true;
        //find the major axis (two Ctrlpts c1 and c2 furthest apart)
        float     dist = 0;
        BezCtrlPt c1 = new BezCtrlPt(Bez, Vector3.zero), c2 = new BezCtrlPt(Bez, Vector3.zero);

        foreach (BezCtrlPt p1 in Bez.CtrlPts)
        {
            foreach (BezCtrlPt p2 in Bez.CtrlPts)
            {
                float thisdist = Mathf.Pow(p1.Pos.x - p2.Pos.x, 2) + Mathf.Pow(p1.Pos.z - p2.Pos.z, 2);
                if (thisdist > dist)
                {
                    dist = thisdist; c1 = p1; c2 = p2;
                }
            }
        }
        Vector3 c1Pos = new Vector3(c1.Pos.x, 500, c1.Pos.z);
        Vector3 c2Pos = new Vector3(c2.Pos.x, 500, c2.Pos.z);

        PlanCam.transform.position = (c1Pos + c2Pos) / 2;
        PlanCam.transform.LookAt(c1Pos);
        PlanCam.transform.Rotate(Vector3.up, 90);
        float _distFwd = 0, _distBwd = 0;

        foreach (BezCtrlPt p1 in Bez.CtrlPts)
        {
            Vector3 RelPos = PlanCam.transform.InverseTransformPoint(new Vector3(p1.Pos.x, 500, p1.Pos.z));
            if (RelPos.z > _distFwd)
            {
                _distFwd = RelPos.z;
            }
            if (RelPos.z < _distBwd)
            {
                _distBwd = RelPos.z;
            }
        }
        PlanCam.transform.Translate(0, 0, (_distFwd + _distBwd) / 2, Space.Self);
        PlanCam.transform.Rotate(Vector3.right, 90, Space.Self);
        PlanCam.orthographicSize = Mathf.Pow(dist, 0.5f) * (float)Screen.height / (float)Screen.width / 2 * 1.1f;
        //_canvas.SetActive(false);
        goPlanCam.GetComponent <ScreenshotCam>().goCanvas = _canvas;
        goPlanCam.GetComponent <ScreenshotCam>().Grab     = true;
        Bez.SetWidth(10);
        Rd.goRoad.SetActive(false);
        foreach (GameObject t in GameObject.FindGameObjectsWithTag("Terrain"))
        {
            t.GetComponent <Terrain>().enabled = false;
        }
        //Debug.Break();
    }
예제 #5
0
    /// <summary>
    /// Divides the Current Section in half
    /// </summary>
    public void InsertSection()
    {
        int        CurrIdx              = BezCtrlPt.Current.CtrlPtId;
        int        newSectnIdx          = CurrIdx + 1;
        iRoadSectn CurrSectn            = Rd.Sectns[CurrIdx];
        int        CurrSectnSegStartId  = BezCtrlPt.Current.SegStartIdx;
        int        CurrSectnSegCount    = BezCtrlPt.Current.SegCount;
        int        CurrSectnNewSegCount = CurrSectnSegCount / 2;
        int        NewSectnSegStartId   = CurrSectnSegStartId + CurrSectnNewSegCount;
        int        NewSectnSegCount     = CurrSectnSegCount - CurrSectnNewSegCount;
        int        NxtSectnStartId      = Bez.CtrlPts[newSectnIdx].SegStartIdx;

        //Insert Bezier Control Point
        Vector3   NewPos    = Bez.Path[NewSectnSegStartId];
        BezCtrlPt NewCtrlPt = new BezCtrlPt(Bez, NewPos);

        NewCtrlPt.BankAngle = BezCtrlPt.Current.BankAngle;
        Bez.CtrlPts.Insert(newSectnIdx, NewCtrlPt);
        Bez.SetCtrlPtIds();
        //We dont have to move the path points from the old CtrlPt to the new one
        BezCtrlPt.Current.SegCount = CurrSectnNewSegCount;
        NewCtrlPt.SegCount         = NewSectnSegCount;
        Bez.SetSegStartIds();
        NewCtrlPt.CreateRoadMarker();
        Bez.Interp(newSectnIdx - 1);
        Bez.Interp(newSectnIdx);
        Bez.Interp(newSectnIdx + 1);
        Bez.DrawLine();

        Bez.AlignAllRoadMarkers();
        //Insert Section
        iRoadSectn NewSectn = new RoadSectn();

        NewSectn.Chargeable = false;
        NewSectn.Idx        = newSectnIdx;
        NewSectn.LFenceType = CurrSectn.LFenceType;
        NewSectn.RFenceType = CurrSectn.RFenceType;
        NewSectn.SetMaterial(CurrSectn.Segments[0].roadMaterial);
        NewSectn.CreateGameObjects();
        NewSectn.name         = "RoadSection" + (newSectnIdx);
        NewSectn.goSectn.name = "RoadSection" + (newSectnIdx);
        Road.Instance.Sectns.Insert(newSectnIdx, NewSectn);    // Section1 comes after RoadMarker1

        Rd.OrganiseObjectsUsingBezierCtrlPtsAndPath();

        /*
         * XSecCalculator.CalcXSecs(newSectnIdx-1, RoadWidth);
         * XSecCalculator.CalcXSecs(newSectnIdx, RoadWidth);
         * XSecCalculator.CalcXSecs(newSectnIdx+1, RoadWidth);
         *
         * CurrSectn.CalcFenceVerts();
         * NewSectn.CalcFenceVerts();
         * BuildQueue.Enqueue(newSectnIdx-1);
         * BuildQueue.Enqueue(newSectnIdx);
         */
    }
예제 #6
0
    public BezCtrlPt Decode()
    {
        BezCtrlPt BCP = new BezCtrlPt(BezierLine.Instance, Pos.V3);     //!!!!!!!Bugbugbug bug -fixed I think

        BCP.BankAngle   = BankAngle;
        BCP.CtrlPtId    = CtrlPtId;
        BCP.SegStartIdx = SegStartIdx;
        BCP.SegCount    = SegCount;
        return(BCP);
    }
예제 #7
0
 /// <summary>
 /// This gets called on a new game. It doesn't get called when you load a saved game
 /// </summary>
 public void Init()
 {
     Path.Clear();
     CtrlPts.Clear();
     //Add 2 control points - this is the minimum to get it working
     for (int i = 0; i < 2; i++)
     {
         BezCtrlPt BCP = new BezCtrlPt(this, Vector3.zero);
         CtrlPts.Add(BCP);
     }
     BezCtrlPt.Current = CtrlPts[0];
     SetCtrlPtIds();
 }
예제 #8
0
    public void Select()
    {
        if (goRdMkr == null)
        {
            return;
        }
        RoadMarker RM = goRdMkr.gameObject.GetComponent <RoadMarker>();

        if (!RM.Selected)
        {
            RM.Select();
        }
        Current = this;
        RM      = null;
    }
예제 #9
0
    public void AddControlPoint(Vector3 Pt, float BankAngle, int segCount)
    {
        BezCtrlPt BCP = new BezCtrlPt(this, Pt);

        BCP.BankAngle = BankAngle;
        CtrlPts[CtrlPts.Count - 2].SegCount = segCount;     //set the SegCount of the previous CtrlPt
        CtrlPts.Insert(CtrlPts.Count - 1, BCP);

        SetCtrlPtIds();
        SetSegStartIds();
        CtrlPts[CtrlPts.Count - 1].Pos = Pt;        //cos the last control point is a dummy and is in the same place
        if (BCP.CtrlPtId == 1)
        {
            CtrlPts[0].Pos = Pt;                              //cos the first one is a dummy too
        }
        if (BCP.CtrlPtId > 1)
        {
            AddPathPoints(segCount);
        }
    }
예제 #10
0
    /// <summary>
    /// Inserts a control point just after the selected one
    /// </summary>
    public void InsertControlPoint(int idx)
    {
        Vector3   InsertPos  = Path[(idx - 1) * 20 + 10];
        BezCtrlPt InsertedCP = new BezCtrlPt(this, InsertPos);

        InsertPathPoints(idx);               //CtrlPt 3 is Path 40
        CtrlPts.Insert(idx + 1, InsertedCP); //this adds an element just before idx+1
        SetCtrlPtIds();
        InsertedCP.CreateRoadMarker();
        //Rename all the Roadmarkers after the inserted one
        for (int idxAdj = idx + 2; idxAdj < CtrlPts.Count; idxAdj++)
        {
            GameObject goRM = CtrlPts[idxAdj].goRdMkr;
            if (goRM != null)
            {
                RoadMarker RM = goRM.GetComponent <RoadMarker>();
                RM.name  = "RoadMarker" + idxAdj;
                RM.Index = idxAdj;
            }
        }
        //dunno why it ended up with the wrong parent
        CtrlPts[idx + 2].goRdMkr.transform.SetParent(Rd.Sectns[idx + 2].goSectn.transform);
    }
예제 #11
0
    private void ReindexSectns(int StartSectnID)
    {
        //Bez.Path
        List <Vector3> PrevPaths = Bez.Path.GetRange(0, Bez.CtrlPts[StartSectnID].SegStartIdx);

        Bez.Path.RemoveRange(0, Bez.CtrlPts[StartSectnID].SegStartIdx);
        Bez.Path.AddRange(PrevPaths);

        //BezCtrlPts
        //remove the extra cp at starts and the two extra at the end
        Bez.CtrlPts.RemoveAt(0);
        Bez.CtrlPts.RemoveAt(Bez.CtrlPts.Count - 1);
        Bez.CtrlPts.RemoveAt(Bez.CtrlPts.Count - 1);
        //Copy the bit before the StartIdx
        List <BezCtrlPt> Prevs = Bez.CtrlPts.Where(c => c.CtrlPtId < StartSectnID).ToList();

        //Paste it at the end
        Bez.CtrlPts.AddRange(Prevs);
        Bez.CtrlPts.RemoveRange(0, StartSectnID - 1);
        //Add the 3 extra CtrlPts
        BezCtrlPt p0 = new BezCtrlPt(Bez, Bez.CtrlPts.Last().Pos);

        Bez.CtrlPts.Insert(0, p0);
        BezCtrlPt p1 = new BezCtrlPt(Bez, Bez.CtrlPts[1].Pos);

        Bez.CtrlPts.Add(p1);
        BezCtrlPt p2 = new BezCtrlPt(Bez, Bez.CtrlPts[2].Pos);

        Bez.CtrlPts.Add(p2);

        Bez.CtrlPts[0].SegStartIdx = 0;
        Bez.SetCtrlPtIds();



        //Road Sections
        iRoadSectn LastSctn = Rd.Sectns.Last();

        Rd.Sectns.Remove(LastSctn);
        List <iRoadSectn> PrevSctns = Rd.Sectns.Where(s => s.Idx > 0 && s.Idx < StartSectnID).ToList();

        Rd.Sectns.AddRange(PrevSctns);
        Rd.Sectns.RemoveRange(1, StartSectnID - 1);
        Rd.Sectns.Add(LastSctn);
        Rd.SetSectionIds();
        for (int SectnID = 1; SectnID < Rd.Sectns.Count - 1; SectnID++)
        {
            Rd.Sectns[SectnID].goSectn.transform.SetSiblingIndex(SectnID);
        }

        //Rename RoadMarkers
        foreach (BezCtrlPt Ctl in Bez.CtrlPts)
        {
            if (Ctl.goRdMkr != null)
            {
                GameObject goRdMkr    = Ctl.goRdMkr;
                RoadMarker RoadMarker = goRdMkr.gameObject.GetComponent <RoadMarker>();
                RoadMarker.name  = "RoadMarker" + Ctl.CtrlPtId;
                RoadMarker.Index = Ctl.CtrlPtId;
                goRdMkr.transform.SetParent(Road.Instance.Sectns[Ctl.CtrlPtId].goSectn.transform);
            }
        }

        //Reindex Segments
        List <RoadSegment> PrevSegs = Rd.Segments.Where(s => s.SectnIdx < StartSectnID).ToList();
        //Rd.XSecs.Join(PrevSegs, x => x.Idx, i => i.Idx, (r) => new XSec);
        var px =
            (from x in Rd.XSecs
             join s in PrevSegs on
             x.Idx equals s.Idx
             select x);
        List <XSec> PrevXSecs = px.Cast <XSec>().ToList();

        Rd.Segments.AddRange(PrevSegs);
        Rd.Segments.RemoveRange(0, PrevSegs.Count);
        for (int i = 0; i < Rd.Segments.Count; i++)
        {
            Rd.Segments[i].Idx        = i;
            Rd.Segments[i].goSeg.name = "RoadSeg" + i;
        }
        foreach (iRoadSectn Sec in Rd.Sectns)
        {
            foreach (RoadSegment seg in Sec.Segments)
            {
                seg.SectnIdx = Sec.Idx;
            }
        }

        Bez.SetSegStartIds();

        //Reindex XSecs
        Rd.XSecs.AddRange(PrevXSecs);
        Rd.XSecs.RemoveRange(0, PrevXSecs.Count);
        for (int i = 0; i < Rd.XSecs.Count; i++)
        {
            Rd.XSecs[i].Idx = i;
        }
    }
예제 #12
0
    public Vector3 LimitSlope(Vector3 Pt, float MaxSlope)
    {
        if (CtrlPts.Count == 2)
        {
            return(Pt);                                     //Because the first click can be anywhere
        }
        BezCtrlPt PrevCtrlPt = CtrlPts[CtrlPts.Count - 2];
        Vector3   Pt1        = PrevCtrlPt.Pos;
        Vector3   Pt2        = Pt;
        float     HorizDist  = Vector2.Distance(new Vector2(Pt1.x, Pt1.z), new Vector2(Pt2.x, Pt2.z));

        //If point is too close move it further away
        if (HorizDist < 20)
        {
            Vector3 NewPt_3d = Pt1 + Vector3.Normalize(Pt2 - Pt1) * 20f;
            Pt2       = NewPt_3d;
            HorizDist = Vector2.Distance(new Vector2(Pt1.x, Pt1.z), new Vector2(Pt2.x, Pt2.z));
        }
        //if point is too high lower it
        float VertDist = Pt2.y - Pt1.y;
        float Slope    = 0;

        if (HorizDist > 0)
        {
            Slope = VertDist / HorizDist;
        }
        if (Slope > MaxSlope)
        {
            //Debug.Log("Lowering cos too steep");
            Slope = MaxSlope;
            float NewVertDist = Slope * HorizDist;
            Pt2.y = Pt1.y + NewVertDist;
        }
        //Dont allow the angle less than 30 degrees
        float angle = 180;

        if (CtrlPts.Count > 3)
        {
            angle = Angle(CtrlPts[CtrlPts.Count - 3].Pos, PrevCtrlPt.Pos, Pt2);
            if (Mathf.Abs(angle) < 45)
            {
                //Debug.Log("Widening angle cos its too acute");
                float RotAngle;
                if (angle > 0)
                {
                    RotAngle = 45;
                }
                else
                {
                    RotAngle = -45;
                }
                Quaternion Rot      = Quaternion.Euler(0, RotAngle - angle, 0);
                Vector3    NewPt_3d = VectGeom.RotateAroundPoint(Pt2, Pt1, Rot);
                Pt2   = NewPt_3d;
                angle = RotAngle;
            }
        }

        //if hairpins are too sharp and too close together, spread them out

        if (HorizDist * Mathf.Abs(angle) < 1500)
        {
            //Debug.Log("Moving CtrlPt away from hairpin");
            Vector3 NewPt_3d = Pt1 + Vector3.Normalize(Pt2 - Pt1) * 1500 / Mathf.Abs(angle);
            Pt2       = NewPt_3d;
            HorizDist = Vector2.Distance(new Vector2(Pt1.x, Pt1.z), new Vector2(Pt2.x, Pt2.z));
        }

        if (Slope > 0 && Mathf.Abs(angle) / Slope < 270)
        {
            //Debug.Log("Flattening steep hairpin");
            Slope = Mathf.Abs(angle) / 270;
            float NewVertDist = Slope * HorizDist;
            Pt2.y = Pt1.y + NewVertDist;
        }

        return(Pt2);
        //Debug.Log("Dist = " + HorizDist.ToString());
        //Debug.Log("Slope = " + Slope.ToString());
        //Debug.Log("Angle = " + angle.ToString());
        //Typical values
        //      Dist 10 - 30
        //      Slope < 0.3
    }