public void AddPoints(PathPoint[] _points){ List<PathPoint> points = FilterPoints(_points); lastPoint = points[0].pos; for (int i = 0; i < points.Count - 1; i++) { Debug.DrawLine(points[i].pos, points[i].pos + Vector3.up, points[i].guessed ? Color.cyan : Color.blue, 20000); Debug.DrawLine(points[i].pos, points[i].pos + points[i].forwards, Color.green, 20000); Debug.DrawLine(points[i].pos, points[i].pos + points[i].backwards, Color.grey, 20000); PathPoint thisPoint = points[i]; PathPoint nextPoint = points[i + 1]; // Log.debug(i + ":" + "Angle:" + Vector3.Angle(thisPoint.normal, nextPoint.normal) + " Magnitude: " + (thisPoint.pos - nextPoint.pos).magnitude); Vector3 thisPointPos = thisPoint.pos; Vector3 nextPointPos = nextPoint.pos; float angle = Vector3.Angle(thisPoint.forwards, nextPoint.forwards); float segementLength = (thisPointPos - nextPointPos).magnitude; if (thisPoint.forwards.magnitude > maxNormalSize) thisPoint.forwards = thisPoint.forwards.normalized * maxNormalSize; if (thisPoint.backwards.magnitude > maxNormalSize) thisPoint.backwards = thisPoint.backwards.normalized * maxNormalSize; Vector3 p0 = thisPointPos; Vector3 p1 = thisPointPos + thisPoint.forwards * normalScaleFactor; Vector3 p2 = nextPointPos + nextPoint.backwards * normalScaleFactor; //Seperate logic for tight turns if (segementLength < 30.0f) { p1 = thisPointPos + thisPoint.forwards.normalized * segementLength * tightNormalScaleFactor; p2 = nextPointPos + nextPoint.backwards.normalized * segementLength * tightNormalScaleFactor; } Vector3 p3 = nextPointPos; // Debug.DrawLine(p0, p1, Color.cyan, 2000); // Debug.DrawLine(p2, p3, Color.cyan, 2000); //First calculate the real length of the spline with a rough calulation float realLength = 0; float maxAngle = 0; for (float a = 0; a < 1.0f; a += 0.1f) { Vector3 pointA = Beizer.CalculateBezierPoint(a, p0, p1, p2, p3); Vector3 pointB = Beizer.CalculateBezierPoint(a + 0.2f, p0, p1, p2, p3); float ang = Vector3.Angle(pointB-p0, p1-p0); if (ang > maxAngle) { maxAngle = ang; } realLength += (pointA - pointB).magnitude; } if (realLength > pathBreakThreshold) { AddVertexPair(thisPoint.pos, thisPoint.forwards.normalized, false); AddEndStop(thisPoint.pos, thisPoint.forwards.normalized, true); AddEndStop(nextPoint.pos, nextPoint.forwards.normalized, false); AddVertexPair(nextPoint.pos, nextPoint.forwards.normalized); continue; } // Make each segment tile a whole number of texture repeats so that // overlaping paths line up int textureRepeats = (int)Math.Floor(realLength / (width * 4)); textureOffset = (float)Math.Round(textureOffset); //Aim to keep a fixed size for each quad, increaing the number the more it curves int steps = (int)Math.Floor(realLength / 20.0f + maxAngle / 3.0f) + 1; float step = 1.0f / steps; for (float a = 0; a < 1.0f; a += step) { Vector3 point = Beizer.CalculateBezierPoint(a, p0, p1, p2, p3); Vector3 pointB = Beizer.CalculateBezierPoint(a+step, p0, p1, p2, p3); Vector3 fwd = (pointB - point).normalized; Debug.DrawLine(point+ Vector3.up, point + Vector3.up + fwd, Color.green, 2000); AddVertexPair(point, fwd); textureOffset += step * textureRepeats; } } //End the last segement AddVertexPair(points[points.Count - 1].pos, points[points.Count - 1].forwards.normalized, false); //GenerateIndiciesAsLineStrip (); AddEndStop(points[0].pos, points[0].forwards.normalized, false); AddEndStop(points[points.Count - 1].pos, points[points.Count - 1].forwards.normalized, true); }
private GameObject CreatePathGameobject(string type, PathPoint[] positions) { lineMaterial.color = new Color(1, 0, 0, 1); PathMeshBuilder pb = new PathMeshBuilder(); if (type == "Citizen/Foot" || type == "Citizen/Cycle") { //Citizens have much tighter paths, to remove duplicate points so much //pb.duplicatePointThreshold = 0.0f; pb.tightNormalScaleFactor = 0.05f; pb.pathBreakThreshold = 300.0f; //If a path segemnt is longer than this they are riding a bus/metro/train pb.maxNormalSize = 30.0f; } pb.AddPoints(positions); Mesh m = pb.GetMesh(); GameObject go = new GameObject(); ; go.AddComponent<MeshFilter>(); go.AddComponent<MeshRenderer>(); go.GetComponent<MeshFilter>().mesh = m; go.GetComponent<MeshFilter>().sharedMesh = m; go.GetComponent<MeshRenderer>().material = lineMaterial; go.transform.localPosition = new Vector3(0, 3, 0); go.SetActive(Config.instance.IsTypeVisible(type)); return go; }
PathPoint[] GatherPathVerticies(uint pathID, bool isPed = false) { List<PathPoint> path = new List<PathPoint>(); NetSegment[] segments = netMan.m_segments.m_buffer; NetNode[] nodes = netMan.m_nodes.m_buffer; NetLane[] lanes = Singleton<NetManager>.instance.m_lanes.m_buffer; PathUnit[] paths = Singleton<PathManager>.instance.m_pathUnits.m_buffer; uint segment = paths[pathID].GetPosition(0).m_segment; uint startNode; startNode = segments[segment].m_startNode; PathUnit.Position[] positions = GatherPathPositions(pathID, isPed); //Log.debug("Generating verticies..."); PathPoint lastPoint = new PathPoint(); for (int i = 0; i < positions.Length; i++) { Vector3 pv, dir; PathPoint newPoint = new PathPoint(); uint laneId = PathManager.GetLaneID(positions[i]); //Put the destination market on the road not the sidewalk if (i == positions.Length - 1) { laneId = lastPoint.laneId; } lanes[laneId].CalculatePositionAndDirection(positions[i].m_offset / 255.0f,out pv, out dir); newPoint.laneId = laneId; newPoint.guessed = false; newPoint.pos = pv; newPoint.forwards = (positions[i].m_offset < 128) ? -dir : dir; newPoint.backwards = -newPoint.forwards; //Point is contining a curve if ((lastPoint.pos - newPoint.pos).magnitude < 5.0f) { newPoint.backwards = -lastPoint.forwards; } newPoint.segmentId = positions[i].m_segment; path.Add(newPoint); lastPoint = newPoint; if (i < positions.Length - 2) { if (positions[i].m_segment != positions[i + 1].m_segment) { newPoint = new PathPoint(); PathUnit.Position nextPos = positions[i + 1]; laneId = PathManager.GetLaneID(nextPos); Vector3 pvA, dirA, pvB,dirB; lanes[laneId].CalculatePositionAndDirection(0, out pvA, out dirA); lanes[laneId].CalculatePositionAndDirection(1, out pvB, out dirB); //Skip when not a junction; if (pvA == pv || pvB == pv) continue; newPoint.guessed = true; newPoint.laneId = laneId; //Find the closest lane end of the next segment if ((pvA - pv).magnitude < (pvB - pv).magnitude) { newPoint.pos = pvA; newPoint.forwards = dirA; newPoint.backwards = -dirA; } else { newPoint.pos = pvB; newPoint.forwards = -dirB; newPoint.backwards = dirB; } newPoint.segmentId = positions[i + 1].m_segment; path.Add(newPoint); lastPoint = newPoint; } } } return path.ToArray(); }
public void AddPoints(PathPoint[] _points) { List<PathPoint> points = FilterPoints(_points); lastPoint = points[0].pos; for (int i = 0; i < points.Count - 1; i++) { Debug.DrawLine(points[i].pos, points[i].pos + Vector3.up, points[i].guessed ? Color.cyan : Color.blue, 20000); Debug.DrawLine(points[i].pos, points[i].pos + points[i].forwards, Color.green, 20000); Debug.DrawLine(points[i].pos, points[i].pos + points[i].backwards, Color.grey, 20000); PathPoint thisPoint = points[i]; PathPoint nextPoint = points[i + 1]; // Log.debug(i + ":" + "Angle:" + Vector3.Angle(thisPoint.normal, nextPoint.normal) + " Magnitude: " + (thisPoint.pos - nextPoint.pos).magnitude); Vector3 thisPointPos = thisPoint.pos; Vector3 nextPointPos = nextPoint.pos; float angle = Vector3.Angle(thisPoint.forwards, nextPoint.forwards); float segementLength = (thisPointPos - nextPointPos).magnitude; if (thisPoint.forwards.magnitude > maxNormalSize) thisPoint.forwards = thisPoint.forwards.normalized * maxNormalSize; if (thisPoint.backwards.magnitude > maxNormalSize) thisPoint.backwards = thisPoint.backwards.normalized * maxNormalSize; Vector3 p0 = thisPointPos; Vector3 p1 = thisPointPos + thisPoint.forwards * normalScaleFactor; Vector3 p2 = nextPointPos + nextPoint.backwards * normalScaleFactor; //Seperate logic for tight turns if (segementLength < 30.0f) { p1 = thisPointPos + thisPoint.forwards.normalized * segementLength * tightNormalScaleFactor; p2 = nextPointPos + nextPoint.backwards.normalized * segementLength * tightNormalScaleFactor; } Vector3 p3 = nextPointPos; // Debug.DrawLine(p0, p1, Color.cyan, 2000); // Debug.DrawLine(p2, p3, Color.cyan, 2000); //First calculate the real length of the spline with a rough calulation float realLength = 0; float maxAngle = 0; for (float a = 0; a < 1.0f; a += 0.1f) { Vector3 pointA = Beizer.CalculateBezierPoint(a, p0, p1, p2, p3); Vector3 pointB = Beizer.CalculateBezierPoint(a + 0.2f, p0, p1, p2, p3); float ang = Vector3.Angle(pointB-p0, p1-p0); if (ang > maxAngle) { maxAngle = ang; } realLength += (pointA - pointB).magnitude; } if (realLength > pathBreakThreshold) { AddVertexPair(thisPoint.pos, thisPoint.forwards.normalized, false); AddEndStop(thisPoint.pos, thisPoint.forwards.normalized, true); AddEndStop(nextPoint.pos, nextPoint.forwards.normalized, false); AddVertexPair(nextPoint.pos, nextPoint.forwards.normalized); continue; } // Make each segment tile a whole number of texture repeats so that // overlaping paths line up int textureRepeats = (int)Math.Floor(realLength / (width * 4)); textureOffset = (float)Math.Round(textureOffset); //Aim to keep a fixed size for each quad, increaing the number the more it curves int steps = (int)Math.Floor(realLength / 20.0f + maxAngle / 3.0f) + 1; float step = 1.0f / steps; for (float a = 0; a < 1.0f; a += step) { Vector3 point = Beizer.CalculateBezierPoint(a, p0, p1, p2, p3); Vector3 pointB = Beizer.CalculateBezierPoint(a+step, p0, p1, p2, p3); Vector3 fwd = (pointB - point).normalized; Debug.DrawLine(point+ Vector3.up, point + Vector3.up + fwd, Color.green, 2000); AddVertexPair(point, fwd); textureOffset += step * textureRepeats; } } //End the last segement AddVertexPair(points[points.Count - 1].pos, points[points.Count - 1].forwards.normalized, false); //GenerateIndiciesAsLineStrip (); AddEndStop(points[0].pos, points[0].forwards.normalized, false); AddEndStop(points[points.Count - 1].pos, points[points.Count - 1].forwards.normalized, true); }
public List<PathPoint> FilterPoints(PathPoint[] points) { List<PathPoint> o = new List<PathPoint>(); int j = 0; for (int i = 0; i < points.Length -1; i++) { if ((points[j].pos - points[i].pos).magnitude < duplicatePointThreshold) continue; // KLUDGE: Filter out tight U-Turns if ( i > points.Length - 4 && (Vector3.Angle(points[j].forwards, points[i].forwards) > 170.0f) && (points[j].pos - points[i].pos).magnitude < duplicatePointThreshold ) continue; j = i; o.Add(points[i]); } points[points.Length - 1].forwards = Vector3.zero;// points[points.Length - 1].pos - points[j].pos; o.Add(points[points.Length - 1]); return o; }
PathPoint[] GatherPathVerticies(uint pathID, bool isPed = false) { List <PathPoint> path = new List <PathPoint>(); NetSegment[] segments = netMan.m_segments.m_buffer; NetNode[] nodes = netMan.m_nodes.m_buffer; NetLane[] lanes = Singleton <NetManager> .instance.m_lanes.m_buffer; PathUnit[] paths = Singleton <PathManager> .instance.m_pathUnits.m_buffer; uint segment = paths[pathID].GetPosition(0).m_segment; uint startNode; startNode = segments[segment].m_startNode; PathUnit.Position[] positions = GatherPathPositions(pathID, isPed); //Log.debug("Generating verticies..."); PathPoint lastPoint = new PathPoint(); for (int i = 0; i < positions.Length; i++) { Vector3 pv, dir; PathPoint newPoint = new PathPoint(); uint laneId = PathManager.GetLaneID(positions[i]); //Put the destination market on the road not the sidewalk if (i == positions.Length - 1) { laneId = lastPoint.laneId; } lanes[laneId].CalculatePositionAndDirection(positions[i].m_offset / 255.0f, out pv, out dir); newPoint.laneId = laneId; newPoint.guessed = false; newPoint.pos = pv; newPoint.forwards = (positions[i].m_offset < 128) ? -dir : dir; newPoint.backwards = -newPoint.forwards; //Point is contining a curve if ((lastPoint.pos - newPoint.pos).magnitude < 5.0f) { newPoint.backwards = -lastPoint.forwards; } newPoint.segmentId = positions[i].m_segment; path.Add(newPoint); lastPoint = newPoint; if (i < positions.Length - 2) { if (positions[i].m_segment != positions[i + 1].m_segment) { newPoint = new PathPoint(); PathUnit.Position nextPos = positions[i + 1]; laneId = PathManager.GetLaneID(nextPos); Vector3 pvA, dirA, pvB, dirB; lanes[laneId].CalculatePositionAndDirection(0, out pvA, out dirA); lanes[laneId].CalculatePositionAndDirection(1, out pvB, out dirB); //Skip when not a junction; if (pvA == pv || pvB == pv) { continue; } newPoint.guessed = true; newPoint.laneId = laneId; //Find the closest lane end of the next segment if ((pvA - pv).magnitude < (pvB - pv).magnitude) { newPoint.pos = pvA; newPoint.forwards = dirA; newPoint.backwards = -dirA; } else { newPoint.pos = pvB; newPoint.forwards = -dirB; newPoint.backwards = dirB; } newPoint.segmentId = positions[i + 1].m_segment; path.Add(newPoint); lastPoint = newPoint; } } } return(path.ToArray()); }