private static bool TryFindWidthRecord(EcsRoadData roadData, EcsLane lane, float sLocal, out LaneWidthRecord laneWidthRecord) { var widthRecordIdx = 0; var foundWidthRecord = false; laneWidthRecord = default; var laneWidthRecords = lane.GetLaneWidthRecords(roadData.laneWidthRecords); for (; widthRecordIdx < laneWidthRecords.Length; widthRecordIdx++) { var widthRecordNext = laneWidthRecords[widthRecordIdx]; var sOffsetNext = widthRecordNext.sSectionOffset; if (sOffsetNext > sLocal) { break; } laneWidthRecord = widthRecordNext; foundWidthRecord = true; } return(foundWidthRecord); }
// TODO: Width records are still searched every time - this could be optimized by tracking the current record /// <summary> /// Sample the laneSection at the given s position. /// </summary> /// <param name="sDelta">s position to sample. Must be between laneSection and s + length.</param> internal static PointSampleLocal BuildLaneSample(EcsRoadData roadData, EcsLane lane, float laneOffset, float sSection) { if (!TryFindWidthRecord(roadData, lane, sSection, out var widthRecord)) { if (lane.laneType == LaneType.Border) { return(new PointSampleLocal(0.0f, 0.0f, 0.0f)); } throw new Exception("Couldn't find width record for lane... xodr file may be malformed.'"); } var sign = lane.id > 0 ? 1f : -1f; var sDelta = sSection - widthRecord.sSectionOffset; var width = sign * Poly3ComputeV(widthRecord.poly3, sDelta); var heading = sign * Poly3ComputeHeading(widthRecord.poly3, sDelta); return(new PointSampleLocal(new Vector2(0, width + laneOffset), heading)); }
protected override void OnUpdate() { var rnd = Parameters.roadNetworkDescription == null ? staticRnd : Parameters.roadNetworkDescription; if (rnd == null) return; var id = rnd.entityRoadId == 0 ? nextId++ : rnd.entityRoadId; rnd.entityRoadId = id; var ecsRoadNetwork = new EcsRoadNetwork() { id = id }; //check for an existing road network var query = EntityManager.CreateEntityQuery(typeof(EcsRoadNetwork), typeof(EcsRoad)); query.AddSharedComponentFilter(ecsRoadNetwork); if (query.CalculateChunkCount() > 0) return; var roadEntities = new NativeArray<Entity>(rnd.AllRoads.Length, Allocator.Temp); EntityManager.CreateEntity(m_RoadArchetype, roadEntities); var junctionEntities = new NativeArray<Entity>(rnd.AllJunctions.Length, Allocator.Temp); EntityManager.CreateEntity(m_JunctionArchetype, junctionEntities); for (var roadIndex = 0; roadIndex < rnd.AllRoads.Length; roadIndex++) { var road = rnd.AllRoads[roadIndex]; var entity = roadEntities[roadIndex]; EntityManager.SetSharedComponentData(entity, ecsRoadNetwork); EntityManager.SetComponentData(entity, new EcsRoad { length = road.length, junction = string.IsNullOrEmpty(road.junction) || string.Equals("-1", road.junction) ? Entity.Null : junctionEntities[rnd.GetJunctionIndexById(road.junction)], name = road.name, predecessor = CreateEcsRoadLink(road.predecessor, rnd, roadEntities, junctionEntities), successor = CreateEcsRoadLink(road.successor, rnd, roadEntities, junctionEntities) }); //multiple copies - there is almost certainly a better way FillBuffer(road.elevationProfiles, entity); FillBuffer(road.geometry, entity); FillBuffer(road.laneOffsets, entity); var laneSections = EntityManager.GetBuffer<EcsLaneSection>(entity); var lanes = EntityManager.GetBuffer<EcsLane>(entity); var laneWidthRecords = EntityManager.GetBuffer<LaneWidthRecord>(entity); laneSections.ResizeUninitialized(road.laneSections.Count); for (var i = 0; i < road.laneSections.Count; i++) { var section = road.laneSections[i]; laneSections[i] = new EcsLaneSection { centerLaneIndex = lanes.Length + section._centerIdx, firstLaneIndex = lanes.Length, laneCount = section._allLanes.Length, sRoad = section.sRoad }; foreach (var lane in section._allLanes) { var ecsLane = new EcsLane { firstLaneWidthRecordIndex = laneWidthRecords.Length, laneWidthRecordCount = lane.widthRecords.Length, firstPredecessorId = FirstOrZero(lane.link.predecessors), predecessorIdCount = lane.link.predecessors?.Length ?? 0, firstSuccessorId = FirstOrZero(lane.link.successors), successorIdCount = lane.link.successors?.Length ?? 0, id = lane.id }; var nativeData = new NativeArray<LaneWidthRecord>(lane.widthRecords, Allocator.Temp); laneWidthRecords.AddRange(nativeData); nativeData.Dispose(); lanes.Add(ecsLane); } } } for (var junctionIndex = 0; junctionIndex < rnd.AllJunctions.Length; junctionIndex++) { var junction = rnd.AllJunctions[junctionIndex]; var entity = junctionEntities[junctionIndex]; EntityManager.SetSharedComponentData(entity, ecsRoadNetwork); EntityManager.SetComponentData(entity, new EcsJunction { name = junction.name, junctionId = junction.junctionId }); var connectionBuffer = EntityManager.GetBuffer<EcsJunctionConnection>(entity); connectionBuffer.ResizeUninitialized(junction.connections.Count); for (int connectionIndex = 0; connectionIndex < junction.connections.Count; connectionIndex++) { var connection = junction.connections[connectionIndex]; connectionBuffer[connectionIndex] = new EcsJunctionConnection { connectingRoad = roadEntities[rnd.GetRoadIndexById(connection.connectingRoadId)], incomingRoad = roadEntities[rnd.GetRoadIndexById(connection.incomingRoadId)], linkContactPoint = connection.contactPoint }; } } }