/// <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); */ }
public void DeleteLastSectn() { //Actually we delete the penultimate section because the last section is empty if (Sectns.Count < 2) { return; } int LastSectnId = Sectns.Count - 1; int PenultSectnId = Sectns.Count - 2; iRoadSectn LastSection = Sectns.Last(); iRoadSectn PenultSection = Sectns[Sectns.Count - 2]; //iRoadSectn PrevSection = Sectns[Sectns.Count - 3]; //int PrevSegCount = PrevSection.Segments.Count; int PenultSegCount = PenultSection.Segments.Count; int PenultSegStartId = PenultSegCount > 0 ? PenultSection.Segments[0].Idx : 0; //I tested this function using Watches on all the XSecCounts, SegmentCounts and SegStart and SegCount for each section //comparing them before adding and deleting a section and then after //Remove Section's Segment GameObjects foreach (RoadSegment seg in PenultSection.Segments) { GameObject.Destroy(seg.goSeg); } if (!IsCircular) { Segments.RemoveRange(PenultSegStartId, PenultSegCount); PenultSection.Segments.Clear(); PenultSection.DeleteFence(); XSecs.RemoveRange(PenultSegStartId, PenultSegCount); //PenultSection.XSecs.Clear(); } if (IsCircular) { PenultSection.DeleteFence(); Segments.RemoveRange(PenultSegStartId, PenultSegCount); PenultSection.Segments.Clear(); XSecs.RemoveRange(PenultSegStartId, PenultSegCount); //PenultSection.XSecs.Clear(); //Road.Instance.XSecs.RemoveRange(PrevSegStartId, PrevSegCount); } //Delete Section GameObject.Destroy(LastSection.goSectn); Sectns.Remove(LastSection); BezierLine.Instance.RemoveLastControlPoint(); //also removes the path points and selects the previous CtrlPt IsCircular = false; Game.current.Dirty = true; }
public void Encode(iRoadSectn RS) { Idx = RS.Idx; LFenceType = RS.LFenceType; RFenceType = RS.RFenceType; Mat = RS.RoadMaterial; LFenceVerts = new Vector3Serial[RS.LFenceVerts.Count]; for (int LFVId = 0; LFVId < RS.LFenceVerts.Count; LFVId++) { LFenceVerts[LFVId] = new Vector3Serial(RS.LFenceVerts[LFVId]); } RFenceVerts = new Vector3Serial[RS.RFenceVerts.Count]; for (int RFVId = 0; RFVId < RS.RFenceVerts.Count; RFVId++) { RFenceVerts[RFVId] = new Vector3Serial(RS.RFenceVerts[RFVId]); } //XSecIds = new int[RS.XSecs.Count]; //for (int XSId = 0; XSId < RS.XSecs.Count; XSId++) //{ // XSecIds[XSId] = RS.XSecs[XSId].Idx; //} }
/// <summary> /// We build a MeshCollider for the whole section's fence by iterating through all the Kerbs /// </summary> public void CreateFenceColliderVerts() { float FenceLeanCoeff = 0f; //Positive 0.11 means the top of the fence leans inward and the bottom leans outward float FenceOffset = 0.1f; //Positive 0.1 means the middle of the fence extends over the kerb iRoadSectn Sec = Road.Instance.Sectns[SectnIdx]; int SectnStartIdx = Sec.Segments[0].Idx; int ReltvIdx = Idx - SectnStartIdx; //The first Segment of the current section has RelativeIdx = 0; try { if (ReltvIdx != -1) //Skip if you are on the last segment { //Contact face of the fence is not vertical. It leans slightly towards the car so the car cannot ride over it. //Too much lean and it gets wedged underneath. Too litle and the car bounces off it throwing the rear end off the road //19/3/20 Added the Gnd function. This throws the fence down to the ground for Air track. //Didn't add it to the last seg of previous sectn. Didn't add it to the last seg of loop Sec.FenceColldrVertsR[ReltvIdx * 4] = Vector3.Lerp(Gnd(Verts.KerbBR), Verts.TerrainBR, FenceLeanCoeff - FenceOffset); //first inner bottom leans out by 0.11f Sec.FenceColldrVertsR[ReltvIdx * 4 + 1] = Vector3.Lerp(Gnd(Verts.KerbBR), Gnd(Verts.TerrainBR), -FenceLeanCoeff - FenceOffset) + Vector3.up * 1.3f; //first inner top - leans in by 0.11f Sec.FenceColldrVertsR[ReltvIdx * 4 + 2] = Vector3.Lerp(Gnd(Verts.KerbBR), Gnd(Verts.TerrainBR), 0.2f) + Vector3.up * 1.3f; Sec.FenceColldrVertsR[ReltvIdx * 4 + 3] = Vector3.Lerp(Gnd(Verts.KerbBR), Gnd(Verts.TerrainBR), 0.2f); Sec.FenceColldrVertsR[ReltvIdx * 4 + 4] = Vector3.Lerp(Gnd(Verts.KerbFR), Gnd(Verts.TerrainFR), FenceLeanCoeff - FenceOffset); //second inner botttom leans out by 0.11f Sec.FenceColldrVertsR[ReltvIdx * 4 + 5] = Vector3.Lerp(Gnd(Verts.KerbFR), Gnd(Verts.TerrainFR), -FenceLeanCoeff - FenceOffset) + Vector3.up * 1.3f; //second inner top - leans in by 0.11f Sec.FenceColldrVertsR[ReltvIdx * 4 + 6] = Vector3.Lerp(Gnd(Verts.KerbFR), Gnd(Verts.TerrainFR), 0.2f) + Vector3.up * 1.3f; Sec.FenceColldrVertsR[ReltvIdx * 4 + 7] = Vector3.Lerp(Gnd(Verts.KerbFR), Gnd(Verts.TerrainFR), 0.2f); Sec.FenceColldrVertsL[ReltvIdx * 4] = Vector3.Lerp(Gnd(Verts.KerbBL), Gnd(Verts.TerrainBL), 0.2f); Sec.FenceColldrVertsL[ReltvIdx * 4 + 1] = Vector3.Lerp(Gnd(Verts.KerbBL), Gnd(Verts.TerrainBL), 0.2f) + Vector3.up * 1.3f; Sec.FenceColldrVertsL[ReltvIdx * 4 + 2] = Vector3.Lerp(Gnd(Verts.KerbBL), Gnd(Verts.TerrainBL), -FenceLeanCoeff - FenceOffset) + Vector3.up * 1.3f; //first inner top - leans in by 0.11f Sec.FenceColldrVertsL[ReltvIdx * 4 + 3] = Vector3.Lerp(Gnd(Verts.KerbBL), Gnd(Verts.TerrainBL), FenceLeanCoeff - FenceOffset); //first inner bottom leans out by 0.11f Sec.FenceColldrVertsL[ReltvIdx * 4 + 4] = Vector3.Lerp(Gnd(Verts.KerbFL), Gnd(Verts.TerrainFL), 0.2f); Sec.FenceColldrVertsL[ReltvIdx * 4 + 5] = Vector3.Lerp(Gnd(Verts.KerbFL), Gnd(Verts.TerrainFL), 0.2f) + Vector3.up * 1.3f; Sec.FenceColldrVertsL[ReltvIdx * 4 + 6] = Vector3.Lerp(Gnd(Verts.KerbFL), Gnd(Verts.TerrainFL), -FenceLeanCoeff - FenceOffset) + Vector3.up * 1.3f; //second inner top - leans in by 0.11f Sec.FenceColldrVertsL[ReltvIdx * 4 + 7] = Vector3.Lerp(Gnd(Verts.KerbFL), Gnd(Verts.TerrainFL), FenceLeanCoeff - FenceOffset); //second inner botttom leans out by 0.11f } if (ReltvIdx == 0 && SectnIdx > 1) //Do the final vertices of the previous section { ReltvIdx = Road.Instance.Sectns[SectnIdx - 1].Segments.Count; Sec = Road.Instance.Sectns[SectnIdx - 1]; Sec.FenceColldrVertsR[ReltvIdx * 4] = Vector3.Lerp(Verts.KerbBR, Verts.TerrainBR, FenceLeanCoeff - FenceOffset); //Inner Bottom Sec.FenceColldrVertsR[ReltvIdx * 4 + 1] = Vector3.Lerp(Verts.KerbBR, Verts.TerrainBR, -FenceLeanCoeff - FenceOffset) + Vector3.up * 1.3f; //Inner Top Sec.FenceColldrVertsR[ReltvIdx * 4 + 2] = Vector3.Lerp(Verts.KerbBR, Verts.TerrainBR, 0.2f) + Vector3.up * 1.3f; Sec.FenceColldrVertsR[ReltvIdx * 4 + 3] = Vector3.Lerp(Verts.KerbBR, Verts.TerrainBR, 0.2f); Sec.FenceColldrVertsL[ReltvIdx * 4] = Vector3.Lerp(Verts.KerbBL, Verts.TerrainBL, 0.2f); Sec.FenceColldrVertsL[ReltvIdx * 4 + 1] = Vector3.Lerp(Verts.KerbBL, Verts.TerrainBL, 0.2f) + Vector3.up * 1.3f; Sec.FenceColldrVertsL[ReltvIdx * 4 + 2] = Vector3.Lerp(Verts.KerbBL, Verts.TerrainBL, -FenceLeanCoeff - FenceOffset) + Vector3.up * 1.3f; //First Inner Top Sec.FenceColldrVertsL[ReltvIdx * 4 + 3] = Vector3.Lerp(Verts.KerbBL, Verts.TerrainBL, FenceLeanCoeff - FenceOffset); //Inner Bottom } if (Road.Instance.IsCircular && ReltvIdx == 18) //The very last segment in the looped track { if (SectnIdx == Road.Instance.Sectns.Count - 2) { ReltvIdx = 20; ///bug - there arent always 20 segs in a sectn Sec = Road.Instance.Sectns[SectnIdx]; Sec.FenceColldrVertsR[ReltvIdx * 4] = Vector3.Lerp(Road.Instance.Segments[1].Verts.KerbBR, Road.Instance.Segments[1].Verts.TerrainBR, FenceLeanCoeff); Sec.FenceColldrVertsR[ReltvIdx * 4 + 1] = Road.Instance.Segments[1].Verts.KerbBR + Vector3.up * 1.3f; Sec.FenceColldrVertsR[ReltvIdx * 4 + 2] = Road.Instance.Segments[1].Verts.TerrainBR + Vector3.up * 1.3f; Sec.FenceColldrVertsR[ReltvIdx * 4 + 3] = Road.Instance.Segments[1].Verts.TerrainBR; Sec.FenceColldrVertsL[ReltvIdx * 4] = Road.Instance.Segments[1].Verts.TerrainBL; Sec.FenceColldrVertsL[ReltvIdx * 4 + 1] = Road.Instance.Segments[1].Verts.TerrainBL + Vector3.up * 1.3f; Sec.FenceColldrVertsL[ReltvIdx * 4 + 2] = Road.Instance.Segments[1].Verts.KerbBL + Vector3.up * 1.3f; Sec.FenceColldrVertsL[ReltvIdx * 4 + 3] = Road.Instance.Segments[1].Verts.KerbBL; } } } catch (Exception e) { Debug.Log(e.ToString()); } }
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; } }