public void CreateRoofCollider() { if (XSecs.Count != 0) // 0 - 2 - 4 - 6 -...This section has 3 XSecs. 6 and 7 belong to the next Sectn // | \ | \ | \ | so we'll only put a roof over the first 2 // 1 - 3 - 5 - 7 { Vector3[] RoofVerts = new Vector3[XSecs.Count * 2]; int[] RoofTris = new int[XSecs.Count * 6 - 6]; for (int i = 0; i < XSecs.Count() - 1; i++) { RoofVerts[i * 2] = XSecs[i].TerrainL + Vector3.up * 2; RoofVerts[i * 2 + 1] = XSecs[i].TerrainR + Vector3.up * 2; RoofTris[i * 6] = i * 2; RoofTris[i * 6 + 1] = i * 2 + 1; RoofTris[i * 6 + 2] = i * 2 + 3; RoofTris[i * 6 + 3] = i * 2; RoofTris[i * 6 + 4] = i * 2 + 3; RoofTris[i * 6 + 5] = i * 2 + 2; } Mesh MR = new Mesh(); MR.vertices = RoofVerts; MR.triangles = RoofTris; MR.RecalculateBounds(); MR.RecalculateNormals(); ; GameObject goTempRoof = new GameObject(); goTempRoof.name = "goTempRoof"; goTempRoof.AddComponent <MeshCollider>().sharedMesh = MR; } }
public void ListXSecs() { foreach (XSec x in XSecs) { Debug.Log("Index=" + XSecs.IndexOf(x) + " - " + x.Idx + x.MidPt); } }
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 Init() { //This is just because the sections and segments start at Idx=1 //Segment[0] doesn't do anything Segments.Clear(); XSecs.Clear(); Sectns.Clear(); //RacingLine = new RacingLine(); IsCircular = false; RoadSectn sectn = new RoadSectn(); Sectns.Add(sectn); sectn.Idx = 0; //Put all the materials in a dictionary for faster retrieval Material M; RoadMaterials = new Dictionary <string, Material>(); M = (Material)Resources.Load("Prefabs/Materials/Tarmac", typeof(Material)); RoadMaterials.Add("Tarmac", M); M = (Material)Resources.Load("Prefabs/Materials/Tarmac0", typeof(Material)); RoadMaterials.Add("Tarmac0", M); M = (Material)Resources.Load("Prefabs/Materials/Tarmac1", typeof(Material)); RoadMaterials.Add("Tarmac1", M); M = (Material)Resources.Load("Prefabs/Materials/Tarmac2", typeof(Material)); RoadMaterials.Add("Tarmac2", M); M = (Material)Resources.Load("Prefabs/Materials/Tarmac3", typeof(Material)); RoadMaterials.Add("Tarmac3", M); M = (Material)Resources.Load("Prefabs/Materials/Washboard0", typeof(Material)); RoadMaterials.Add("Washboard0", M); M = (Material)Resources.Load("Prefabs/Materials/Washboard1", typeof(Material)); RoadMaterials.Add("Washboard1", M); M = (Material)Resources.Load("Prefabs/Materials/DirtyRoad", typeof(Material)); RoadMaterials.Add("DirtyRoad", M); M = (Material)Resources.Load("Prefabs/Materials/DirtRoad0", typeof(Material)); RoadMaterials.Add("DirtRoad0", M); M = (Material)Resources.Load("Prefabs/Materials/DirtRoad1", typeof(Material)); RoadMaterials.Add("DirtRoad1", M); M = (Material)Resources.Load("Prefabs/Materials/DirtRoad2", typeof(Material)); RoadMaterials.Add("DirtRoad2", M); M = (Material)Resources.Load("Prefabs/Materials/DirtRoad3", typeof(Material)); RoadMaterials.Add("DirtRoad3", M); M = (Material)Resources.Load("Prefabs/Materials/TarmacUnderside", typeof(Material)); RoadMaterials.Add("TarmacUnderside", M); M = (Material)Resources.Load("Prefabs/Materials/WashboardUnderside", typeof(Material)); RoadMaterials.Add("WashboardUnderside", M); M = (Material)Resources.Load("Prefabs/Materials/DirtyRoadUnderside", typeof(Material)); RoadMaterials.Add("DirtyRoadUnderside", M); SkidMks = new Queue <FlatLineRenderer>(); }
private void PopulateXSecCurrBends() { foreach (Bend _bend in Bends) { //These two saved a massive performance hit Bend _nb = Bends.Next(_bend); for (XSec x = _bend.TurninXSec; x != _bend.ExitXSec; x = XSecs.Next(x)) { x.CurrBend = _bend; } if (_nb.TurninXSec == null) { Debug.Log("BendId" + _bend.BendId + " no turnin"); } else { for (XSec x = _bend.TurninXSec; x != _nb.TurninXSec; x = XSecs.Next(x)) { x.NextBend = _nb; } } } }
public void CalculateBends() { if (!IsCircular) { return; } Bends = new CircleList <Bend>(); Bend _bend = new Bend(); int BendId = 0; MovingAvgFloat AngleQueue = new MovingAvgFloat(5); _bez = BezierLine.Instance; int XSecCount = XSecs.Count(); Vector3 PrevMid; Vector3 ThisMid; Vector3 NextMid; BendType _bt = BendType.Unknown; BendType _prevbt = BendType.Unknown; int Incr = 1; float AngleThreshold = 1.34f; foreach (XSec X in XSecs) { PrevMid = XSecs.Prev(X).MidPt; ThisMid = X.MidPt; NextMid = XSecs.Next(X).MidPt; float Angle = VectGeom.SignedAngle(ThisMid + ThisMid - PrevMid, ThisMid, NextMid, Vector3.up); float _segDist = Vector3.Distance(ThisMid, NextMid); AngleQueue.Push(Angle); if (Mathf.Abs(AngleQueue.Avg) < AngleThreshold) { _bt = BendType.Straight; } else { _bt = AngleQueue.Avg > 0 ? BendType.Right : BendType.Left; } if (_prevbt == _bt) { _bend.Angle += Angle; } else { if (_prevbt == BendType.Left || _prevbt == BendType.Right) { //Finish off the previous bend if (Mathf.Abs(_bend.Angle) < 15) { //ignore small bends Bends.Remove(_bend); BendId--; } else { //take 2 off cos of moving avg _bend.EndXSec = XSecs[X.Idx - 2]; _bend.EndSegIdx = _bend.EndXSec.Idx; _bend.ApexXSec = XSecs[_bend.StartSegIdx + Mathf.RoundToInt(XSecs.Diff(_bend.StartXSec, _bend.EndXSec) / 2)]; _bend.ApexSegIdx = _bend.ApexXSec.Idx; if (_bend.Type == BendType.Right) { _bend.ApexPos = _bend.ApexXSec.KerbR + (_bend.ApexXSec.KerbL - _bend.ApexXSec.KerbR).normalized; _bend.MinTurninPos = _bend.StartXSec.KerbR + (_bend.StartXSec.KerbL - _bend.StartXSec.KerbR).normalized * (_bend.Concatenated ? 4 : 2); } if (_bend.Type == BendType.Left) { _bend.ApexPos = _bend.ApexXSec.KerbL + (_bend.ApexXSec.KerbR - _bend.ApexXSec.KerbL).normalized; _bend.MinTurninPos = _bend.StartXSec.KerbL + (_bend.StartXSec.KerbR - _bend.StartXSec.KerbL).normalized * (_bend.Concatenated ? 4 : 2); } //Fmax = mv^2/r float c = (_bend.EndSegIdx - _bend.StartSegIdx) * 360 / _bend.Angle; float r = Mathf.Abs(c) / Mathf.PI / 2f; //Debug.Log("Bend" + _bend.BendId + " radius = " + r); _bend.SqrtRad = Mathf.Sqrt(r); } } else { //We might be starting a new bend or carrying n the previous one if (_bt == BendType.Left || _bt == BendType.Right) { bool StartNewBend = true; if (BendId > 0 && X.Idx - Bends[BendId - 1].EndSegIdx < 15 && Bends[BendId - 1].Type == _bt) ///bugbugbug circle bug { //if the bend we've just finished is close to and the same sign as one before //We just carry on with this bend and dont create a new one StartNewBend = false; _bend.Concatenated = true; GameObject.Destroy(GameObject.Find("Turnin" + _bend.BendId)); GameObject.Destroy(GameObject.Find("Apex" + _bend.BendId)); GameObject.Destroy(GameObject.Find("BendStart" + _bend.BendId)); } if (StartNewBend) { //Create a new Bend _bend = new Bend(); _bend.Type = _bt; _bend.Sign = _bt == BendType.Right ? (Int16)1 : (Int16)(-1); _bend.StartXSec = XSecs[X.Idx - 2];//-2 cos of moving avg _bend.StartSegIdx = _bend.StartXSec.Idx; _bend.Angle = Angle; _bend.BendId = BendId; Bends.Add(_bend); BendId++; } } } //****************************************************************************************** } _prevbt = _bt; } //This is the last bend. NOt a brilliant bit but it doesn't crash if (_bt == BendType.Straight) { goto Finalise; } _bend.EndSegIdx = XSecs.Count - 1; _bend.EndXSec = XSecs[_bend.EndSegIdx]; if (_bend.EndSegIdx <= _bend.StartSegIdx && Bends.Count() > 0) { Bends.Remove(_bend); Bends.Last().EndSegIdx = XSecs.Count; } else { _bend.ApexSegIdx = Mathf.RoundToInt((_bend.EndSegIdx + _bend.StartSegIdx) / 2); _bend.ApexXSec = XSecs[_bend.ApexSegIdx]; if (_bend.Type == BendType.Right) { _bend.ApexPos = _bend.ApexXSec.KerbR + (_bend.ApexXSec.KerbL - _bend.ApexXSec.KerbR).normalized; } if (_bend.Type == BendType.Left) { _bend.ApexPos = _bend.ApexXSec.KerbL + (_bend.ApexXSec.KerbR - _bend.ApexXSec.KerbL).normalized; } } Finalise: CalculateTurninAndExitPoints(); PopulateXSecCurrBends(); }