public bool NodeInsertion(ushort segment, float time) // time is in the range (0, 1) inclusive { Bezier3 bezier = new Bezier3(); NetSegment s1 = GetSegment(segment); bezier.a = NetManager.instance.m_nodes.m_buffer[s1.m_startNode].m_position; bezier.d = NetManager.instance.m_nodes.m_buffer[s1.m_endNode].m_position; bool smoothStart = (Singleton <NetManager> .instance.m_nodes.m_buffer[s1.m_startNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; bool smoothEnd = (Singleton <NetManager> .instance.m_nodes.m_buffer[s1.m_endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; NetSegment.CalculateMiddlePoints(bezier.a, s1.m_startDirection, bezier.d, s1.m_endDirection, smoothStart, smoothEnd, out Vector3 b, out Vector3 c); bezier.b = b; bezier.c = c; Vector3 timePoint = bezier.Position(time); ushort seg1ls = s1.m_startNode; Vector3 seg1lsd = s1.m_startDirection; Vector3 seg1led = -bezier.Tangent(time).normalized; ushort seg1rs = s1.m_endNode; Vector3 seg1rsd = s1.m_endDirection; Vector3 seg1red = bezier.Tangent(time).normalized; Manager.CreateNode(out ushort timePointNode, ref SimulationManager.instance.m_randomizer, s1.Info, timePoint, SimulationManager.instance.m_currentBuildIndex++); Manager.CreateSegment(out ushort seg1, ref SimulationManager.instance.m_randomizer, s1.Info, timePointNode, seg1ls, seg1led, seg1lsd, SimulationManager.instance.m_currentBuildIndex++, SimulationManager.instance.m_currentBuildIndex - 1, false); Manager.CreateSegment(out ushort seg2, ref SimulationManager.instance.m_randomizer, s1.Info, seg1rs, timePointNode, seg1rsd, seg1red, SimulationManager.instance.m_currentBuildIndex++, SimulationManager.instance.m_currentBuildIndex - 1, false); Manager.UpdateNode(timePointNode); Manager.UpdateSegment(seg1); Manager.UpdateSegment(seg2); Manager.ReleaseSegment(segment, true); m_newSeg1 = seg1; m_newSeg2 = seg2; return(true); }
private void RenderConnectLineOverlay(RenderManager.CameraInfo cameraInfo) { if (!IsSelectPoint) { return; } var bezier = new Bezier3(); Color color; if (IsHoverPoint) { var pointPair = new MarkupPointPair(SelectPoint, HoverPoint); color = EditMarkup.ExistConnection(pointPair) ? Color.red : Color.green; bezier.a = SelectPoint.Position; bezier.b = HoverPoint.Enter == SelectPoint.Enter ? HoverPoint.Position - SelectPoint.Position : SelectPoint.Direction; bezier.c = HoverPoint.Enter == SelectPoint.Enter ? SelectPoint.Position - HoverPoint.Position : HoverPoint.Direction; bezier.d = HoverPoint.Position; } else { color = Color.white; RaycastInput input = new RaycastInput(MouseRay, MouseRayLength); RayCast(input, out RaycastOutput output); bezier.a = SelectPoint.Position; bezier.b = SelectPoint.Direction; bezier.c = SelectPoint.Direction.Turn90(true); bezier.d = output.m_hitPos; Line2.Intersect(VectorUtils.XZ(bezier.a), VectorUtils.XZ(bezier.a + bezier.b), VectorUtils.XZ(bezier.d), VectorUtils.XZ(bezier.d + bezier.c), out _, out float v); bezier.c = v >= 0 ? bezier.c : -bezier.c; } NetSegment.CalculateMiddlePoints(bezier.a, bezier.b, bezier.d, bezier.c, true, true, out bezier.b, out bezier.c); RenderManager.OverlayEffect.DrawBezier(cameraInfo, color, bezier, 0.5f, 0f, 0f, -1f, 1280f, false, true); }
private void RenderSegmentParkings(RenderManager.CameraInfo cameraInfo) { bool allowed = parkingManager.IsParkingAllowed(renderInfo_.SegmentId, renderInfo_.FinalDirection); bool pressed = Input.GetMouseButton(0); Color color; if (pressed) { color = MainTool.GetToolColor(true, false); } else if (allowed) { color = Color.green; } else { color = Color.red; } Bezier3 bezier = default; netService.IterateSegmentLanes( renderInfo_.SegmentId, (uint laneId, ref NetLane lane, NetInfo.Lane laneInfo, ushort _, ref NetSegment segment, byte laneIndex) => { bool isParking = laneInfo.m_laneType.IsFlagSet(NetInfo.LaneType.Parking); if (isParking && laneInfo.m_finalDirection == renderInfo_.FinalDirection) { bezier = lane.m_bezier; laneMarker_ = new SegmentLaneMarker(bezier); laneMarker_.RenderOverlay(cameraInfo, color, enlarge: pressed); } return(true); }); }
public static void ClosestPositionAndDirection(this Bezier3 bezier, Vector3 point, out Vector3 position, out Vector3 direction, out float t) { var distance = 1E+11f; t = 0f; var prevPosition = bezier.a; for (var i = 1; i <= 16; i += 1) { var currentPosition = bezier.Position(i / 16f); var currentDistance = Segment3.DistanceSqr(prevPosition, currentPosition, point, out var u); if (currentDistance < distance) { distance = currentDistance; t = (i - 1f + u) / 16f; } prevPosition = currentPosition; } float delta = 0.03125f; for (var i = 0; i < 4; i += 1) { var minPosition = bezier.Position(Mathf.Max(0f, t - delta)); var currentPosition = bezier.Position(t); var maxPosition = bezier.Position(Mathf.Min(1f, t + delta)); var minDistance = Segment3.DistanceSqr(minPosition, currentPosition, point, out var minU); var maxDistance = Segment3.DistanceSqr(currentPosition, maxPosition, point, out var maxU); t = minDistance >= maxDistance?Mathf.Min(1f, t + delta *maxU) : Mathf.Max(0f, t - delta * (1f - minU)); delta *= 0.5f; } position = bezier.Position(t); direction = NormalizeXZ(bezier.Tangent(t)); }
void MakeRoad(Vector3 start, Vector3 end, Vector3 startDirection, Vector3 endDirection, bool flip, uint prefabId) { DebugOutputPanel.AddMessage(PluginManager.MessageType.Warning, "making bezier road"); if (flip) { Vector3 temp = start; start = end; end = temp; temp = -startDirection; startDirection = -endDirection; endDirection = temp; } float length = (end - start).magnitude; var curve = new Bezier3(start, start + startDirection * length / 3, end + endDirection * length / 3, end); Vector3 priorPos = curve.Position(0); Vector3 priorDir = curve.Tangent(0).normalized; float t = curve.Travel(0, pitch); DebugOutputPanel.AddMessage(PluginManager.MessageType.Warning, t.ToString()); while (t < .9999) { Vector3 pos = curve.Position(t); Vector3 dir = curve.Tangent(t); MakeSegment(priorPos, pos, priorDir, -dir, prefabId); t = curve.Travel(t, pitch); DebugOutputPanel.AddMessage(PluginManager.MessageType.Warning, t.ToString()); priorPos = pos; priorDir = dir; } { Vector3 pos = curve.Position(1); Vector3 dir = curve.Tangent(1).normalized; MakeSegment(priorPos, pos, priorDir, -dir, prefabId); } }
private static Bezier3 GetBezier(Vector3 startPos, Vector3 startDir, Vector3 endPos) { var startAngle = startDir.AbsoluteAngle(); var dir = endPos - startPos; var strangeAngle = dir.AbsoluteAngle(); var endAngle = strangeAngle + Mathf.PI + (strangeAngle - startAngle); var bezier = new Bezier3() { a = startPos, d = endPos, }; if (Vector3.Dot(startDir, dir) < 0) { NetSegment.CalculateMiddlePoints(bezier.a, dir, bezier.d, -dir, true, true, out bezier.b, out bezier.c); } else { NetSegment.CalculateMiddlePoints(bezier.a, startDir, bezier.d, endAngle.Direction(), true, true, out bezier.b, out bezier.c); } return(bezier); }
private static bool CheckOverlap(ushort ignoreParked, ref Bezier3 bezier, float offset, float length, out float minPos, out float maxPos) { throw new NotImplementedException("CheckOverlap is target of redirection and is not implemented."); }
// FIXME: Lines aren't always drawn void RenderUndergroundLane(Bezier3 bezier, Color color, float size) { Material mat = new Material(Shader.Find("Legacy Shaders/VertexLit")); mat.color = color; Mesh quadMesh = new Mesh(); Vector3 start = bezier.Position(0f); for (int i = 1; i <= 10; i++) { Vector3 end = bezier.Position(i / 10f); Vector3 normal = Vector3.up; //Vector3.Cross(start, end); Vector3 side = Vector3.Cross(normal, end - start); side.Normalize(); Vector3[] vertices = new Vector3[] { start + side * (size / 2f) + Vector3.up * 0.1f, start + side * (-size / 2f) + Vector3.up * 0.1f, end + side * (size / 2f) + Vector3.up * 0.1f, end + side * (-size / 2f) + Vector3.up * 0.1f, }; quadMesh.vertices = vertices; int[] tri = new int[] { 0, 1, 3, 3, 2, 0 }; quadMesh.triangles = tri; Vector3[] normals = new Vector3[] { normal, normal, normal, normal }; quadMesh.normals = normals; if (mat.SetPass(0)) Graphics.DrawMeshNow(quadMesh, Matrix4x4.identity); start = end; } }
private void _renderOverlayDraw(RenderManager.CameraInfo cameraInfo, Bezier3 bezier, Color color) { const float width = 8f; var exprEaCp0 = Singleton<ToolManager>.instance; exprEaCp0.m_drawCallData.m_overlayCalls = exprEaCp0.m_drawCallData.m_overlayCalls + 1; Singleton<RenderManager>.instance.OverlayEffect.DrawBezier(cameraInfo, color, bezier, width * 2f, width, width, -1f, 1280f, false, false); // 8 - small roads; 16 - big roads }
// from TransportLine public static bool UpdateMeshData(ref TransportLine transportLine, ushort lineID) { //return transportLine.UpdateMeshData(lineID); bool flag = true; int num = 0; int num2 = 0; int num3 = 0; float num4 = 0f; TransportManager instance = Singleton <TransportManager> .instance; NetManager instance2 = Singleton <NetManager> .instance; PathManager instance3 = Singleton <PathManager> .instance; ushort stops = transportLine.m_stops; ushort num5 = stops; int num6 = 0; while (num5 != 0) { ushort num7 = 0; for (int i = 0; i < 8; i++) { ushort segment = instance2.m_nodes.m_buffer[(int)num5].GetSegment(i); if (segment != 0 && instance2.m_segments.m_buffer[(int)segment].m_startNode == num5) { uint path = instance2.m_segments.m_buffer[(int)segment].m_path; if (path != 0u) { byte pathFindFlags = instance3.m_pathUnits.m_buffer[(int)((UIntPtr)path)].m_pathFindFlags; if ((pathFindFlags & 4) != 0) { if (!TransportLine.CalculatePathSegmentCount(path, ref num2, ref num3, ref num4)) { TransportInfo info = transportLine.Info; BusTransportLineAI.StartPathFind(segment, ref instance2.m_segments.m_buffer[(int)segment], info.m_netService, info.m_vehicleType, (transportLine.m_flags & TransportLine.Flags.Temporary) != TransportLine.Flags.None); flag = false; } } else if ((pathFindFlags & 8) == 0) { flag = false; } } num7 = instance2.m_segments.m_buffer[(int)segment].m_endNode; break; } } num++; num2++; num5 = num7; if (num5 == stops) { break; } if (!flag) { break; } if (++num6 >= 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } if (!flag) { return(flag); } RenderGroup.MeshData meshData = new RenderGroup.MeshData(); meshData.m_vertices = new Vector3[num2 * 8]; meshData.m_normals = new Vector3[num2 * 8]; meshData.m_tangents = new Vector4[num2 * 8]; meshData.m_uvs = new Vector2[num2 * 8]; meshData.m_uvs1 = new Vector2[num2 * 8]; meshData.m_colors = new Color32[num2 * 8]; meshData.m_triangles = new int[num2 * 30]; TransportManager.LineSegment[] array = new TransportManager.LineSegment[num]; Bezier3[] array2 = new Bezier3[num3]; int num8 = 0; int num9 = 0; int num10 = 0; float lengthScale = Mathf.Ceil(num4 / 64f) / num4; float num11 = 0f; num5 = stops; Vector3 vector = new Vector3(100000f, 100000f, 100000f); Vector3 vector2 = new Vector3(-100000f, -100000f, -100000f); num6 = 0; while (num5 != 0) { ushort num12 = 0; for (int j = 0; j < 8; j++) { ushort segment2 = instance2.m_nodes.m_buffer[(int)num5].GetSegment(j); if (segment2 != 0 && instance2.m_segments.m_buffer[(int)segment2].m_startNode == num5) { uint path2 = instance2.m_segments.m_buffer[(int)segment2].m_path; if (path2 != 0u && (instance3.m_pathUnits.m_buffer[(int)((UIntPtr)path2)].m_pathFindFlags & 4) != 0) { array[num8].m_curveStart = num10; Vector3 vector3; Vector3 vector4; TransportLine.FillPathSegments(path2, meshData, array2, ref num9, ref num10, ref num11, lengthScale, out vector3, out vector4); vector = Vector3.Min(vector, vector3); vector2 = Vector3.Max(vector2, vector4); array[num8].m_bounds.SetMinMax(vector3, vector4); array[num8].m_curveEnd = num10; } num12 = instance2.m_segments.m_buffer[(int)segment2].m_endNode; break; } } TransportLine.FillPathNode(instance2.m_nodes.m_buffer[(int)num5].m_position, meshData, num9); num8++; num9++; num5 = num12; if (num5 == stops) { break; } if (++num6 >= 32768) { CODebugBase <LogChannel> .Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } while (!Monitor.TryEnter(instance.m_lineMeshData, SimulationManager.SYNCHRONIZE_TIMEOUT)) { } try { instance.m_lineMeshData[(int)lineID] = meshData; instance.m_lineSegments[(int)lineID] = array; instance.m_lineCurves[(int)lineID] = array2; transportLine.m_bounds.SetMinMax(vector, vector2); } finally { Monitor.Exit(instance.m_lineMeshData); } return(flag); }
public static bool RenderInstancePrefix(Vehicle __instance, RenderManager.CameraInfo cameraInfo, ushort vehicleID, ref bool __result) { if ((__instance.m_flags & Flags.Spawned) == 0) { __result = false; return(false); } VehicleInfo info = __instance.Info; if (info == null) { __result = false; return(false); } uint targetFrame = __instance.GetTargetFrame(info, vehicleID); Vector3 framePosition = __instance.GetFramePosition(targetFrame - 32); float maxDistance = Mathf.Min(Mathf.Max(info.m_maxRenderDistance, RenderManager.LevelOfDetailFactor * 5000f), info.m_maxRenderDistance * (1f + cameraInfo.m_height * 0.0005f) + cameraInfo.m_height * 0.4f); if (!cameraInfo.CheckRenderDistance(framePosition, maxDistance)) { __result = false; return(false); } if (!cameraInfo.Intersect(framePosition, info.m_generatedInfo.m_size.z * 0.5f + 15f)) { __result = false; return(false); } Frame frameData = __instance.GetFrameData(targetFrame - 32); Frame frameData2 = __instance.GetFrameData(targetFrame - 16); float num = ((float)(double)(targetFrame & 0xF) + Singleton <SimulationManager> .instance.m_referenceTimer) * 0.0625f; bool flag = frameData2.m_underground && frameData.m_underground; bool flag2 = frameData2.m_insideBuilding && frameData.m_insideBuilding; bool flag3 = frameData2.m_transition || frameData.m_transition; if (flag2 && !flag3) { __result = false; return(false); } if (flag && !flag3) { if ((cameraInfo.m_layerMask & (1 << Singleton <VehicleManager> .instance.m_undergroundLayer)) == 0) { __result = false; return(false); } } else if ((cameraInfo.m_layerMask & (1 << info.m_prefabDataLayer)) == 0) { __result = false; return(false); } Bezier3 bezier = default(Bezier3); bezier.a = frameData.m_position; bezier.b = frameData.m_position + frameData.m_velocity * 0.333f; bezier.c = frameData2.m_position - frameData2.m_velocity * 0.333f; bezier.d = frameData2.m_position; Vector3 position = bezier.Position(num); Bezier3 bezier2 = default(Bezier3); bezier2.a = frameData.m_swayPosition; bezier2.b = frameData.m_swayPosition + frameData.m_swayVelocity * 0.333f; bezier2.c = frameData2.m_swayPosition - frameData2.m_swayVelocity * 0.333f; bezier2.d = frameData2.m_swayPosition; Vector3 swayPosition = bezier2.Position(num); swayPosition.x *= info.m_leanMultiplier / Mathf.Max(1f, info.m_generatedInfo.m_wheelGauge); swayPosition.z *= info.m_nodMultiplier / Mathf.Max(1f, info.m_generatedInfo.m_wheelBase); Vector4 lightState = (!(num >= 0.5f)) ? frameData.m_lightIntensity : frameData2.m_lightIntensity; Quaternion rotation = Quaternion.Lerp(frameData.m_rotation, frameData2.m_rotation, num); Color color = info.m_vehicleAI.GetColor(vehicleID, ref __instance, Singleton <InfoManager> .instance.CurrentMode); color.a = ((!(num >= 0.5f)) ? frameData.m_blinkState : frameData2.m_blinkState); Vector4 tyrePosition = default(Vector4); tyrePosition.x = frameData.m_steerAngle + (frameData2.m_steerAngle - frameData.m_steerAngle) * num; tyrePosition.y = frameData.m_travelDistance + (frameData2.m_travelDistance - frameData.m_travelDistance) * num; tyrePosition.z = 0f; tyrePosition.w = 0f; Vector3 velocity = Vector3.Lerp(frameData.m_velocity, frameData2.m_velocity, num) * 3.75f; float acceleration = frameData2.m_velocity.magnitude - frameData.m_velocity.magnitude; InstanceID id = default(InstanceID); id.Vehicle = vehicleID; #if UseTask Patcher.Dispatcher.Add(() => Vehicle.RenderInstance(cameraInfo, info, position, rotation, swayPosition, lightState, tyrePosition, velocity, acceleration, color, __instance.m_flags, ~(1 << (int)__instance.m_gateIndex), id, flag || flag3, !flag || flag3)); #else Vehicle.RenderInstance(cameraInfo, info, position, rotation, swayPosition, lightState, tyrePosition, velocity, acceleration, color, __instance.m_flags, ~(1 << (int)__instance.m_gateIndex), id, flag || flag3, !flag || flag3); #endif __result = true; return(false); }
public static bool RenderInstancePrefix(CitizenInstance __instance, RenderManager.CameraInfo cameraInfo, ushort instanceID, ref bool __result) { if ((__instance.m_flags & Flags.Character) == 0) { __result = false; return(false); } CitizenInfo info = __instance.Info; if (info == null) { __result = false; return(false); } uint num = (uint)(instanceID << 4) / 65536u; uint num2 = Singleton <SimulationManager> .instance.m_referenceFrameIndex - num; Frame frameData = __instance.GetFrameData(num2 - 32); float maxDistance = Mathf.Min(RenderManager.LevelOfDetailFactor * 800f, info.m_maxRenderDistance + cameraInfo.m_height * 0.5f); if (!cameraInfo.CheckRenderDistance(frameData.m_position, maxDistance)) { __result = false; return(false); } if (!cameraInfo.Intersect(frameData.m_position, 10f)) { __result = false; return(false); } Frame frameData2 = __instance.GetFrameData(num2 - 16); float t = ((float)(double)(num2 & 0xF) + Singleton <SimulationManager> .instance.m_referenceTimer) * 0.0625f; bool flag = frameData2.m_underground && frameData.m_underground; bool flag2 = frameData2.m_insideBuilding && frameData.m_insideBuilding; bool flag3 = frameData2.m_transition || frameData.m_transition; if ((flag2 && !flag3) || (flag && !flag3 && (cameraInfo.m_layerMask & (1 << Singleton <CitizenManager> .instance.m_undergroundLayer)) == 0)) { __result = false; return(false); } Bezier3 bezier = default(Bezier3); bezier.a = frameData.m_position; bezier.b = frameData.m_position + frameData.m_velocity * 0.333f; bezier.c = frameData2.m_position - frameData2.m_velocity * 0.333f; bezier.d = frameData2.m_position; Vector3 vector = bezier.Position(t); Quaternion quaternion = Quaternion.Lerp(frameData.m_rotation, frameData2.m_rotation, t); Color color = info.m_citizenAI.GetColor(instanceID, ref __instance, Singleton <InfoManager> .instance.CurrentMode); var action = new Action(() => { if (cameraInfo.CheckRenderDistance(vector, info.m_lodRenderDistance)) { InstanceID empty = InstanceID.Empty; empty.CitizenInstance = instanceID; CitizenInfo citizenInfo = info.ObtainPrefabInstance <CitizenInfo>(empty, 255); if (citizenInfo != null) { Vector3 velocity = Vector3.Lerp(frameData.m_velocity, frameData2.m_velocity, t); citizenInfo.m_citizenAI.SetRenderParameters(cameraInfo, instanceID, ref __instance, vector, quaternion, velocity, color, (flag || flag3) && (cameraInfo.m_layerMask & (1 << Singleton <CitizenManager> .instance.m_undergroundLayer)) != 0); return; } } if (flag || flag3) { info.m_undergroundLodLocations[info.m_undergroundLodCount].SetTRS(vector, quaternion, Vector3.one); info.m_undergroundLodColors[info.m_undergroundLodCount] = color.linear; info.m_undergroundLodMin = Vector3.Min(info.m_undergroundLodMin, vector); info.m_undergroundLodMax = Vector3.Max(info.m_undergroundLodMax, vector); if (++info.m_undergroundLodCount == info.m_undergroundLodLocations.Length) { RenderUndergroundLod(cameraInfo, info); } } if (!flag || flag3) { info.m_lodLocations[info.m_lodCount].SetTRS(vector, quaternion, Vector3.one); info.m_lodColors[info.m_lodCount] = color.linear; info.m_lodMin = Vector3.Min(info.m_lodMin, vector); info.m_lodMax = Vector3.Max(info.m_lodMax, vector); if (++info.m_lodCount == info.m_lodLocations.Length) { RenderLod(cameraInfo, info); } } }); #if UseTask Patcher.Dispatcher.Add(action); #else action.Invoke(); #endif __result = true; return(false); }
public BezierBounds(Bezier3 bezier, float size) { Bezier = bezier; Size = size; CalculateBounds(); }
public static void CalculateCorner(NetInfo info, Vector3 startPos, Vector3 endPos, Vector3 startDir, Vector3 endDir, NetInfo extraInfo1, Vector3 extraEndPos1, Vector3 extraStartDir1, Vector3 extraEndDir1, NetInfo extraInfo2, Vector3 extraEndPos2, Vector3 extraStartDir2, Vector3 extraEndDir2, ushort ignoreSegmentID, ushort startNodeID, bool heightOffset, bool leftSide, out Vector3 cornerPos, out Vector3 cornerDirection, out bool smooth) { //add null check //begin mod if (info == null) { cornerPos = new Vector3(); cornerDirection = new Vector3(); smooth = false; return; } //end mod NetManager instance = Singleton <NetManager> .instance; Bezier3 bezier1 = new Bezier3(); Bezier3 bezier2 = new Bezier3(); NetNode.Flags flags = NetNode.Flags.End; ushort num1 = 0; if ((int)startNodeID != 0) { flags = instance.m_nodes.m_buffer[(int)startNodeID].m_flags; num1 = instance.m_nodes.m_buffer[(int)startNodeID].m_building; } cornerDirection = startDir; float num2 = !leftSide ? -info.m_halfWidth : info.m_halfWidth; smooth = (flags & NetNode.Flags.Middle) != NetNode.Flags.None; if (extraInfo1 != null) { flags = (flags & NetNode.Flags.End) == NetNode.Flags.None || !info.IsCombatible(extraInfo1) || extraInfo2 != null ? flags & ~(NetNode.Flags.Middle | NetNode.Flags.Bend) | NetNode.Flags.Junction : ((double)startDir.x * (double)extraStartDir1.x + (double)startDir.z * (double)extraStartDir1.z >= -0.999000012874603 ? flags & ~NetNode.Flags.End | NetNode.Flags.Bend : flags & ~NetNode.Flags.End | NetNode.Flags.Middle); } if ((flags & NetNode.Flags.Middle) != NetNode.Flags.None) { int num3 = extraInfo1 == null ? 0 : -1; int num4 = (int)startNodeID == 0 ? 0 : 8; for (int index = num3; index < num4; ++index) { Vector3 vector3; if (index == -1) { vector3 = extraStartDir1; } else { ushort segment = instance.m_nodes.m_buffer[(int)startNodeID].GetSegment(index); if ((int)segment != 0 && (int)segment != (int)ignoreSegmentID) { ushort num5 = instance.m_segments.m_buffer[(int)segment].m_startNode; vector3 = (int)startNodeID == (int)num5 ? instance.m_segments.m_buffer[(int)segment].m_startDirection : instance.m_segments.m_buffer[(int)segment].m_endDirection; } else { continue; } } cornerDirection = VectorUtils.NormalizeXZ(cornerDirection - vector3); break; } } Vector3 lhs = Vector3.Cross(cornerDirection, Vector3.up).normalized; if (info.m_twistSegmentEnds && (int)num1 != 0) { float f = Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)num1].m_angle; Vector3 rhs = new Vector3(Mathf.Cos(f), 0.0f, Mathf.Sin(f)); lhs = (double)Vector3.Dot(lhs, rhs) < 0.0 ? -rhs : rhs; } bezier1.a = startPos + lhs * num2; bezier2.a = startPos - lhs * num2; cornerPos = bezier1.a; if ((flags & NetNode.Flags.Junction) != NetNode.Flags.None && info.m_clipSegmentEnds || (flags & (NetNode.Flags.Bend | NetNode.Flags.Outside)) != NetNode.Flags.None) { Vector3 vector3_1 = endDir; Vector3 normalized1 = Vector3.Cross(vector3_1, Vector3.up).normalized; bezier1.d = endPos - normalized1 * num2; bezier2.d = endPos + normalized1 * num2; NetSegment.CalculateMiddlePoints(bezier1.a, cornerDirection, bezier1.d, vector3_1, false, false, out bezier1.b, out bezier1.c); NetSegment.CalculateMiddlePoints(bezier2.a, cornerDirection, bezier2.d, vector3_1, false, false, out bezier2.b, out bezier2.c); Bezier2 bezier2_1 = Bezier2.XZ(bezier1); Bezier2 bezier2_2 = Bezier2.XZ(bezier2); float a1 = -1f; float num3 = -1f; bool flag = false; int num4 = extraInfo1 == null ? 0 : (extraInfo2 == null ? -1 : -2); int num5 = (int)startNodeID == 0 ? 0 : 8; float a2 = info.m_halfWidth * 0.5f; for (int index = num4; index < num5; ++index) { NetInfo netInfo; if (index == -2) { netInfo = extraInfo2; Vector3 vector3_2 = extraEndPos2; Vector3 vector3_3 = extraEndDir2; if (vector3_2 == endPos && vector3_3 == endDir) { continue; } } else if (index == -1) { netInfo = extraInfo1; Vector3 vector3_2 = extraEndPos1; Vector3 vector3_3 = extraEndDir1; if (vector3_2 == endPos && vector3_3 == endDir) { continue; } } else { ushort segment = instance.m_nodes.m_buffer[(int)startNodeID].GetSegment(index); if ((int)segment != 0 && (int)segment != (int)ignoreSegmentID) { netInfo = instance.m_segments.m_buffer[(int)segment].Info; } else { continue; } } if (netInfo != null) { a2 = Mathf.Max(a2, netInfo.m_halfWidth * 0.5f); } } for (int index = num4; index < num5; ++index) { NetInfo netInfo; Vector3 vector3_2; Vector3 vector3_3; Vector3 vector3_4; if (index == -2) { netInfo = extraInfo2; vector3_2 = extraEndPos2; vector3_3 = extraStartDir2; vector3_4 = extraEndDir2; if (vector3_2 == endPos && vector3_4 == endDir) { continue; } } else if (index == -1) { netInfo = extraInfo1; vector3_2 = extraEndPos1; vector3_3 = extraStartDir1; vector3_4 = extraEndDir1; if (vector3_2 == endPos && vector3_4 == endDir) { continue; } } else { ushort segment = instance.m_nodes.m_buffer[(int)startNodeID].GetSegment(index); if ((int)segment != 0 && (int)segment != (int)ignoreSegmentID) { ushort num6 = instance.m_segments.m_buffer[(int)segment].m_startNode; ushort num7 = instance.m_segments.m_buffer[(int)segment].m_endNode; vector3_3 = instance.m_segments.m_buffer[(int)segment].m_startDirection; vector3_4 = instance.m_segments.m_buffer[(int)segment].m_endDirection; if ((int)startNodeID != (int)num6) { num7 = num6; Vector3 vector3_5 = vector3_3; vector3_3 = vector3_4; vector3_4 = vector3_5; } netInfo = instance.m_segments.m_buffer[(int)segment].Info; vector3_2 = instance.m_nodes.m_buffer[(int)num7].m_position; } else { continue; } } if (netInfo != null) { if ((double)vector3_3.z * (double)cornerDirection.x - (double)vector3_3.x * (double)cornerDirection.z > 0.0 == leftSide) { Bezier3 bezier3 = new Bezier3(); float num6 = Mathf.Max(a2, netInfo.m_halfWidth); if (!leftSide) { num6 = -num6; } Vector3 normalized2 = Vector3.Cross(vector3_3, Vector3.up).normalized; bezier3.a = startPos - normalized2 * num6; Vector3 normalized3 = Vector3.Cross(vector3_4, Vector3.up).normalized; bezier3.d = vector3_2 + normalized3 * num6; NetSegment.CalculateMiddlePoints(bezier3.a, vector3_3, bezier3.d, vector3_4, false, false, out bezier3.b, out bezier3.c); Bezier2 b2 = Bezier2.XZ(bezier3); float t1; float t2; if (bezier2_1.Intersect(b2, out t1, out t2, 6)) { a1 = Mathf.Max(a1, t1); } else if (bezier2_1.Intersect(b2.a, b2.a - VectorUtils.XZ(vector3_3) * 16f, out t1, out t2, 6)) { a1 = Mathf.Max(a1, t1); } else if (b2.Intersect(bezier2_1.d + (bezier2_1.d - bezier2_2.d) * 0.01f, bezier2_2.d, out t1, out t2, 6)) { a1 = Mathf.Max(a1, 1f); } if ((double)cornerDirection.x * (double)vector3_3.x + (double)cornerDirection.z * (double)vector3_3.z >= -0.75) { flag = true; } } else { Bezier3 bezier3 = new Bezier3(); float num6 = (float)((double)cornerDirection.x * (double)vector3_3.x + (double)cornerDirection.z * (double)vector3_3.z); if ((double)num6 >= 0.0) { vector3_3.x -= (float)((double)cornerDirection.x * (double)num6 * 2.0); vector3_3.z -= (float)((double)cornerDirection.z * (double)num6 * 2.0); } float num7 = Mathf.Max(a2, netInfo.m_halfWidth); if (!leftSide) { num7 = -num7; } Vector3 normalized2 = Vector3.Cross(vector3_3, Vector3.up).normalized; bezier3.a = startPos + normalized2 * num7; Vector3 normalized3 = Vector3.Cross(vector3_4, Vector3.up).normalized; bezier3.d = vector3_2 - normalized3 * num7; NetSegment.CalculateMiddlePoints(bezier3.a, vector3_3, bezier3.d, vector3_4, false, false, out bezier3.b, out bezier3.c); Bezier2 b2 = Bezier2.XZ(bezier3); float t1; float t2; if (bezier2_2.Intersect(b2, out t1, out t2, 6)) { num3 = Mathf.Max(num3, t1); } else if (bezier2_2.Intersect(b2.a, b2.a - VectorUtils.XZ(vector3_3) * 16f, out t1, out t2, 6)) { num3 = Mathf.Max(num3, t1); } else if (b2.Intersect(bezier2_1.d, bezier2_2.d + (bezier2_2.d - bezier2_1.d) * 0.01f, out t1, out t2, 6)) { num3 = Mathf.Max(num3, 1f); } } } } if ((flags & NetNode.Flags.Junction) != NetNode.Flags.None) { if (!flag) { a1 = Mathf.Max(a1, num3); } } else if ((flags & NetNode.Flags.Bend) != NetNode.Flags.None && !flag) { a1 = Mathf.Max(a1, num3); } float num8; if ((flags & NetNode.Flags.Outside) != NetNode.Flags.None) { float num6 = 8640f; Vector2 vector2_1 = new Vector2(-num6, -num6); Vector2 vector2_2 = new Vector2(-num6, num6); Vector2 vector2_3 = new Vector2(num6, num6); Vector2 vector2_4 = new Vector2(num6, -num6); float t1; float t2; if (bezier2_1.Intersect(vector2_1, vector2_2, out t1, out t2, 6)) { a1 = Mathf.Max(a1, t1); } if (bezier2_1.Intersect(vector2_2, vector2_3, out t1, out t2, 6)) { a1 = Mathf.Max(a1, t1); } if (bezier2_1.Intersect(vector2_3, vector2_4, out t1, out t2, 6)) { a1 = Mathf.Max(a1, t1); } if (bezier2_1.Intersect(vector2_4, vector2_1, out t1, out t2, 6)) { a1 = Mathf.Max(a1, t1); } num8 = Mathf.Clamp01(a1); } else { if ((double)a1 < 0.0) { a1 = (double)info.m_halfWidth >= 4.0 ? bezier2_1.Travel(0.0f, 8f) : 0.0f; } float num6 = Mathf.Clamp01(a1); float num7 = VectorUtils.LengthXZ(bezier1.Position(num6) - bezier1.a); num8 = bezier2_1.Travel(num6, Mathf.Max(info.m_minCornerOffset - num7, 2f)); if (info.m_straightSegmentEnds) { if ((double)num3 < 0.0) { num3 = (double)info.m_halfWidth >= 4.0 ? bezier2_2.Travel(0.0f, 8f) : 0.0f; } float num9 = Mathf.Clamp01(num3); float num10 = VectorUtils.LengthXZ(bezier2.Position(num9) - bezier2.a); float b = bezier2_2.Travel(num9, Mathf.Max(info.m_minCornerOffset - num10, 2f)); num8 = Mathf.Max(num8, b); } } float num11 = cornerDirection.y; cornerDirection = bezier1.Tangent(num8); cornerDirection.y = 0.0f; cornerDirection.Normalize(); if (!info.m_flatJunctions) { cornerDirection.y = num11; } cornerPos = bezier1.Position(num8); cornerPos.y = startPos.y; } if (!heightOffset || (int)startNodeID == 0) { return; } cornerPos.y += (float)instance.m_nodes.m_buffer[(int)startNodeID].m_heightOffset * (1f / 64f); }
public static void Render(this Bezier3 bezier, RenderManager.CameraInfo cameraInfo, Color color, float hw, bool alphaBlend = false) { bezier.Render(cameraInfo, color, hw, hw, hw, alphaBlend); }
private OSMWay CreateWay(int index, NetSegment segment) { OSMWay returnWay = null; NetSegment.Flags segmentFlags = segment.m_flags; NetManager netManager = Singleton<NetManager>.instance; List<OSMWayND> wayPaths = new List<OSMWayND>(); List<OSMWayTag> wayTags; ushort startNodeId = segment.m_startNode, endNodeId = segment.m_endNode; if(startNodeId != 0 && endNodeId != 0) { Vector3 startNodeDirection = segment.m_startDirection; Vector3 endNodeDirection = segment.m_endDirection; if(segmentFlags.IsFlagSet(NetSegment.Flags.Invert)) { startNodeId = segment.m_endNode; endNodeId = segment.m_startNode; startNodeDirection = segment.m_endDirection; endNodeDirection = segment.m_startDirection; } NetNode startNode = netManager.m_nodes.m_buffer[startNodeId]; NetNode endNode = netManager.m_nodes.m_buffer[endNodeId]; Vector3 startNodePosition = startNode.m_position; Vector3 endNodePosition = endNode.m_position; wayPaths.Add(new OSMWayND { @ref = startNodeId }); if (Vector3.Angle(startNodeDirection, -endNodeDirection) > 3f) { Vector3 midPointA = Vector3.zero, midPointB = Vector3.zero; NetSegment.CalculateMiddlePoints(startNodePosition, startNodeDirection, endNodePosition, endNodeDirection, false, false, out midPointA, out midPointB); Bezier3 bezier = new Bezier3(startNodePosition, midPointA, midPointB, endNodePosition); osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.25f))); osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.5f))); osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.75f))); wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 3 }); wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 2 }); wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 1 }); } wayPaths.Add(new OSMWayND { @ref = endNodeId }); if(Tagger.CreateWayTags(segment, out wayTags)) { returnWay = new OSMWay { changeset = 50000000, id = (uint)index, timestamp = DateTime.Now, user = "******", nd = wayPaths.ToArray(), tag = wayTags.ToArray(), version = 1 }; } else { UniqueLogger.AddLog("Road names missing from search", segment.Info.name, ""); } } return returnWay; }
// from TransportLine public static bool UpdateMeshData(ref TransportLine transportLine, ushort lineID) { bool flag = true; int num = 0; int num2 = 0; int num3 = 0; float num4 = 0f; TransportManager instance = Singleton<TransportManager>.instance; NetManager instance2 = Singleton<NetManager>.instance; PathManager instance3 = Singleton<PathManager>.instance; ushort stops = transportLine.m_stops; ushort num5 = stops; int num6 = 0; while (num5 != 0) { ushort num7 = 0; for (int i = 0; i < 8; i++) { ushort segment = instance2.m_nodes.m_buffer[(int)num5].GetSegment(i); if (segment != 0 && instance2.m_segments.m_buffer[(int)segment].m_startNode == num5) { uint path = instance2.m_segments.m_buffer[(int)segment].m_path; if (path != 0u) { byte pathFindFlags = instance3.m_pathUnits.m_buffer[(int)((UIntPtr)path)].m_pathFindFlags; if ((pathFindFlags & 4) != 0) { if (!TransportLine.CalculatePathSegmentCount(path, ref num2, ref num3, ref num4)) { TransportInfo info = transportLine.Info; BusTransportLineAI.StartPathFind(segment, ref instance2.m_segments.m_buffer[(int)segment], info.m_netService, info.m_vehicleType, (transportLine.m_flags & TransportLine.Flags.Temporary) != TransportLine.Flags.None); flag = false; } } else if ((pathFindFlags & 8) == 0) { flag = false; } } num7 = instance2.m_segments.m_buffer[(int)segment].m_endNode; break; } } num++; num2++; num5 = num7; if (num5 == stops) { break; } if (!flag) { break; } if (++num6 >= 32768) { CODebugBase<LogChannel>.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } if (!flag) { return flag; } RenderGroup.MeshData meshData = new RenderGroup.MeshData(); meshData.m_vertices = new Vector3[num2 * 8]; meshData.m_normals = new Vector3[num2 * 8]; meshData.m_tangents = new Vector4[num2 * 8]; meshData.m_uvs = new Vector2[num2 * 8]; meshData.m_uvs1 = new Vector2[num2 * 8]; meshData.m_colors = new Color32[num2 * 8]; meshData.m_triangles = new int[num2 * 30]; TransportManager.LineSegment[] array = new TransportManager.LineSegment[num]; Bezier3[] array2 = new Bezier3[num3]; int num8 = 0; int num9 = 0; int num10 = 0; float lengthScale = Mathf.Ceil(num4 / 64f) / num4; float num11 = 0f; num5 = stops; Vector3 vector = new Vector3(100000f, 100000f, 100000f); Vector3 vector2 = new Vector3(-100000f, -100000f, -100000f); num6 = 0; while (num5 != 0) { ushort num12 = 0; for (int j = 0; j < 8; j++) { ushort segment2 = instance2.m_nodes.m_buffer[(int)num5].GetSegment(j); if (segment2 != 0 && instance2.m_segments.m_buffer[(int)segment2].m_startNode == num5) { uint path2 = instance2.m_segments.m_buffer[(int)segment2].m_path; if (path2 != 0u && (instance3.m_pathUnits.m_buffer[(int)((UIntPtr)path2)].m_pathFindFlags & 4) != 0) { array[num8].m_curveStart = num10; Vector3 vector3; Vector3 vector4; TransportLine.FillPathSegments(path2, meshData, array2, ref num9, ref num10, ref num11, lengthScale, out vector3, out vector4); vector = Vector3.Min(vector, vector3); vector2 = Vector3.Max(vector2, vector4); array[num8].m_bounds.SetMinMax(vector3, vector4); array[num8].m_curveEnd = num10; } num12 = instance2.m_segments.m_buffer[(int)segment2].m_endNode; break; } } TransportLine.FillPathNode(instance2.m_nodes.m_buffer[(int)num5].m_position, meshData, num9); num8++; num9++; num5 = num12; if (num5 == stops) { break; } if (++num6 >= 32768) { CODebugBase<LogChannel>.Error(LogChannel.Core, "Invalid list detected!\n" + Environment.StackTrace); break; } } while (!Monitor.TryEnter(instance.m_lineMeshData, SimulationManager.SYNCHRONIZE_TIMEOUT)) { } try { instance.m_lineMeshData[(int)lineID] = meshData; instance.m_lineSegments[(int)lineID] = array; instance.m_lineCurves[(int)lineID] = array2; transportLine.m_bounds.SetMinMax(vector, vector2); } finally { Monitor.Exit(instance.m_lineMeshData); } return flag; }
// Essential Tool Functions protected override void OnToolUpdate() { base.OnToolUpdate(); Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastInput input = new RaycastInput(ray, Camera.main.farClipPlane); input.m_ignoreSegmentFlags = NetSegment.Flags.None; input.m_ignoreNodeFlags = NetNode.Flags.All; input.m_ignoreParkFlags = DistrictPark.Flags.All; input.m_ignorePropFlags = PropInstance.Flags.All; input.m_ignoreTreeFlags = TreeInstance.Flags.All; input.m_ignoreCitizenFlags = CitizenInstance.Flags.All; input.m_ignoreVehicleFlags = Vehicle.Flags.Created; input.m_ignoreBuildingFlags = Building.Flags.All; input.m_ignoreDisasterFlags = DisasterData.Flags.All; input.m_ignoreTransportFlags = TransportLine.Flags.All; input.m_ignoreParkedVehicleFlags = VehicleParked.Flags.All; input.m_ignoreTerrain = true; RayCast(input, out RaycastOutput output); m_hover = output.m_netSegment; if (m_newSeg1 != 0 && m_newSeg2 != 0) { NetSegment s1 = GetSegment(m_newSeg1); NetSegment s2 = GetSegment(m_newSeg2); NetNode a = GetNode(s1.m_startNode); NetNode b = GetNode(s2.m_endNode); NetNode c = GetNode(s2.m_startNode); if ((a.m_problems | b.m_problems | c.m_problems) == Notification.Problem.RoadNotConnected) { InvertSegment(m_newSeg1); InvertSegment(m_newSeg2); } m_newSeg1 = 0; m_newSeg2 = 0; enabled = false; UIView.Find("E3A").Unfocus(); UIView.Find("E3B").Unfocus(); mode = 0; ToolsModifierControl.SetTool <DefaultTool>(); } if (m_hover != 0) { if (mode == 1) { //Snap to location on segment Bezier3 bezierx = new Bezier3(); NetSegment seg = GetSegment(m_hover); bezierx.a = NetManager.instance.m_nodes.m_buffer[seg.m_startNode].m_position; bezierx.d = NetManager.instance.m_nodes.m_buffer[seg.m_endNode].m_position; bool smoothStart = (Singleton <NetManager> .instance.m_nodes.m_buffer[seg.m_startNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; bool smoothEnd = (Singleton <NetManager> .instance.m_nodes.m_buffer[seg.m_endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; NetSegment.CalculateMiddlePoints(bezierx.a, seg.m_startDirection, bezierx.d, seg.m_endDirection, smoothStart, smoothEnd, out Vector3 b, out Vector3 c); bezierx.b = b; bezierx.c = c; float iterations = 40f; // Could be anywhere 0-100. Maybe configurable at a later point. float time = 0f; float shortestDistance = 1000f; for (float i = 0f; i < iterations; i++) { float ttime = (i + 1f) / iterations; Vector3 testPoint = bezierx.Position(ttime); float distance = Vector3.Distance(testPoint, output.m_hitPos); if (distance < shortestDistance) { shortestDistance = distance; time = ttime; m_snapFakeNode = testPoint; } } // If x < 0.1f or x > 0.9f, display a warning telling people the segment may start to glitch out? perhaps over a certain length? <0.1m? m_errors = time * seg.m_averageLength < 3.0f || seg.m_averageLength - (time * seg.m_averageLength) < 3.0f; pulsating++; if (Input.GetMouseButtonUp(0) && Mathf.Abs(0.5f - time) < 0.5) { if (!NodeInsertion(m_hover, time)) { Debug.LogError(":("); return; } } } else { if (Input.GetMouseButtonUp(0)) { if (m_seg1 == 0) { m_seg1 = m_hover; } else { m_seg2 = m_hover; } } else if (Input.GetMouseButtonUp(1)) { if (m_seg2 != 0) { m_seg2 = 0; } else if (m_seg1 != 0) { m_seg1 = 0; } } } } if (Input.GetKeyUp(KeyCode.Return)) { if (!Intersection(m_seg1, m_seg2)) { Debug.LogError(":("); } enabled = false; ToolsModifierControl.SetTool <DefaultTool>(); m_seg1 = 0; m_seg2 = 0; UIView.Find("E3A").Unfocus(); UIView.Find("E3B").Unfocus(); } }
public bool Intersection(ushort segment1, ushort segment2) { Bezier3 bezier = new Bezier3(); Bezier3 bezier2 = new Bezier3(); NetSegment s1 = GetSegment(segment1); NetSegment s2 = GetSegment(segment2); // Turn the segment data into a Bezier2 for easier calculations supported by the game bezier.a = NetManager.instance.m_nodes.m_buffer[s1.m_startNode].m_position; bezier.d = NetManager.instance.m_nodes.m_buffer[s1.m_endNode].m_position; bool smoothStart = (Singleton <NetManager> .instance.m_nodes.m_buffer[s1.m_startNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; bool smoothEnd = (Singleton <NetManager> .instance.m_nodes.m_buffer[s1.m_endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; NetSegment.CalculateMiddlePoints(bezier.a, s1.m_startDirection, bezier.d, s1.m_endDirection, smoothStart, smoothEnd, out Vector3 b, out Vector3 c); bezier.b = b; bezier.c = c; Bezier2 xz = Bezier2.XZ(bezier); // Second segment: bezier2.a = NetManager.instance.m_nodes.m_buffer[s2.m_startNode].m_position; bezier2.d = NetManager.instance.m_nodes.m_buffer[s2.m_endNode].m_position; smoothStart = (Singleton <NetManager> .instance.m_nodes.m_buffer[s2.m_startNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; smoothEnd = (Singleton <NetManager> .instance.m_nodes.m_buffer[s2.m_endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; NetSegment.CalculateMiddlePoints(bezier2.a, s2.m_startDirection, bezier2.d, s2.m_endDirection, smoothStart, smoothEnd, out Vector3 _b, out Vector3 _c); bezier2.b = _b; bezier2.c = _c; Bezier2 xz2 = Bezier2.XZ(bezier2); if (!xz.Intersect(xz2, out float t1, out float t2, 8)) { return(ThrowError("Could not find an intersection between these two roads. Remember, T-junctions do not count as intersections. Try extending the segment, creating the intersection, and deleting the excess.")); } Vector3 intersectionPoint = bezier.Position(t1); ushort seg1ls = s1.m_startNode; Vector3 seg1lsd = s1.m_startDirection; Vector3 seg1led = -bezier.Tangent(t1).normalized; ushort seg1rs = s1.m_endNode; Vector3 seg1rsd = s1.m_endDirection; Vector3 seg1red = bezier.Tangent(t1).normalized; ushort seg2ls = s2.m_startNode; Vector3 seg2lsd = s2.m_startDirection; Vector3 seg2led = -bezier2.Tangent(t2).normalized; ushort seg2rs = s2.m_endNode; Vector3 seg2rsd = s2.m_endDirection; Vector3 seg2red = bezier2.Tangent(t2).normalized; // place segments and nodes Manager.CreateNode(out ushort intersectionNode, ref SimulationManager.instance.m_randomizer, s1.Info, intersectionPoint, SimulationManager.instance.m_currentBuildIndex); Manager.CreateSegment(out ushort seg1, ref SimulationManager.instance.m_randomizer, s1.Info, seg1ls, intersectionNode, seg1lsd, seg1led, SimulationManager.instance.m_currentBuildIndex, SimulationManager.instance.m_currentBuildIndex, false); Manager.CreateSegment(out ushort seg2, ref SimulationManager.instance.m_randomizer, s1.Info, seg1rs, intersectionNode, seg1rsd, seg1red, SimulationManager.instance.m_currentBuildIndex, SimulationManager.instance.m_currentBuildIndex, false); Manager.CreateSegment(out ushort seg3, ref SimulationManager.instance.m_randomizer, s2.Info, seg2ls, intersectionNode, seg2lsd, seg2led, SimulationManager.instance.m_currentBuildIndex, SimulationManager.instance.m_currentBuildIndex, false); Manager.CreateSegment(out ushort seg4, ref SimulationManager.instance.m_randomizer, s2.Info, seg2rs, intersectionNode, seg2rsd, seg2red, SimulationManager.instance.m_currentBuildIndex, SimulationManager.instance.m_currentBuildIndex, false); List <ushort> newSegments = new List <ushort>(); newSegments.Add(seg1); newSegments.Add(seg2); newSegments.Add(seg3); newSegments.Add(seg4); if (seg1 == 0 || seg2 == 0 || seg3 == 0 || seg4 == 0) { return(Revert(newSegments, intersectionNode)); } Manager.ReleaseSegment(segment1, true); Manager.ReleaseSegment(segment2, true); FixTJunctions(newSegments); return(true); }
public static void RenderBezier(RenderManager.CameraInfo cameraInfo, Color color, Bezier3 bezier, float width = 0.2f, bool cut = false, bool alphaBlend = true) => RenderManager.OverlayEffect.DrawBezier(cameraInfo, color, bezier, width, cut ? width / 2 : 0f, cut ? width / 2 : 0f, -1f, 1280f, false, alphaBlend);
public static StopPointDescriptorLanes[] MapStopPoints(BuildingInfo buildingInfo, float thresold) { var result = new List <StopPointDescriptorLanes>(); if (buildingInfo?.m_paths != null) { foreach (BuildingInfo.PathInfo path in buildingInfo.m_paths) { if (path.m_nodes.Length < 2) { continue; } Vector3 position = path.m_nodes[0]; Vector3 position2 = path.m_nodes[1]; position.z *= -1; position2.z *= -1; Vector3 directionPath = Quaternion.AngleAxis(90, Vector3.up) * (position2 - position).normalized; foreach (NetInfo.Lane refLane in path.m_netInfo.m_lanes) { if (refLane.m_stopType == VehicleInfo.VehicleType.None) { continue; } NetInfo.Lane lane = FindNearestVehicleStopLane(path.m_netInfo.m_lanes, refLane, out ushort laneId); if (lane == null) { continue; } LogUtils.DoLog($"[{buildingInfo}] pos + dir = ({position} {position2} + {directionPath})"); Vector3 lanePos = position + (lane.m_position / 2 * directionPath) + new Vector3(0, lane.m_verticalOffset); Vector3 lanePos2 = position2 + (lane.m_position / 2 * directionPath) + new Vector3(0, lane.m_verticalOffset); Vector3 b3, c; if (path.m_curveTargets == null || path.m_curveTargets.Length == 0) { NetSegment.CalculateMiddlePoints(lanePos, Vector3.zero, lanePos2, Vector3.zero, true, true, out b3, out c); } else { GetMiddlePointsFor(path, out b3, out c); LogUtils.DoLog($"[{buildingInfo}] GetMiddlePointsFor path = ({b3} {c})"); b3 += (lane.m_position * directionPath) + new Vector3(0, lane.m_verticalOffset); c += (lane.m_position * directionPath) + new Vector3(0, lane.m_verticalOffset); b3.y = c.y = (lanePos.y + lanePos2.y) / 2; } var refBezier = new Bezier3(lanePos, b3, c, lanePos2); LogUtils.DoLog($"[{buildingInfo}]refBezier = {refBezier} ({lanePos} {b3} {c} {lanePos2})"); Vector3 positionR = refBezier.Position(m_defaultStopOffset); Vector3 direction = refBezier.Tangent(m_defaultStopOffset); LogUtils.DoLog($"[{buildingInfo}]1positionR = {positionR}; direction = {direction}"); Vector3 normalized = Vector3.Cross(Vector3.up, direction).normalized; positionR += normalized * (MathUtils.SmootherStep(0.5f, 0f, Mathf.Abs(m_defaultStopOffset - 0.5f)) * lane.m_stopOffset); LogUtils.DoLog($"[{buildingInfo}]2positionR = {positionR}; direction = {direction}; {normalized}"); result.Add(new StopPointDescriptorLanes { platformLine = refBezier, width = lane.m_width, vehicleType = refLane.m_stopType, laneId = laneId, subbuildingId = -1, directionPath = directionPath * (path.m_invertSegments == (refLane.m_finalDirection == NetInfo.Direction.AvoidForward || refLane.m_finalDirection == NetInfo.Direction.Backward) ? 1 : -1) }); } } } for (int i = 0; i < (buildingInfo.m_subBuildings?.Length ?? 0); i++) { StopPointDescriptorLanes[] subPlats = MapStopPoints(buildingInfo.m_subBuildings[i].m_buildingInfo, thresold); if (subPlats != null) { var rotationToApply = Quaternion.AngleAxis(buildingInfo.m_subBuildings[i].m_angle, Vector3.up); result.AddRange(subPlats.Select(x => { x.platformLine.a = (rotationToApply * x.platformLine.a) + buildingInfo.m_subBuildings[i].m_position; x.platformLine.b = (rotationToApply * x.platformLine.b) + buildingInfo.m_subBuildings[i].m_position; x.platformLine.c = (rotationToApply * x.platformLine.c) + buildingInfo.m_subBuildings[i].m_position; x.platformLine.d = (rotationToApply * x.platformLine.d) + buildingInfo.m_subBuildings[i].m_position; x.subbuildingId = (sbyte)i; x.directionPath = (rotationToApply * x.directionPath).normalized; return(x); })); } } result.Sort((x, y) => { int priorityX = VehicleToPriority(x.vehicleType); int priorityY = VehicleToPriority(y.vehicleType); if (priorityX != priorityY) { return(priorityX.CompareTo(priorityY)); } Vector3 centerX = (x.platformLine.Position(0.5f)); Vector3 centerY = (y.platformLine.Position(0.5f)); if (Mathf.Abs(centerX.y - centerY.y) >= thresold) { return(-centerX.y.CompareTo(centerY.y)); } if (Mathf.Abs(centerX.z - centerY.z) >= thresold) { return(-centerX.z.CompareTo(centerY.z)); } return(-centerX.x.CompareTo(centerY.x)); }); if (CommonProperties.DebugMode) { LogUtils.DoLog($"{buildingInfo.name} PLAT ORDER:\n{string.Join("\n", result.Select((x, y) => $"{y}=> {x.ToString()}").ToArray())}"); } return(result.ToArray()); }
public static bool RenderInstance(ref CitizenInstance instance, RenderManager.CameraInfo cameraInfo, ushort instanceID) { if ((instance.m_flags & CitizenInstance.Flags.Character) == CitizenInstance.Flags.None) return false; CitizenInfo info = instance.Info; if ((UnityEngine.Object)info == (UnityEngine.Object)null) return false; uint num = Singleton<SimulationManager>.instance.m_referenceFrameIndex - ((uint)instanceID << 4) / 65536U; CitizenInstance.Frame frameData1 = instance.GetFrameData(num - 32U); float maxDistance = Mathf.Min(RenderManager.LevelOfDetailFactor * 800f, info.m_maxRenderDistance + cameraInfo.m_height * 0.5f); if (!cameraInfo.CheckRenderDistance(frameData1.m_position, maxDistance) || !cameraInfo.Intersect(frameData1.m_position, 10f)) return false; CitizenInstance.Frame frameData2 = instance.GetFrameData(num - 16U); float t = (float)(((double)(num & 15U) + (double)Singleton<SimulationManager>.instance.m_referenceTimer) * (1.0 / 16.0)); bool flag1 = frameData2.m_underground && frameData1.m_underground; bool flag2 = frameData2.m_insideBuilding && frameData1.m_insideBuilding; bool flag3 = frameData2.m_transition || frameData1.m_transition; if (flag2 && !flag3 || flag1 && !flag3 && (cameraInfo.m_layerMask & 1 << Singleton<CitizenManager>.instance.m_undergroundLayer) == 0) return false; //begin mod info = GetUpdatedInfo(instance, instanceID); //end mod Vector3 vector3 = new Bezier3() { a = frameData1.m_position, b = (frameData1.m_position + frameData1.m_velocity * 0.333f), c = (frameData2.m_position - frameData2.m_velocity * 0.333f), d = frameData2.m_position }.Position(t); Quaternion quaternion = Quaternion.Lerp(frameData1.m_rotation, frameData2.m_rotation, t); Color color = info.m_citizenAI.GetColor(instanceID, ref instance, Singleton<InfoManager>.instance.CurrentMode); if (cameraInfo.CheckRenderDistance(vector3, info.m_lodRenderDistance)) { InstanceID id = InstanceID.Empty; id.CitizenInstance = instanceID; CitizenInfo citizenInfo = info.ObtainPrefabInstance<CitizenInfo>(id, (int)byte.MaxValue); if ((UnityEngine.Object)citizenInfo != (UnityEngine.Object)null) { Vector3 velocity = Vector3.Lerp(frameData1.m_velocity, frameData2.m_velocity, t); //begin mod if (info.m_subCulture == Citizen.SubCulture.Generic) { citizenInfo.m_citizenAI.SetRenderParameters(cameraInfo, instanceID, ref instance, vector3, quaternion, velocity, color, (flag1 || flag3) && (cameraInfo.m_layerMask & 1 << Singleton<CitizenManager>.instance.m_undergroundLayer) != 0); } else { citizenInfo.SetRenderParameters(vector3, quaternion, velocity, color, 5, (flag1 || flag3) && (cameraInfo.m_layerMask & 1 << Singleton<CitizenManager>.instance.m_undergroundLayer) != 0); } //end mod return true; } } if (flag1 || flag3) { info.m_undergroundLodLocations[info.m_undergroundLodCount].SetTRS(vector3, quaternion, Vector3.one); info.m_undergroundLodColors[info.m_undergroundLodCount] = color; info.m_undergroundLodMin = Vector3.Min(info.m_undergroundLodMin, vector3); info.m_undergroundLodMax = Vector3.Max(info.m_undergroundLodMax, vector3); if (++info.m_undergroundLodCount == info.m_undergroundLodLocations.Length) CitizenInstance.RenderUndergroundLod(cameraInfo, info); } if (!flag1 || flag3) { info.m_lodLocations[info.m_lodCount].SetTRS(vector3, quaternion, Vector3.one); info.m_lodColors[info.m_lodCount] = color; info.m_lodMin = Vector3.Min(info.m_lodMin, vector3); info.m_lodMax = Vector3.Max(info.m_lodMax, vector3); if (++info.m_lodCount == info.m_lodLocations.Length) CitizenInstance.RenderLod(cameraInfo, info); } return true; }
/// <summary> /// This method marks zone cells overlapped by network segments as invalid. Called by CalculateBlock1. /// </summary> /// <param name="_this"></param> /// <param name="blockID"></param> /// <param name="segmentID"></param> /// <param name="data"></param> /// <param name="valid"></param> /// <param name="minX"></param> /// <param name="minZ"></param> /// <param name="maxX"></param> /// <param name="maxZ"></param> private static void CalculateImplementation1(ref ZoneBlock _this, ushort blockID, ushort segmentID, ref NetSegment data, ref ulong valid, float minX, float minZ, float maxX, float maxZ) { // do nothing if the block belongs to the network segment if ((int)data.m_blockStartLeft == (int)blockID || (int)data.m_blockStartRight == (int)blockID || ((int)data.m_blockEndLeft == (int)blockID || (int)data.m_blockEndRight == (int)blockID)) { return; } NetInfo info = data.Info; if (!info.m_canCollide) return; // water pipes etc. float collisionHalfWidth = info.m_netAI.GetCollisionHalfWidth(); NetNode[] netNodeArray = Singleton<NetManager>.instance.m_nodes.m_buffer; // calculate network bezier curve Bezier3 bezier = new Bezier3(); bezier.a = netNodeArray[(int)data.m_startNode].m_position; bezier.d = netNodeArray[(int)data.m_endNode].m_position; NetSegment.CalculateMiddlePoints(bezier.a, data.m_startDirection, bezier.d, data.m_endDirection, true, true, out bezier.b, out bezier.c); // remove vertical component Bezier2 bezierXZ = Bezier2.XZ(bezier); // do nothing if the collision hitbox is outside of the hitbox of the zone block Vector2 collisionAreaMin = bezierXZ.Min() + new Vector2(-collisionHalfWidth, -collisionHalfWidth); Vector2 collisionAreaMax = bezierXZ.Max() + new Vector2(collisionHalfWidth, collisionHalfWidth); if ((double)collisionAreaMin.x > (double)maxX || (double)collisionAreaMin.y > (double)maxZ || ((double)minX > (double)collisionAreaMax.x || (double)minZ > (double)collisionAreaMax.y)) { return; } // width of the zone block int rowCount = _this.RowCount; // directions of the rows and columns based on zone block angle, multiplied by 8 (cell size) Vector2 columnDirection = new Vector2(Mathf.Cos(_this.m_angle), Mathf.Sin(_this.m_angle)) * 8f; Vector2 rowDirection = new Vector2(columnDirection.y, -columnDirection.x); // origin of the zone block // this position is in the center of the 8x8 zone block (4 columns and 4 rows away from the lower corner) Vector2 positionXZ = VectorUtils.XZ(_this.m_position); // area of the zone block (8x8 cells) Quad2 zoneBlockQuad = new Quad2 { a = positionXZ - 4f * columnDirection - 4f * rowDirection, b = positionXZ + 4f * columnDirection - 4f * rowDirection, c = positionXZ + 4f * columnDirection + (float)(rowCount - 4) * rowDirection, d = positionXZ - 4f * columnDirection + (float)(rowCount - 4) * rowDirection }; // Calculate the bounds of the network segment at the start node float start; float end; info.m_netAI.GetTerrainModifyRange(out start, out end); float halfStart = start * 0.5f; // e.g. 0.25f ---> 0.125f float halfEnd = (float)(1.0 - (1.0 - (double)end) * 0.5); // e.g. 0.75f --> 0.875f float t = halfStart; Vector2 startBezierPos = bezierXZ.Position(halfStart); Vector2 startBezierTan = bezierXZ.Tangent(halfStart); Vector2 startOrthogonalNormalized = new Vector2(-startBezierTan.y, startBezierTan.x).normalized; // tangent rotated by -90 deg = orthogonal Quad2 bezierQuad = new Quad2(); // set the initial a/b bounds if ((double)t < 0.00999999977648258 && (info.m_clipSegmentEnds || (netNodeArray[(int)data.m_startNode].m_flags & NetNode.Flags.Bend) != NetNode.Flags.None)) { Vector2 ortho4m = startOrthogonalNormalized * 4f; bezierQuad.a = startBezierPos + ortho4m - VectorUtils.XZ(data.m_startDirection) * 4f; bezierQuad.d = startBezierPos - ortho4m - VectorUtils.XZ(data.m_startDirection) * 4f; } else { Vector2 orthoHalfWidth = startOrthogonalNormalized * collisionHalfWidth; bezierQuad.a = startBezierPos + orthoHalfWidth; bezierQuad.d = startBezierPos - orthoHalfWidth; } // overlap 8 quads describing the position int steps = 8; for (int step = 1; step <= steps; ++step) { float interp = halfStart + (halfEnd - halfStart) * (float)step / (float)steps; Vector2 interpBezierPos = bezierXZ.Position(interp); Vector2 interpBezierTangent = bezierXZ.Tangent(interp); interpBezierTangent = new Vector2(-interpBezierTangent.y, interpBezierTangent.x).normalized; // set the c/d bounds if ((double)interp > 0.990000009536743 && (info.m_clipSegmentEnds || (netNodeArray[(int)data.m_endNode].m_flags & NetNode.Flags.Bend) != NetNode.Flags.None)) { interpBezierTangent *= 4f; bezierQuad.b = interpBezierPos + interpBezierTangent - VectorUtils.XZ(data.m_endDirection) * 4f; bezierQuad.c = interpBezierPos - interpBezierTangent - VectorUtils.XZ(data.m_endDirection) * 4f; } else { interpBezierTangent *= collisionHalfWidth; bezierQuad.b = interpBezierPos + interpBezierTangent; bezierQuad.c = interpBezierPos - interpBezierTangent; } Vector2 quadMin = bezierQuad.Min(); Vector2 quadMax = bezierQuad.Max(); // Overlap the quad with the zone block quad if ((double)quadMin.x <= (double)maxX && (double)quadMin.y <= (double)maxZ && ((double)minX <= (double)quadMax.x && (double)minZ <= (double)quadMax.y) && zoneBlockQuad.Intersect(bezierQuad)) { // mark colliding cells as invalid valid = valid & ~OverlapQuad(ref _this, bezierQuad); } // set the a/b bounds for the next quad bezierQuad.a = bezierQuad.b; bezierQuad.d = bezierQuad.c; } }
/// <summary> /// Create curved zone blocks. /// </summary> /// <param name="info">Network prefab</param> /// <param name="randomizer">Randomizer</param> /// <param name="segment">Network segment</param> private static void CurvedZoneBlocks(NetInfo info, Randomizer randomizer, ref NetSegment segment) { #pragma warning disable IDE0018 // Inline variable declaration // TODO: Basically game code with some NExT2 modifications. Could do with a good refactor, and possible replacement with Transpiler. var minHalfWidth = MIN_HALFWIDTH_TINY_CURVE; NetManager instance = Singleton <NetManager> .instance; Vector3 startPosition = instance.m_nodes.m_buffer[(int)segment.m_startNode].m_position; Vector3 endPosition = instance.m_nodes.m_buffer[(int)segment.m_endNode].m_position; Vector3 startDirection = segment.m_startDirection; Vector3 endDirection = segment.m_endDirection; float num = startDirection.x * endDirection.x + startDirection.z * endDirection.z; float num2 = Mathf.Max(minHalfWidth, info.m_halfWidth); // minHalfWidth here. float num3 = 32f; int distance = Mathf.RoundToInt(num2); float num4 = VectorUtils.LengthXZ(endPosition - startPosition); bool flag2 = startDirection.x * endDirection.z - startDirection.z * endDirection.x > 0f; bool flag3 = num <-0.8f || num4> 50f; if (flag2) { num2 = -num2; num3 = -num3; } Vector3 vector = startPosition - new Vector3(startDirection.z, 0f, -startDirection.x) * num2; Vector3 vector2 = endPosition + new Vector3(endDirection.z, 0f, -endDirection.x) * num2; Vector3 vector3; Vector3 vector4; NetSegment.CalculateMiddlePoints(vector, startDirection, vector2, endDirection, true, true, out vector3, out vector4); if (flag3) { float num5 = num * 0.025f + 0.04f; float num6 = num * 0.025f + 0.06f; if (num < -0.9f) { num6 = num5; } Bezier3 bezier = new Bezier3(vector, vector3, vector4, vector2); vector = bezier.Position(num5); vector3 = bezier.Position(0.5f - num6); vector4 = bezier.Position(0.5f + num6); vector2 = bezier.Position(1f - num5); } else { Bezier3 bezier2 = new Bezier3(vector, vector3, vector4, vector2); vector3 = bezier2.Position(0.86f); vector = bezier2.Position(0.14f); } float num7; Vector3 vector5 = VectorUtils.NormalizeXZ(vector3 - vector, out num7); int num8 = Mathf.FloorToInt(num7 / 8f + 0.01f); float num9 = num7 * 0.5f + (float)(num8 - 8) * ((!flag2) ? -4f : 4f); if (num8 != 0) { float angle = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z); Vector3 position3 = vector + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3); if (flag2) { Singleton <ZoneManager> .instance.CreateBlock( out segment.m_blockStartRight, ref randomizer, position3, angle, num8, distance, segment.m_buildIndex); } else { Singleton <ZoneManager> .instance.CreateBlock( out segment.m_blockStartLeft, ref randomizer, position3, angle, num8, distance, segment.m_buildIndex); } } if (flag3) { vector5 = VectorUtils.NormalizeXZ(vector2 - vector4, out num7); num8 = Mathf.FloorToInt(num7 / 8f + 0.01f); num9 = num7 * 0.5f + (float)(num8 - 8) * ((!flag2) ? -4f : 4f); if (num8 != 0) { float angle2 = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z); Vector3 position4 = vector4 + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3); if (flag2) { Singleton <ZoneManager> .instance.CreateBlock( out segment.m_blockEndRight, ref randomizer, position4, angle2, num8, distance, segment.m_buildIndex + 1u); } else { Singleton <ZoneManager> .instance.CreateBlock( out segment.m_blockEndLeft, ref randomizer, position4, angle2, num8, distance, segment.m_buildIndex + 1u); } } } Vector3 vector6 = startPosition + new Vector3(startDirection.z, 0f, -startDirection.x) * num2; Vector3 vector7 = endPosition - new Vector3(endDirection.z, 0f, -endDirection.x) * num2; Vector3 b; Vector3 c; NetSegment.CalculateMiddlePoints(vector6, startDirection, vector7, endDirection, true, true, out b, out c); Bezier3 bezier3 = new Bezier3(vector6, b, c, vector7); Vector3 vector8 = bezier3.Position(0.5f); Vector3 vector9 = bezier3.Position(0.25f); vector9 = Line2.Offset(VectorUtils.XZ(vector6), VectorUtils.XZ(vector8), VectorUtils.XZ(vector9)); Vector3 vector10 = bezier3.Position(0.75f); vector10 = Line2.Offset(VectorUtils.XZ(vector7), VectorUtils.XZ(vector8), VectorUtils.XZ(vector10)); Vector3 vector11 = vector6; Vector3 a = vector7; float d; #pragma warning disable IDE0059 // Unnecessary assignment of a value float num10; if (Line2.Intersect(VectorUtils.XZ(startPosition), VectorUtils.XZ(vector6), VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), out d, out num10)) { vector6 = startPosition + (vector6 - startPosition) * d; } if (Line2.Intersect(VectorUtils.XZ(endPosition), VectorUtils.XZ(vector7), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10)) { vector7 = endPosition + (vector7 - endPosition) * d; } if (Line2.Intersect(VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10)) #pragma warning restore IDE0059 // Unnecessary assignment of a value { vector8 = vector11 - vector9 + (vector8 - vector11) * d; } float num11; Vector3 vector12 = VectorUtils.NormalizeXZ(vector8 - vector6, out num11); int num12 = Mathf.FloorToInt(num11 / 8f + 0.01f); float num13 = num11 * 0.5f + (float)(num12 - 8) * ((!flag2) ? 4f : -4f); if (num12 != 0) { float angle3 = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z); Vector3 position5 = vector6 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3); if (flag2) { Singleton <ZoneManager> .instance.CreateBlock( out segment.m_blockStartLeft, ref randomizer, position5, angle3, num12, distance, segment.m_buildIndex); } else { Singleton <ZoneManager> .instance.CreateBlock( out segment.m_blockStartRight, ref randomizer, position5, angle3, num12, distance, segment.m_buildIndex); } } vector12 = VectorUtils.NormalizeXZ(vector7 - vector8, out num11); num12 = Mathf.FloorToInt(num11 / 8f + 0.01f); num13 = num11 * 0.5f + (float)(num12 - 8) * ((!flag2) ? 4f : -4f); if (num12 != 0) { float angle4 = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z); Vector3 position6 = vector8 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3); if (flag2) { Singleton <ZoneManager> .instance.CreateBlock( out segment.m_blockEndLeft, ref randomizer, position6, angle4, num12, distance, segment.m_buildIndex + 1u); } else { Singleton <ZoneManager> .instance.CreateBlock( out segment.m_blockEndRight, ref randomizer, position6, angle4, num12, distance, segment.m_buildIndex + 1u); } } #pragma warning restore IDE0018 // Inline variable declaration }
private static void CreateZoneBlocksTiny_Curve(NetInfo info, Randomizer randomizer, ref NetSegment segment) { var minHalfWidth = MIN_HALFWIDTH_TINY_CURVE; NetManager instance = Singleton<NetManager>.instance; Vector3 startPosition = instance.m_nodes.m_buffer[(int)segment.m_startNode].m_position; Vector3 endPosition = instance.m_nodes.m_buffer[(int)segment.m_endNode].m_position; Vector3 startDirection = segment.m_startDirection; Vector3 endDirection = segment.m_endDirection; float num = startDirection.x * endDirection.x + startDirection.z * endDirection.z; float num2 = Mathf.Max(minHalfWidth, info.m_halfWidth); float num3 = 32f; float num4 = VectorUtils.LengthXZ(endPosition - startPosition); bool flag2 = startDirection.x * endDirection.z - startDirection.z * endDirection.x > 0f; bool flag3 = num < -0.8f || num4 > 50f; if (flag2) { num2 = -num2; num3 = -num3; } Vector3 vector = startPosition - new Vector3(startDirection.z, 0f, -startDirection.x) * num2; Vector3 vector2 = endPosition + new Vector3(endDirection.z, 0f, -endDirection.x) * num2; Vector3 vector3; Vector3 vector4; NetSegment.CalculateMiddlePoints(vector, startDirection, vector2, endDirection, true, true, out vector3, out vector4); if (flag3) { float num5 = num * 0.025f + 0.04f; float num6 = num * 0.025f + 0.06f; if (num < -0.9f) { num6 = num5; } Bezier3 bezier = new Bezier3(vector, vector3, vector4, vector2); vector = bezier.Position(num5); vector3 = bezier.Position(0.5f - num6); vector4 = bezier.Position(0.5f + num6); vector2 = bezier.Position(1f - num5); } else { Bezier3 bezier2 = new Bezier3(vector, vector3, vector4, vector2); vector3 = bezier2.Position(0.86f); vector = bezier2.Position(0.14f); } float num7; Vector3 vector5 = VectorUtils.NormalizeXZ(vector3 - vector, out num7); int num8 = Mathf.FloorToInt(num7 / 8f + 0.01f); float num9 = num7 * 0.5f + (float)(num8 - 8) * ((!flag2) ? -4f : 4f); if (num8 != 0) { float angle = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z); Vector3 position3 = vector + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3); if (flag2) { Singleton<ZoneManager>.instance.CreateBlock( out segment.m_blockStartRight, ref randomizer, position3, angle, num8, segment.m_buildIndex); } else { Singleton<ZoneManager>.instance.CreateBlock( out segment.m_blockStartLeft, ref randomizer, position3, angle, num8, segment.m_buildIndex); } } if (flag3) { vector5 = VectorUtils.NormalizeXZ(vector2 - vector4, out num7); num8 = Mathf.FloorToInt(num7 / 8f + 0.01f); num9 = num7 * 0.5f + (float)(num8 - 8) * ((!flag2) ? -4f : 4f); if (num8 != 0) { float angle2 = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z); Vector3 position4 = vector4 + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3); if (flag2) { Singleton<ZoneManager>.instance.CreateBlock( out segment.m_blockEndRight, ref randomizer, position4, angle2, num8, segment.m_buildIndex + 1u); } else { Singleton<ZoneManager>.instance.CreateBlock( out segment.m_blockEndLeft, ref randomizer, position4, angle2, num8, segment.m_buildIndex + 1u); } } } Vector3 vector6 = startPosition + new Vector3(startDirection.z, 0f, -startDirection.x) * num2; Vector3 vector7 = endPosition - new Vector3(endDirection.z, 0f, -endDirection.x) * num2; Vector3 b; Vector3 c; NetSegment.CalculateMiddlePoints(vector6, startDirection, vector7, endDirection, true, true, out b, out c); Bezier3 bezier3 = new Bezier3(vector6, b, c, vector7); Vector3 vector8 = bezier3.Position(0.5f); Vector3 vector9 = bezier3.Position(0.25f); vector9 = Line2.Offset(VectorUtils.XZ(vector6), VectorUtils.XZ(vector8), VectorUtils.XZ(vector9)); Vector3 vector10 = bezier3.Position(0.75f); vector10 = Line2.Offset(VectorUtils.XZ(vector7), VectorUtils.XZ(vector8), VectorUtils.XZ(vector10)); Vector3 vector11 = vector6; Vector3 a = vector7; float d; float num10; if (Line2.Intersect(VectorUtils.XZ(startPosition), VectorUtils.XZ(vector6), VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), out d, out num10)) { vector6 = startPosition + (vector6 - startPosition) * d; } if (Line2.Intersect(VectorUtils.XZ(endPosition), VectorUtils.XZ(vector7), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10)) { vector7 = endPosition + (vector7 - endPosition) * d; } if (Line2.Intersect(VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10)) { vector8 = vector11 - vector9 + (vector8 - vector11) * d; } float num11; Vector3 vector12 = VectorUtils.NormalizeXZ(vector8 - vector6, out num11); int num12 = Mathf.FloorToInt(num11 / 8f + 0.01f); float num13 = num11 * 0.5f + (float)(num12 - 8) * ((!flag2) ? 4f : -4f); if (num12 != 0) { float angle3 = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z); Vector3 position5 = vector6 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3); if (flag2) { Singleton<ZoneManager>.instance.CreateBlock( out segment.m_blockStartLeft, ref randomizer, position5, angle3, num12, segment.m_buildIndex); } else { Singleton<ZoneManager>.instance.CreateBlock( out segment.m_blockStartRight, ref randomizer, position5, angle3, num12, segment.m_buildIndex); } } vector12 = VectorUtils.NormalizeXZ(vector7 - vector8, out num11); num12 = Mathf.FloorToInt(num11 / 8f + 0.01f); num13 = num11 * 0.5f + (float)(num12 - 8) * ((!flag2) ? 4f : -4f); if (num12 != 0) { float angle4 = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z); Vector3 position6 = vector8 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3); if (flag2) { Singleton<ZoneManager>.instance.CreateBlock( out segment.m_blockEndLeft, ref randomizer, position6, angle4, num12, segment.m_buildIndex + 1u); } else { Singleton<ZoneManager>.instance.CreateBlock( out segment.m_blockEndRight, ref randomizer, position6, angle4, num12, segment.m_buildIndex + 1u); } } }
public string ExportSegment(NetSegment a_seg, ref int segId, ref System.Reflection.PropertyInfo[] properties) { var startNodeId = a_seg.m_startNode; var endNodeId = a_seg.m_endNode; var startDirection = a_seg.m_startDirection; var endDirection = a_seg.m_endDirection; if ((a_seg.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) { startNodeId = a_seg.m_endNode; endNodeId = a_seg.m_startNode; startDirection = a_seg.m_endDirection; endDirection = a_seg.m_startDirection; } var road_name = net_manager.GetSegmentName((ushort)segId); if (road_name == null || road_name == "") { road_name = "no name " + segId.ToString(); } var startPos = net_manager.m_nodes.m_buffer[startNodeId].m_position; LatLng startRwoLL = GamePosition2LatLng(startPos); var endPos = net_manager.m_nodes.m_buffer[endNodeId].m_position; LatLng endRwoLL = GamePosition2LatLng(endPos); string wkt = ""; if (Vector3.Angle(startDirection, -endDirection) > 3f) { Vector3 a = Vector3.zero; Vector3 b = Vector3.zero; NetSegment.CalculateMiddlePoints(startPos, startDirection, endPos, endDirection, false, false, out a, out b); var bezier = new Bezier3(startPos, a, b, endPos); var p1 = bezier.Position(0.25f); var p1RwoLL = GamePosition2LatLng(p1); var p2 = bezier.Position(0.5f); var p2RwoLL = GamePosition2LatLng(p2); var p3 = bezier.Position(0.5f); var p3RwoLL = GamePosition2LatLng(p3); LatLng[] listOfPositions = new LatLng[] { startRwoLL, p1RwoLL, p2RwoLL, p3RwoLL, endRwoLL }; wkt = CreateWkt(listOfPositions); } else { wkt = CreateWkt(new LatLng[] { startRwoLL, endRwoLL }); } float tmpY = tm.SampleRawHeightSmoothWithWater(startPos, false, 0f); float elevS = startPos.y - tmpY; tmpY = tm.SampleRawHeightSmoothWithWater(endPos, false, 0f); float elevE = endPos.y - tmpY; string rowTxt = string.Format("{0},{1},{2},{3},{4}", segId, road_name, wkt, elevS, elevE); string field_info = ""; foreach (var prop in properties) { var prop_val = prop.GetValue(a_seg, null); if (prop_val.ToString().Contains(",")) { prop_val = "\"" + prop_val.ToString() + "\""; } field_info += string.Format(",{0}", prop_val); } rowTxt += field_info; return(rowTxt); }
void SetLaneMarkers() { m_hoveredLaneMarkers.Clear(); if (m_segments.Count == 0) { return; } NetSegment segment = NetManager.instance.m_segments.m_buffer[m_segments.Values.First().m_segmentId]; NetInfo info = segment.Info; int laneCount = info.m_lanes.Length; bool bothWays = info.m_hasBackwardVehicleLanes && info.m_hasForwardVehicleLanes; bool isInverted = false; for (ushort i = 0; i < laneCount; i++) { m_hoveredLaneMarkers[i] = new FastList <SegmentLaneMarker>(); } foreach (Segment seg in m_segments.Values) { segment = NetManager.instance.m_segments.m_buffer[seg.m_segmentId]; uint laneId = segment.m_lanes; if (bothWays) { isInverted = seg.m_targetNode == segment.m_startNode; if ((segment.m_flags & NetSegment.Flags.Invert) == NetSegment.Flags.Invert) { isInverted = !isInverted; } } for (int j = 0; j < laneCount && laneId != 0; j++) { NetLane lane = NetManager.instance.m_lanes.m_buffer[laneId]; //if ((info.m_lanes[j].m_laneType & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != NetInfo.LaneType.None) if ((info.m_lanes[j].m_laneType & NetInfo.LaneType.Vehicle) == NetInfo.LaneType.Vehicle) { Bezier3 bezier = lane.m_bezier; bezier.GetBounds().Expand(1f); int index = j; if (bothWays && isInverted) { index += (j % 2 == 0) ? 1 : -1; } m_hoveredLaneMarkers[index].Add(new SegmentLaneMarker() { m_bezier = bezier, m_lane = laneId, m_laneIndex = index }); } laneId = lane.m_nextLane; } } }
public void PopulateGroupData(ushort segmentID, int groupX, int groupZ, int layer, ref int vertexIndex, ref int triangleIndex, Vector3 groupPosition, RenderGroup.MeshData data, ref Vector3 min, ref Vector3 max, ref float maxRenderDistance, ref float maxInstanceDistance, ref bool requireSurfaceMaps) { bool hasProps = false; NetInfo info = Info; NetManager instance = Singleton <NetManager> .instance; if (m_problems != Notification.Problem.None && layer == Singleton <NotificationManager> .instance.m_notificationLayer) { Vector3 middlePosition = m_middlePosition; middlePosition.y += info.m_maxHeight; Notification.PopulateGroupData(m_problems, middlePosition, 1f, groupX, groupZ, ref vertexIndex, ref triangleIndex, groupPosition, data, ref min, ref max, ref maxRenderDistance, ref maxInstanceDistance); } if (info.m_hasForwardVehicleLanes != info.m_hasBackwardVehicleLanes && layer == Singleton <NetManager> .instance.m_arrowLayer) { Bezier3 bezier = default(Bezier3); bezier.a = Singleton <NetManager> .instance.m_nodes.m_buffer[m_startNode].m_position; bezier.d = Singleton <NetManager> .instance.m_nodes.m_buffer[m_endNode].m_position; CalculateMiddlePoints(bezier.a, m_startDirection, bezier.d, m_endDirection, smoothStart: true, smoothEnd: true, out bezier.b, out bezier.c); Vector3 pos = bezier.Position(0.5f); pos.y += info.m_netAI.GetSnapElevation(); Vector3 vector = VectorUtils.NormalizeXZ(bezier.Tangent(0.5f)) * (4f + info.m_halfWidth * 0.5f); if ((m_flags & Flags.Invert) != 0 == info.m_hasForwardVehicleLanes) { vector = -vector; } PopulateArrowGroupData(pos, vector, ref vertexIndex, ref triangleIndex, groupPosition, data, ref min, ref max, ref maxRenderDistance, ref maxInstanceDistance); } if (info.m_lanes != null) { bool invert; NetNode.Flags flags; NetNode.Flags flags2; if ((m_flags & Flags.Invert) != 0) { invert = true; instance.m_nodes.m_buffer[m_endNode].Info.m_netAI.GetNodeFlags(m_endNode, ref instance.m_nodes.m_buffer[m_endNode], segmentID, ref this, out flags); instance.m_nodes.m_buffer[m_startNode].Info.m_netAI.GetNodeFlags(m_startNode, ref instance.m_nodes.m_buffer[m_startNode], segmentID, ref this, out flags2); } else { invert = false; instance.m_nodes.m_buffer[m_startNode].Info.m_netAI.GetNodeFlags(m_startNode, ref instance.m_nodes.m_buffer[m_startNode], segmentID, ref this, out flags); instance.m_nodes.m_buffer[m_endNode].Info.m_netAI.GetNodeFlags(m_endNode, ref instance.m_nodes.m_buffer[m_endNode], segmentID, ref this, out flags2); } bool terrainHeight = info.m_segments == null || info.m_segments.Length == 0; float startAngle = (float)(int)m_cornerAngleStart * ((float)Math.PI / 128f); float endAngle = (float)(int)m_cornerAngleEnd * ((float)Math.PI / 128f); bool destroyed = (m_flags & Flags.Collapsed) != 0; uint num = m_lanes; for (int i = 0; i < info.m_lanes.Length; i++) { if (num == 0) { break; } instance.m_lanes.m_buffer[num].PopulateGroupData(segmentID, num, info.m_lanes[i], destroyed, flags, flags2, startAngle, endAngle, invert, terrainHeight, layer, ref vertexIndex, ref triangleIndex, groupPosition, data, ref min, ref max, ref maxRenderDistance, ref maxInstanceDistance, ref hasProps); num = instance.m_lanes.m_buffer[num].m_nextLane; } } if ((info.m_netLayers & (1 << layer)) == 0) { return; } bool flag = info.m_segments != null && info.m_segments.Length != 0; if (!flag && !hasProps) { return; } min = Vector3.Min(min, m_bounds.min); max = Vector3.Max(max, m_bounds.max); maxRenderDistance = Mathf.Max(maxRenderDistance, 30000f); maxInstanceDistance = Mathf.Max(maxInstanceDistance, 1000f); if (!flag) { return; } float vScale = info.m_netAI.GetVScale(); CalculateCorner(segmentID, heightOffset: true, start: true, leftSide: true, out var cornerPosSL, out var cornerDirectionSL, out var smoothStart); CalculateCorner(segmentID, heightOffset: true, start: false, leftSide: true, out var cornerPosEL, out var cornerDirectionEL, out var smoothEnd); CalculateCorner(segmentID, heightOffset: true, start: true, leftSide: false, out var cornerPosSR, out var cornerDirectionSR, out smoothStart); CalculateCorner(segmentID, heightOffset: true, start: false, leftSide: false, out var cornerPosER, out var cornerDirectionER, out smoothEnd); CalculateMiddlePoints(cornerPosSL, cornerDirectionSL, cornerPosER, cornerDirectionER, smoothStart, smoothEnd, out var b1, out var c1); CalculateMiddlePoints(cornerPosSR, cornerDirectionSR, cornerPosEL, cornerDirectionEL, smoothStart, smoothEnd, out var b2, out var c2); Vector3 position = instance.m_nodes.m_buffer[m_startNode].m_position; Vector3 position2 = instance.m_nodes.m_buffer[m_endNode].m_position; Vector4 meshScale = new Vector4(0.5f / info.m_halfWidth, 1f / info.m_segmentLength, 1f, 1f); Vector4 colorLocationStart = RenderManager.GetColorLocation((uint)(49152 + segmentID)); Vector4 colorlocationEnd = colorLocationStart; if (NetNode.BlendJunction(m_startNode)) { colorLocationStart = RenderManager.GetColorLocation((uint)(86016 + m_startNode)); } if (NetNode.BlendJunction(m_endNode)) { colorlocationEnd = RenderManager.GetColorLocation((uint)(86016 + m_endNode)); } Vector4 objectIndex0 = new Vector4(colorLocationStart.x, colorLocationStart.y, colorlocationEnd.x, colorlocationEnd.y); for (int j = 0; j < info.m_segments.Length; j++) { NetInfo.Segment segment = info.m_segments[j]; bool turnAround = false; if (segment.m_layer == layer && segment.CheckFlags(m_flags, out turnAround) && segment.m_combinedLod != null) { Vector4 objectIndex = objectIndex0; if (segment.m_requireWindSpeed) { objectIndex.w = Singleton <WeatherManager> .instance.GetWindSpeed((position + position2) * 0.5f); } else if (turnAround) { objectIndex = new Vector4(objectIndex.z, objectIndex.w, objectIndex.x, objectIndex.y); } Matrix4x4 leftMatrix; Matrix4x4 rightMatrix; if (turnAround) { leftMatrix = CalculateControlMatrix(cornerPosEL, c2, b2, cornerPosSR, cornerPosER, c1, b1, cornerPosSL, groupPosition, vScale); rightMatrix = CalculateControlMatrix(cornerPosER, c1, b1, cornerPosSL, cornerPosEL, c2, b2, cornerPosSR, groupPosition, vScale); } else { leftMatrix = CalculateControlMatrix(cornerPosSL, b1, c1, cornerPosER, cornerPosSR, b2, c2, cornerPosEL, groupPosition, vScale); rightMatrix = CalculateControlMatrix(cornerPosSR, b2, c2, cornerPosEL, cornerPosSL, b1, c1, cornerPosER, groupPosition, vScale); } PopulateGroupData(info, segment, leftMatrix, rightMatrix, meshScale, objectIndex, ref vertexIndex, ref triangleIndex, groupPosition, data, ref requireSurfaceMaps); } } }
public void CustomCheckNextLane(ushort vehicleID, ref Vehicle vehicleData, ref float maxSpeed, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, Bezier3 bezier) { if ((Options.prioritySignsEnabled || Options.timedLightsEnabled) && Options.simAccuracy <= 1) { try { VehicleStateManager.Instance().UpdateVehiclePos(vehicleID, ref vehicleData, ref prevPos, ref position); } catch (Exception e) { Log.Error("TrainAI CustomCheckNextLane Error: " + e.ToString()); } } NetManager instance = Singleton <NetManager> .instance; Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData(); Vector3 a = lastFrameData.m_position; Vector3 a2 = lastFrameData.m_position; Vector3 b = lastFrameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f); a += b; a2 -= b; float num = 0.5f * lastFrameData.m_velocity.sqrMagnitude / this.m_info.m_braking; float a3 = Vector3.Distance(a, bezier.a); float b2 = Vector3.Distance(a2, bezier.a); if (Mathf.Min(a3, b2) >= num - 5f) { if (!instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(1000f, vehicleID)) { maxSpeed = 0f; return; } Vector3 vector = bezier.Position(0.5f); Segment3 segment; if (Vector3.SqrMagnitude(vehicleData.m_segment.a - vector) < Vector3.SqrMagnitude(bezier.a - vector)) { segment = new Segment3(vehicleData.m_segment.a, vector); } else { segment = new Segment3(bezier.a, vector); } if (segment.LengthSqr() >= 3f) { segment.a += (segment.b - segment.a).normalized * 2.5f; if (CustomTrainAI.CheckOverlap(vehicleID, ref vehicleData, segment, vehicleID)) { maxSpeed = 0f; return; } } segment = new Segment3(vector, bezier.d); if (segment.LengthSqr() >= 1f && CustomTrainAI.CheckOverlap(vehicleID, ref vehicleData, segment, vehicleID)) { maxSpeed = 0f; return; } ushort targetNodeId; if (offset < position.m_offset) { targetNodeId = instance.m_segments.m_buffer[(int)position.m_segment].m_startNode; } else { targetNodeId = instance.m_segments.m_buffer[(int)position.m_segment].m_endNode; } ushort prevTargetNodeId; if (prevOffset == 0) { prevTargetNodeId = instance.m_segments.m_buffer[(int)prevPos.m_segment].m_startNode; } else { prevTargetNodeId = instance.m_segments.m_buffer[(int)prevPos.m_segment].m_endNode; } if (targetNodeId == prevTargetNodeId) { float oldMaxSpeed = maxSpeed; #if DEBUG bool debug = false; // targetNodeId == 14527 || targetNodeId == 15048; if (debug) { Log._Debug($"Train {vehicleID} wants to change segment. seg. {prevPos.m_segment} -> node {targetNodeId} -> seg. {position.m_segment}"); } #else bool debug = false; #endif bool mayChange = CustomVehicleAI.MayChangeSegment(vehicleID, ref vehicleData, ref lastFrameData, false, ref prevPos, prevTargetNodeId, prevLaneID, ref position, targetNodeId, laneID, out maxSpeed, debug); if (!mayChange) { return; } maxSpeed = oldMaxSpeed; } } }
public static bool NetSegmentRayCastMasked(NetSegment mysegment, ushort segmentID, Segment3 ray, float snapElevation, bool bothSides, out float t, out float priority) { bool lht = false; //if (SimulationManager.instance.m_metaData.m_invertTraffic == SimulationMetaData.MetaBool.True) lht = true; //Debug.Log(mysegment.m_flags); if ((mysegment.m_flags & NetSegment.Flags.Invert) != 0) { lht = true; } bool isMasked = false; NetInfo info = mysegment.Info; t = 0f; priority = 0f; Bounds bounds = mysegment.m_bounds; bounds.Expand(16f); if (!bounds.IntersectRay(new Ray(ray.a, ray.b - ray.a))) { return(false); } NetManager instance = Singleton <NetManager> .instance; Bezier3 bezier = default(Bezier3); bezier.a = instance.m_nodes.m_buffer[mysegment.m_startNode].m_position; bezier.d = instance.m_nodes.m_buffer[mysegment.m_endNode].m_position; bool result = false; info.m_netAI.GetRayCastHeights(segmentID, ref mysegment, out float leftMin, out float rightMin, out float max); bezier.a.y += max; bezier.d.y += max; bool flag = (instance.m_nodes.m_buffer[mysegment.m_startNode].m_flags & NetNode.Flags.Middle) != 0; bool flag2 = (instance.m_nodes.m_buffer[mysegment.m_endNode].m_flags & NetNode.Flags.Middle) != 0; NetSegment.CalculateMiddlePoints(bezier.a, mysegment.m_startDirection, bezier.d, mysegment.m_endDirection, flag, flag2, out bezier.b, out bezier.c); float minNodeDistance = info.GetMinNodeDistance(); // float collisionHalfWidth = info.m_halfWidth; float maskHalfWidth = info.m_pavementWidth; // float num4 = (int)instance.m_nodes.m_buffer[mysegment.m_startNode].m_elevation; float num5 = (int)instance.m_nodes.m_buffer[mysegment.m_endNode].m_elevation; if (info.m_netAI.IsUnderground()) { num4 = 0f - num4; num5 = 0f - num5; } num4 += info.m_netAI.GetSnapElevation(); num5 += info.m_netAI.GetSnapElevation(); float a = Mathf.Lerp(minNodeDistance, collisionHalfWidth, Mathf.Clamp01(Mathf.Abs(snapElevation - num4) / 12f)); float b2 = Mathf.Lerp(minNodeDistance, collisionHalfWidth, Mathf.Clamp01(Mathf.Abs(snapElevation - num5) / 12f)); float am = Mathf.Lerp(minNodeDistance, maskHalfWidth, Mathf.Clamp01(Mathf.Abs(snapElevation - num4) / 12f)); float b2m = Mathf.Lerp(minNodeDistance, maskHalfWidth, Mathf.Clamp01(Mathf.Abs(snapElevation - num5) / 12f)); float num6 = Mathf.Min(leftMin, rightMin); t = 1000000f; priority = 1000000f; Segment3 segment = default(Segment3); segment.a = bezier.a; Segment2 segment2 = default(Segment2); //Debug.Log($"mouse ray: {ray.a} --> {ray.b}"); //Debug.Log($"segment direction: {bezier.a} --> {bezier.b}"); for (int i = 1; i <= 16; i++) { segment.b = bezier.Position((float)i / 16f); float num7 = ray.DistanceSqr(segment, out float u2, out float v2); float num8 = Mathf.Lerp(a, b2, ((float)(i - 1) + v2) / 16f); float num8m = Mathf.Lerp(am, b2m, ((float)(i - 1) + v2) / 16f); Vector3 vector2 = segment.Position(v2); bool atOffsetSide = bothSides || IsTrafficHandSideOf(segment, ray, u2, lht); if (atOffsetSide && num7 < priority && Segment1.Intersect(ray.a.y, ray.b.y, vector2.y, out u2)) { Vector3 vector3 = ray.Position(u2); num7 = Vector3.SqrMagnitude(vector3 - vector2); //Debug.Log($"num7: {num7}, num8: {num8}, num8m: {num8m}"); if (num7 < priority && num7 < num8 * num8) { if (flag && i == 1 && v2 < 0.001f) { Vector3 rhs = segment.a - segment.b; u2 += Mathf.Max(0f, Vector3.Dot(vector3, rhs)) / Mathf.Max(0.001f, Mathf.Sqrt(rhs.sqrMagnitude * ray.LengthSqr())); } if (flag2 && i == 16 && v2 > 0.999f) { Vector3 rhs2 = segment.b - segment.a; u2 += Mathf.Max(0f, Vector3.Dot(vector3, rhs2)) / Mathf.Max(0.001f, Mathf.Sqrt(rhs2.sqrMagnitude * ray.LengthSqr())); } priority = num7; t = u2; result = true; if (num7 < num8m * num8m) { isMasked = true; } } } if (atOffsetSide && num6 < max) { float num9 = vector2.y + num6 - max; if (Mathf.Max(ray.a.y, ray.b.y) > num9 && Mathf.Min(ray.a.y, ray.b.y) < vector2.y) { float num10; if (Segment1.Intersect(ray.a.y, ray.b.y, vector2.y, out u2)) { segment2.a = VectorUtils.XZ(ray.Position(u2)); num10 = u2; } else { segment2.a = VectorUtils.XZ(ray.a); num10 = 0f; } float num11; if (Segment1.Intersect(ray.a.y, ray.b.y, num9, out u2)) { segment2.b = VectorUtils.XZ(ray.Position(u2)); num11 = u2; } else { segment2.b = VectorUtils.XZ(ray.b); num11 = 1f; } num7 = segment2.DistanceSqr(VectorUtils.XZ(vector2), out u2); if (num7 < priority && num7 < num8 * num8) { u2 = num10 + (num11 - num10) * u2; Vector3 lhs = ray.Position(u2); if (flag && i == 1 && v2 < 0.001f) { Vector3 rhs3 = segment.a - segment.b; u2 += Mathf.Max(0f, Vector3.Dot(lhs, rhs3)) / Mathf.Max(0.001f, Mathf.Sqrt(rhs3.sqrMagnitude * ray.LengthSqr())); } if (flag2 && i == 16 && v2 > 0.999f) { Vector3 rhs4 = segment.b - segment.a; u2 += Mathf.Max(0f, Vector3.Dot(lhs, rhs4)) / Mathf.Max(0.001f, Mathf.Sqrt(rhs4.sqrMagnitude * ray.LengthSqr())); } priority = num7; t = u2; result = true; if (num7 < num8m * num8m) { isMasked = true; } } } } segment.a = segment.b; } priority = Mathf.Max(0f, Mathf.Sqrt(priority) - collisionHalfWidth); if (isMasked) { result = false; } return(result); }
public static bool Prefix(ref NetSegment __instance, ushort segmentID, Quad2 quad, float minY, float maxY, ItemClass.CollisionType collisionType) { if ((__instance.m_flags & (NetSegment.Flags.Created | NetSegment.Flags.Deleted)) != NetSegment.Flags.Created) { return(false); } NetInfo info = __instance.Info; if (!info.m_canCollide) { return(false); } float collisionHalfWidth = info.m_netAI.GetCollisionHalfWidth(); Vector2 vector = quad.Min(); Vector2 vector2 = quad.Max(); Bezier3 bezier = default(Bezier3); bezier.a = Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_startNode].m_position; bezier.d = Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_endNode].m_position; // NON-STOCK CODE STARTS if (CSURUtil.IsCSUROffset(Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_startNode].Info)) { var width = (Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_startNode].Info.m_halfWidth + Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_startNode].Info.m_pavementWidth) / 2f; bool lht = false; Vector3 direction = __instance.m_startDirection; if ((__instance.m_flags & NetSegment.Flags.Invert) != 0) { lht = true; } // normal to the right hand side Vector3 normal = new Vector3(direction.z, 0, -direction.x).normalized; bezier.a = bezier.a + (lht ? -width : width) * normal; } if (CSURUtil.IsCSUROffset(Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_endNode].Info)) { bool lht = false; var width = (Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_endNode].Info.m_halfWidth + Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_endNode].Info.m_pavementWidth) / 2f; Vector3 direction = -__instance.m_endDirection; if ((__instance.m_flags & NetSegment.Flags.Invert) != 0) { lht = true; } // normal to the right hand side Vector3 normal = new Vector3(direction.z, 0, -direction.x).normalized; bezier.d = bezier.d + (lht ? -width : width) * normal; } // NON-STOCK CODE ENDS NetSegment.CalculateMiddlePoints(bezier.a, __instance.m_startDirection, bezier.d, __instance.m_endDirection, true, true, out bezier.b, out bezier.c); // NON-STOCK CODE STARTS float laneOffsetS = 0; float startOffsetS = 0; float endOffsetS = 0; bool IsCSURSLaneS = CSURUtil.IsCSURSLane(Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_startNode].Info, ref laneOffsetS, ref startOffsetS, ref endOffsetS); float laneOffsetE = 0; float startOffsetE = 0; float endOffsetE = 0; bool IsCSURSLaneE = CSURUtil.IsCSURSLane(Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_endNode].Info, ref laneOffsetE, ref startOffsetE, ref endOffsetE); Vector3 newBezierA1 = Vector3.zero; Vector3 newBezierB1 = Vector3.zero; Vector3 newBezierC1 = Vector3.zero; Vector3 newBezierD1 = Vector3.zero; if (IsCSURSLaneS || IsCSURSLaneE) { float vehicleLaneNum = CSURUtil.CountCSURSVehicleLanes(Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_startNode].Info); float otherLaneNum = CSURUtil.CountCSURSOtherLanes(Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_startNode].Info); float laneNum = vehicleLaneNum + otherLaneNum; startOffsetS = startOffsetS * 3.75f - laneNum * 1.875f + 1.875f + otherLaneNum * 3.75f; endOffsetE = endOffsetE * 3.75f - laneNum * 1.875f + 1.875f + otherLaneNum * 3.75f; if ((__instance.m_flags & NetSegment.Flags.Invert) != 0) { startOffsetS = -startOffsetS; endOffsetE = -endOffsetE; } if (!IsCSURSLaneS) { startOffsetS = 0; } if (!IsCSURSLaneE) { endOffsetE = 0; } //EG: before patch: point1-point4 is 1.5*3.75 //After patch, point1-point4 is (1 1.3333 1.6667 2)*3.75 newBezierA1 = bezier.a + (new Vector3(__instance.m_startDirection.z, 0, -__instance.m_startDirection.x).normalized) * (startOffsetS); Vector3 newBezierBDir = VectorUtils.NormalizeXZ(bezier.Tangent(0.333f)); newBezierB1 = bezier.b + (new Vector3(newBezierBDir.z, 0, -newBezierBDir.x).normalized) * (startOffsetS * 0.667f + endOffsetE * 0.333f); Vector3 newBezierCDir = VectorUtils.NormalizeXZ(bezier.Tangent(0.667f)); newBezierC1 = bezier.c + (new Vector3(newBezierCDir.z, 0, -newBezierCDir.x).normalized) * (startOffsetS * 0.333f + endOffsetE * 0.667f); newBezierD1 = bezier.d + (new Vector3(-__instance.m_endDirection.z, 0, __instance.m_endDirection.x).normalized) * (endOffsetE); bezier.a = newBezierA1; bezier.b = newBezierB1; bezier.c = newBezierC1; bezier.d = newBezierD1; } // NON-STOCK CODE ENDS Vector3 vector3 = bezier.Min() + new Vector3(0f - collisionHalfWidth, info.m_minHeight, 0f - collisionHalfWidth); Vector3 vector4 = bezier.Max() + new Vector3(collisionHalfWidth, info.m_maxHeight, collisionHalfWidth); ItemClass.CollisionType collisionType2 = info.m_netAI.GetCollisionType(); if (vector3.x <= vector2.x && vector3.z <= vector2.y && vector.x <= vector4.x && vector.y <= vector4.z && ItemClass.CheckCollisionType(minY, maxY, vector3.y, vector4.y, collisionType, collisionType2)) { int num = 16; info.m_netAI.GetTerrainModifyRange(out float start, out float end); start *= 0.5f; end = 1f - (1f - end) * 0.5f; float t = start; Vector3 vector5 = bezier.Position(t); Vector3 vector6 = bezier.Tangent(t); vector6 = new Vector3(0f - vector6.z, 0f, vector6.x).normalized *collisionHalfWidth; Vector3 a = vector5 + vector6; Vector3 vector7 = vector5 - vector6; float endRadius = info.m_netAI.GetEndRadius(); if (info.m_clipSegmentEnds && endRadius != 0f && start == 0f && (Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_startNode].m_flags & (NetNode.Flags.End | NetNode.Flags.Bend | NetNode.Flags.Junction)) != 0) { Vector3 vector8 = vector5; vector8.x += vector6.x * 0.8f - vector6.z * 0.6f * endRadius / collisionHalfWidth; vector8.z += vector6.z * 0.8f + vector6.x * 0.6f * endRadius / collisionHalfWidth; Vector3 vector9 = vector5; vector9.x -= vector6.x * 0.8f + vector6.z * 0.6f * endRadius / collisionHalfWidth; vector9.z -= vector6.z * 0.8f - vector6.x * 0.6f * endRadius / collisionHalfWidth; Vector3 d = vector5; d.x += vector6.x * 0.3f - vector6.z * endRadius / collisionHalfWidth; d.z += vector6.z * 0.3f + vector6.x * endRadius / collisionHalfWidth; Vector3 c = vector5; c.x -= vector6.x * 0.3f + vector6.z * endRadius / collisionHalfWidth; c.z -= vector6.z * 0.3f - vector6.x * endRadius / collisionHalfWidth; vector3.y = vector5.y + info.m_minHeight; vector4.y = vector5.y + info.m_maxHeight; if (ItemClass.CheckCollisionType(minY, maxY, vector3.y, vector4.y, collisionType, collisionType2)) { if (quad.Intersect(Quad2.XZ(a, vector7, vector9, vector8))) { return(true); } if (quad.Intersect(Quad2.XZ(vector8, vector9, c, d))) { return(true); } } } for (int i = 1; i <= num; i++) { t = start + (end - start) * (float)i / (float)num; vector5 = bezier.Position(t); vector6 = bezier.Tangent(t); vector6 = new Vector3(0f - vector6.z, 0f, vector6.x).normalized *collisionHalfWidth; Vector3 vector10 = vector5 + vector6; Vector3 vector11 = vector5 - vector6; vector3.y = Mathf.Min(Mathf.Min(a.y, vector10.y), Mathf.Min(vector11.y, vector7.y)) + info.m_minHeight; vector4.y = Mathf.Max(Mathf.Max(a.y, vector10.y), Mathf.Max(vector11.y, vector7.y)) + info.m_maxHeight; if (ItemClass.CheckCollisionType(minY, maxY, vector3.y, vector4.y, collisionType, collisionType2) && quad.Intersect(Quad2.XZ(a, vector10, vector11, vector7))) { return(true); } a = vector10; vector7 = vector11; } if (info.m_clipSegmentEnds && endRadius != 0f && end == 1f && (Singleton <NetManager> .instance.m_nodes.m_buffer[__instance.m_endNode].m_flags & (NetNode.Flags.End | NetNode.Flags.Bend | NetNode.Flags.Junction)) != 0) { Vector3 vector12 = vector5; vector12.x += vector6.x * 0.8f + vector6.z * 0.6f * endRadius / collisionHalfWidth; vector12.z += vector6.z * 0.8f - vector6.x * 0.6f * endRadius / collisionHalfWidth; Vector3 vector13 = vector5; vector13.x -= vector6.x * 0.8f - vector6.z * 0.6f * endRadius / collisionHalfWidth; vector13.z -= vector6.z * 0.8f + vector6.x * 0.6f * endRadius / collisionHalfWidth; Vector3 b = vector5; b.x += vector6.x * 0.3f + vector6.z * endRadius / collisionHalfWidth; b.z += vector6.z * 0.3f - vector6.x * endRadius / collisionHalfWidth; Vector3 c2 = vector5; c2.x -= vector6.x * 0.3f - vector6.z * endRadius / collisionHalfWidth; c2.z -= vector6.z * 0.3f + vector6.x * endRadius / collisionHalfWidth; vector3.y = vector5.y + info.m_minHeight; vector4.y = vector5.y + info.m_maxHeight; if (ItemClass.CheckCollisionType(minY, maxY, vector3.y, vector4.y, collisionType, collisionType2)) { if (quad.Intersect(Quad2.XZ(a, vector12, vector13, vector7))) { return(true); } if (quad.Intersect(Quad2.XZ(vector12, b, c2, vector13))) { return(true); } } } } return(false); }
public abstract IEnumerable <MarkupStyleDash> Calculate(Bezier3 trajectory);
public static float DeltaAngle(this Bezier3 bezier) => 180 - Vector3.Angle(bezier.b - bezier.a, bezier.c - bezier.d);
public BezierTrajectory(Bezier3 trajectory) { Trajectory = trajectory; }
private bool TrySnapNodeDirections(ushort node, Vector3 newPosition, Vector3 moveDelta, out Vector3 newMoveDelta, out bool autoCurve) { string snapType = ""; m_segmentGuide = default; NetManager netManager = NetManager.instance; NetSegment[] segmentBuffer = netManager.m_segments.m_buffer; NetNode[] nodeBuffer = netManager.m_nodes.m_buffer; float minSqDistance = nodeBuffer[node].Info.GetMinNodeDistance() / 2f; minSqDistance *= minSqDistance; autoCurve = false; newMoveDelta = moveDelta; float distanceSq = minSqDistance; bool snap = false; // Snap to curve for (int i = 0; i < 8; i++) { ushort segmentA = nodeBuffer[node].GetSegment(i); if (segmentA != 0) { for (int j = i + 1; j < 8; j++) { ushort segmentB = nodeBuffer[node].GetSegment(j); if (segmentB != 0 && segmentB != segmentA) { NetSegment segment = default; segment.m_startNode = segmentBuffer[segmentA].m_startNode == node ? segmentBuffer[segmentA].m_endNode : segmentBuffer[segmentA].m_startNode; segment.m_endNode = segmentBuffer[segmentB].m_startNode == node ? segmentBuffer[segmentB].m_endNode : segmentBuffer[segmentB].m_startNode; segment.m_startDirection = (nodeBuffer[segment.m_endNode].m_position - nodeBuffer[segment.m_startNode].m_position).normalized; segment.m_endDirection = -segment.m_startDirection; segment.GetClosestPositionAndDirection(newPosition, out Vector3 testPos, out Vector3 direction); // Straight if (TrySnapping(testPos, newPosition, minSqDistance, ref distanceSq, moveDelta, ref newMoveDelta)) { autoCurve = true; m_segmentGuide = segment; snapType = "Straight"; snap = true; } for (int k = 0; k < 8; k++) { ushort segmentC = nodeBuffer[segment.m_startNode].GetSegment(k); if (segmentC != 0 && segmentC != segmentA) { for (int l = 0; l < 8; l++) { ushort segmentD = nodeBuffer[segment.m_endNode].GetSegment(l); if (segmentD != 0 && segmentD != segmentB) { segment.m_startDirection = segmentBuffer[segmentC].m_startNode == segment.m_startNode ? -segmentBuffer[segmentC].m_startDirection : -segmentBuffer[segmentC].m_endDirection; segment.m_endDirection = segmentBuffer[segmentD].m_startNode == segment.m_endNode ? -segmentBuffer[segmentD].m_startDirection : -segmentBuffer[segmentD].m_endDirection; Vector2 A = VectorUtils.XZ(nodeBuffer[segment.m_endNode].m_position - nodeBuffer[segment.m_startNode].m_position).normalized; Vector2 B = VectorUtils.XZ(segment.m_startDirection); float side1 = A.x * B.y - A.y * B.x; B = VectorUtils.XZ(segment.m_endDirection); float side2 = A.x * B.y - A.y * B.x; if (Mathf.Sign(side1) != Mathf.Sign(side2) || (side1 != side2 && (side1 == 0 || side2 == 0)) || Vector2.Dot(A, VectorUtils.XZ(segment.m_startDirection)) < 0 || Vector2.Dot(A, VectorUtils.XZ(segment.m_endDirection)) > 0) { continue; } Bezier3 bezier = default; bezier.a = Singleton <NetManager> .instance.m_nodes.m_buffer[segment.m_startNode].m_position; bezier.d = Singleton <NetManager> .instance.m_nodes.m_buffer[segment.m_endNode].m_position; bool smoothStart = (Singleton <NetManager> .instance.m_nodes.m_buffer[segment.m_startNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; bool smoothEnd = (Singleton <NetManager> .instance.m_nodes.m_buffer[segment.m_endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; NetSegment.CalculateMiddlePoints(bezier.a, segment.m_startDirection, bezier.d, segment.m_endDirection, smoothStart, smoothEnd, out bezier.b, out bezier.c); testPos = bezier.Position(0.5f); // Curve Middle if (TrySnapping(testPos, newPosition, minSqDistance, ref distanceSq, moveDelta, ref newMoveDelta)) { autoCurve = true; m_segmentGuide = segment; snapType = "Curve Middle"; snap = true; } else { segment.GetClosestPositionAndDirection(newPosition, out testPos, out direction); // Curve if (TrySnapping(testPos, newPosition, minSqDistance, ref distanceSq, moveDelta, ref newMoveDelta)) { autoCurve = true; m_segmentGuide = segment; snapType = "Curve"; snap = true; } } } } } } } } } } // Snap to tangent for (int i = 0; i < 8; i++) { ushort segment = nodeBuffer[node].GetSegment(i); if (segment != 0) { ushort testNode = segmentBuffer[segment].m_startNode == node ? segmentBuffer[segment].m_endNode : segmentBuffer[segment].m_startNode; Vector3 testPos = nodeBuffer[testNode].m_position; for (int j = 0; j < 8; j++) { ushort segmentA = nodeBuffer[testNode].GetSegment(j); if (segmentA != 0 && segmentA != segment) { // Straight Vector3 startDir = segmentBuffer[segmentA].m_startNode == testNode ? segmentBuffer[segmentA].m_startDirection : segmentBuffer[segmentA].m_endDirection; Vector3 offset = Line2.Offset(startDir, testPos - newPosition); offset = newPosition + offset - testPos; float num = offset.x * startDir.x + offset.z * startDir.z; if (TrySnapping(testPos + startDir * num, newPosition, minSqDistance, ref distanceSq, moveDelta, ref newMoveDelta)) { m_segmentGuide = default; m_segmentGuide.m_startNode = node; m_segmentGuide.m_endNode = testNode; m_segmentGuide.m_startDirection = startDir; m_segmentGuide.m_endDirection = -startDir; snapType = "Tangent Straight"; autoCurve = false; snap = true; } else { // 90° startDir = new Vector3(-startDir.z, startDir.y, startDir.x); offset = Line2.Offset(startDir, testPos - newPosition); offset = newPosition + offset - testPos; num = offset.x * startDir.x + offset.z * startDir.z; if (TrySnapping(testPos + startDir * num, newPosition, minSqDistance, ref distanceSq, moveDelta, ref newMoveDelta)) { m_segmentGuide = default; m_segmentGuide.m_startNode = node; m_segmentGuide.m_endNode = testNode; m_segmentGuide.m_startDirection = startDir; m_segmentGuide.m_endDirection = -startDir; snapType = "Tangent 90°"; autoCurve = false; snap = true; } } } } } } if (snap) { DebugUtils.Log("Snapping " + snapType + " " + autoCurve); } return(snap); }
private osmWay AddWay(int i, NetSegment netSegment) { var nm = Singleton<NetManager>.instance; if (netSegment.m_startNode == 0 || netSegment.m_endNode == 0) { return null; } var startNode = netSegment.m_startNode; var endNode = netSegment.m_endNode; var startDirection = netSegment.m_startDirection; var endDirection = netSegment.m_endDirection; if ((netSegment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None) { startNode = netSegment.m_endNode; endNode = netSegment.m_startNode; startDirection = netSegment.m_endDirection; endDirection = netSegment.m_startDirection; } osmWayND[] nd; if (Vector3.Angle(startDirection, -endDirection) > 3f) { var start = nm.m_nodes.m_buffer[startNode].m_position; var end = nm.m_nodes.m_buffer[endNode].m_position; Vector3 a = Vector3.zero; Vector3 b = Vector3.zero; NetSegment.CalculateMiddlePoints(start, startDirection, end, endDirection, false, false, out a, out b); var bezier = new Bezier3(start, a, b, end); nd = new osmWayND[5]; nd[0] = new osmWayND { @ref = startNode }; nd[1] = new osmWayND { @ref = AddNode(bezier.Position(0.25f)) }; nd[2] = new osmWayND { @ref = AddNode(bezier.Position(0.5f)) }; nd[3] = new osmWayND { @ref = AddNode(bezier.Position(0.75f)) }; nd[4] = new osmWayND { @ref = endNode }; } else { nd = new osmWayND[2]; nd[0] = new osmWayND { @ref = startNode }; nd[1] = new osmWayND { @ref = endNode }; } byte elevation = (byte)(Mathf.Clamp((nm.m_nodes.m_buffer[startNode].m_elevation + nm.m_nodes.m_buffer[endNode].m_elevation) / 2, 0, 255)); var tags = new List<osmWayTag>(); if (!mapping.GetTags(elevation, netSegment, tags)) { return null; } return new osmWay { changeset = 50000000, id = (uint)i, timestamp = DateTime.Now, user = "******", version = 1, nd = nd, tag = tags.ToArray() }; }
private static bool Intersect(List <MarkupIntersect> results, Bezier3 first, Bezier3 second, int fIdx = 0, int fOf = 1, int sIdx = 0, int sOf = 1) { CalcParts(first, out int fParts, out float[] fPoints, out Vector3[] fPos);
private List<Vector2> BezierToPoints(List<Segment> list) { var result = new List<Vector2>(); result.Add(list[0].startPoint); foreach (var seg in list) { if (seg.controlA == Vector2.zero) { result.Add(seg.endPoint); } else { var bezier = new Bezier3(seg.startPoint,seg.controlA,seg.controlB,seg.endPoint); var steps = Mathf.RoundToInt((seg.endPoint - seg.startPoint).magnitude / 50) + 1; for (var i = 0; i <= steps; i += 1) { if (i == 0) { continue; } result.Add(bezier.Position(i / (float)steps)); } } } return result; }
private OSMWay CreateWay(int index, NetSegment segment, ushort segmentId) { OSMWay returnWay = null; NetSegment.Flags segmentFlags = segment.m_flags; NetManager netManager = Singleton<NetManager>.instance; List<OSMWayND> wayPaths = new List<OSMWayND>(); List<OSMWayTag> wayTags; ushort startNodeId = segment.m_startNode, endNodeId = segment.m_endNode; if(startNodeId != 0 && endNodeId != 0) { Vector3 startNodeDirection = segment.m_startDirection; Vector3 endNodeDirection = segment.m_endDirection; if(segmentFlags.IsFlagSet(NetSegment.Flags.Invert)) { startNodeId = segment.m_endNode; endNodeId = segment.m_startNode; startNodeDirection = segment.m_endDirection; endNodeDirection = segment.m_startDirection; } NetNode startNode = netManager.m_nodes.m_buffer[startNodeId]; NetNode endNode = netManager.m_nodes.m_buffer[endNodeId]; Vector3 startNodePosition = startNode.m_position; Vector3 endNodePosition = endNode.m_position; wayPaths.Add(new OSMWayND { @ref = startNodeId }); if (Vector3.Angle(startNodeDirection, -endNodeDirection) > 3f) { Vector3 midPointA = Vector3.zero, midPointB = Vector3.zero; NetSegment.CalculateMiddlePoints(startNodePosition, startNodeDirection, endNodePosition, endNodeDirection, false, false, out midPointA, out midPointB); Bezier3 bezier = new Bezier3(startNodePosition, midPointA, midPointB, endNodePosition); osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.25f))); osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.5f))); osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.75f))); wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 3 }); wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 2 }); wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 1 }); } wayPaths.Add(new OSMWayND { @ref = endNodeId }); if(Tagger.CreateWayTags(segment, out wayTags)) { if (haveRoadNamerMod) { // If road namer mod is available, then attempt to get the name asscociated with the segment, if any string roadName = RoadNamerManager.Instance().getSegmentName((ushort)(segmentId)); if (roadName != null) { //If a name is available, add a name tag wayTags.Add(new OSMWayTag { k = "name", v = StringUtilities.RemoveTags(roadName) }); } } returnWay = new OSMWay { changeset = 50000000, id = (uint)index, timestamp = DateTime.Now, user = "******", nd = wayPaths.ToArray(), tag = wayTags.ToArray(), version = 1 }; } else { UniqueLogger.AddLog("Road names missing from search", segment.Info.name, ""); } } return returnWay; }
/// <summary> /// Initializes/recalculates bezier bounds. /// </summary> /// <param name="hitH">vertical raycast hit position.</param> private void CalculateBounds(float hitH) { // maximum vertical postion of the bezier. float maxH = Mathf.Max(raycastBezier.a.y, raycastBezier.d.y); float mouseH = UIBase.GetTrafficManagerTool(false).MousePosition.y; if ((hitH == prev_H || hitH == maxH || prev_H == mouseH) && bounds != null) { // use cached results if mouse has not moved or hitH is ignored. return; } Bezier3 bezier0 = raycastBezier; if (hitH < mouseH - MAX_HIT_ERROR) { // For Metros use projection on the terrain. bezier0.a.y = bezier0.b.y = bezier0.c.y = bezier0.d.y = mouseH; prev_H = mouseH; } else if (hitH > maxH + MAX_HIT_ERROR) { // if marker is projected on another road plane then modify its height bezier0.a.y = bezier0.b.y = bezier0.c.y = bezier0.d.y = hitH; prev_H = hitH; } else { // ignore hitH prev_H = maxH; } float angle = Vector3.Angle(bezier0.a, bezier0.b); if (Mathf.Approximately(angle, 0f) || Mathf.Approximately(angle, 180f)) { angle = Vector3.Angle(bezier0.b, bezier0.c); if (Mathf.Approximately(angle, 0f) || Mathf.Approximately(angle, 180f)) { angle = Vector3.Angle(bezier0.c, bezier0.d); if (Mathf.Approximately(angle, 0f) || Mathf.Approximately(angle, 180f)) { // linear bezier Bounds bounds = bezier0.GetBounds(); bounds.Expand(0.4f); this.bounds = new Bounds[] { bounds }; return; } } } // split bezier in 10 parts to correctly raycast curves int n = 10; bounds = new Bounds[n]; float size = 1f / n; for (int i = 0; i < n; i++) { Bezier3 bezier = bezier0.Cut(i * size, (i + 1) * size); Bounds bounds = bezier.GetBounds(); bounds.Expand(1f); this.bounds[i] = bounds; } }
private void CreateZoneBlocks(int segment, ref NetSegment data, NetInfo info) { var instance = Singleton<NetManager>.instance; var randomizer = new Randomizer(segment); var position = instance.m_nodes.m_buffer[data.m_startNode].m_position; var position2 = instance.m_nodes.m_buffer[data.m_endNode].m_position; var startDirection = data.m_startDirection; var endDirection = data.m_endDirection; var num = startDirection.x * endDirection.x + startDirection.z * endDirection.z; var flag = !NetSegment.IsStraight(position, startDirection, position2, endDirection); var num2 = Mathf.Max(8f, info.m_halfWidth); var num3 = 32f; if (flag) { var num4 = VectorUtils.LengthXZ(position2 - position); var flag2 = startDirection.x * endDirection.z - startDirection.z * endDirection.x > 0f; var flag3 = num < -0.8f || num4 > 50f; if (flag2) { num2 = -num2; num3 = -num3; } var vector = position - new Vector3(startDirection.z, 0f, -startDirection.x) * num2; var vector2 = position2 + new Vector3(endDirection.z, 0f, -endDirection.x) * num2; Vector3 vector3; Vector3 vector4; NetSegment.CalculateMiddlePoints(vector, startDirection, vector2, endDirection, true, true, out vector3, out vector4); if (flag3) { var num5 = num * 0.025f + 0.04f; var num6 = num * 0.025f + 0.06f; if (num < -0.9f) { num6 = num5; } var bezier = new Bezier3(vector, vector3, vector4, vector2); vector = bezier.Position(num5); vector3 = bezier.Position(0.5f - num6); vector4 = bezier.Position(0.5f + num6); vector2 = bezier.Position(1f - num5); } else { var bezier2 = new Bezier3(vector, vector3, vector4, vector2); vector3 = bezier2.Position(0.86f); vector = bezier2.Position(0.14f); } float num7; var vector5 = VectorUtils.NormalizeXZ(vector3 - vector, out num7); var num8 = Mathf.FloorToInt(num7 / 8f + 0.01f); var num9 = num7 * 0.5f + (num8 - 8) * ((!flag2) ? -4f : 4f); if (num8 != 0) { var angle = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z); var position3 = vector + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3); if (flag2) { Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartRight, ref randomizer, position3, angle, num8, data.m_buildIndex); } else { Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartLeft, ref randomizer, position3, angle, num8, data.m_buildIndex); } } if (flag3) { vector5 = VectorUtils.NormalizeXZ(vector2 - vector4, out num7); num8 = Mathf.FloorToInt(num7 / 8f + 0.01f); num9 = num7 * 0.5f + (num8 - 8) * ((!flag2) ? -4f : 4f); if (num8 != 0) { var angle2 = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z); var position4 = vector4 + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3); if (flag2) { Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndRight, ref randomizer, position4, angle2, num8, data.m_buildIndex + 1u); } else { Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndLeft, ref randomizer, position4, angle2, num8, data.m_buildIndex + 1u); } } } var vector6 = position + new Vector3(startDirection.z, 0f, -startDirection.x) * num2; var vector7 = position2 - new Vector3(endDirection.z, 0f, -endDirection.x) * num2; Vector3 b; Vector3 c; NetSegment.CalculateMiddlePoints(vector6, startDirection, vector7, endDirection, true, true, out b, out c); var bezier3 = new Bezier3(vector6, b, c, vector7); var vector8 = bezier3.Position(0.5f); var vector9 = bezier3.Position(0.25f); vector9 = Line2.Offset(VectorUtils.XZ(vector6), VectorUtils.XZ(vector8), VectorUtils.XZ(vector9)); var vector10 = bezier3.Position(0.75f); vector10 = Line2.Offset(VectorUtils.XZ(vector7), VectorUtils.XZ(vector8), VectorUtils.XZ(vector10)); var vector11 = vector6; var a = vector7; float d; float num10; if (Line2.Intersect(VectorUtils.XZ(position), VectorUtils.XZ(vector6), VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), out d, out num10)) { vector6 = position + (vector6 - position) * d; } if (Line2.Intersect(VectorUtils.XZ(position2), VectorUtils.XZ(vector7), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10)) { vector7 = position2 + (vector7 - position2) * d; } if (Line2.Intersect(VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10)) { vector8 = vector11 - vector9 + (vector8 - vector11) * d; } float num11; var vector12 = VectorUtils.NormalizeXZ(vector8 - vector6, out num11); var num12 = Mathf.FloorToInt(num11 / 8f + 0.01f); var num13 = num11 * 0.5f + (num12 - 8) * ((!flag2) ? 4f : -4f); if (num12 != 0) { var angle3 = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z); var position5 = vector6 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3); if (flag2) { Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartLeft, ref randomizer, position5, angle3, num12, data.m_buildIndex); } else { Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartRight, ref randomizer, position5, angle3, num12, data.m_buildIndex); } } vector12 = VectorUtils.NormalizeXZ(vector7 - vector8, out num11); num12 = Mathf.FloorToInt(num11 / 8f + 0.01f); num13 = num11 * 0.5f + (num12 - 8) * ((!flag2) ? 4f : -4f); if (num12 == 0) return; var angle4 = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z); var position6 = vector8 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3); if (flag2) { Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndLeft, ref randomizer, position6, angle4, num12, data.m_buildIndex + 1u); } else { Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndRight, ref randomizer, position6, angle4, num12, data.m_buildIndex + 1u); } } else { num2 += num3; var vector13 = new Vector2(position2.x - position.x, position2.z - position.z); var magnitude = vector13.magnitude; var num14 = Mathf.FloorToInt(magnitude / 8f + 0.1f); var num15 = (num14 <= 8) ? num14 : (num14 + 1 >> 1); var num16 = (num14 <= 8) ? 0 : (num14 >> 1); if (num15 > 0) { var num17 = Mathf.Atan2(startDirection.x, -startDirection.z); var position7 = position + new Vector3(startDirection.x * 32f - startDirection.z * num2, 0f, startDirection.z * 32f + startDirection.x * num2); Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartLeft, ref randomizer, position7, num17, num15, data.m_buildIndex); position7 = position + new Vector3(startDirection.x * (num15 - 4) * 8f + startDirection.z * num2, 0f, startDirection.z * (num15 - 4) * 8f - startDirection.x * num2); Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartRight, ref randomizer, position7, num17 + 3.14159274f, num15, data.m_buildIndex); } if (num16 <= 0) return; var num18 = magnitude - num14 * 8f; var num19 = Mathf.Atan2(endDirection.x, -endDirection.z); var position8 = position2 + new Vector3(endDirection.x * (32f + num18) - endDirection.z * num2, 0f, endDirection.z * (32f + num18) + endDirection.x * num2); Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndLeft, ref randomizer, position8, num19, num16, data.m_buildIndex + 1u); position8 = position2 + new Vector3(endDirection.x * ((num16 - 4) * 8f + num18) + endDirection.z * num2, 0f, endDirection.z * ((num16 - 4) * 8f + num18) - endDirection.x * num2); Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndRight, ref randomizer, position8, num19 + 3.14159274f, num16, data.m_buildIndex + 1u); } }
private static List <NodeLaneMarker> GetNodeMarkers(ushort nodeId, ref NetNode node) { if (nodeId == 0) { return(null); } if ((node.m_flags & NetNode.Flags.Created) == NetNode.Flags.None) { return(null); } List <NodeLaneMarker> nodeMarkers = new List <NodeLaneMarker>(); int nodeMarkerColorIndex = 0; LaneConnectionManager connManager = LaneConnectionManager.Instance; int offsetMultiplier = node.CountSegments() <= 2 ? 3 : 1; for (int i = 0; i < 8; i++) { ushort segmentId = node.GetSegment(i); if (segmentId == 0) { continue; } NetSegment[] segmentsBuffer = NetManager.instance.m_segments.m_buffer; bool startNode = segmentsBuffer[segmentId].m_startNode == nodeId; Vector3 offset = segmentsBuffer[segmentId] .FindDirection(segmentId, nodeId) * offsetMultiplier; NetInfo.Lane[] lanes = segmentsBuffer[segmentId].Info.m_lanes; uint laneId = segmentsBuffer[segmentId].m_lanes; for (byte laneIndex = 0; (laneIndex < lanes.Length) && (laneId != 0); laneIndex++) { NetInfo.Lane laneInfo = lanes[laneIndex]; if (((laneInfo.m_laneType & LaneConnectionManager.LANE_TYPES) != NetInfo.LaneType.None) && ((laneInfo.m_vehicleType & LaneConnectionManager.VEHICLE_TYPES) != VehicleInfo.VehicleType.None)) { if (connManager.GetLaneEndPoint( segmentId, startNode, laneIndex, laneId, laneInfo, out bool isSource, out bool isTarget, out Vector3? pos)) { pos = pos.Value + offset; float terrainY = Singleton <TerrainManager> .instance.SampleDetailHeightSmooth(pos.Value); var finalPos = new Vector3(pos.Value.x, terrainY, pos.Value.z); Color32 nodeMarkerColor = isSource ? COLOR_CHOICES[nodeMarkerColorIndex % COLOR_CHOICES.Length] : default; // or black (not used while rendering) NetLane lane = NetManager.instance.m_lanes.m_buffer[laneId]; Bezier3 bezier = lane.m_bezier; if (startNode) { bezier.a = (Vector3)pos; } else { bezier.d = (Vector3)pos; } SegmentLaneMarker segmentLaneMarker = new SegmentLaneMarker { renderBezier = bezier, raycastBezier = bezier, laneID = laneId, laneIndex = laneIndex, }; nodeMarkers.Add( new NodeLaneMarker { SegmentId = segmentId, LaneId = laneId, NodeId = nodeId, StartNode = startNode, Position = finalPos, SecondaryPosition = (Vector3)pos, Color = nodeMarkerColor, IsSource = isSource, IsTarget = isTarget, LaneType = laneInfo.m_laneType, VehicleType = laneInfo.m_vehicleType, InnerSimilarLaneIndex = ((byte)(laneInfo.m_direction & NetInfo.Direction.Forward) != 0) ? laneInfo.m_similarLaneIndex : laneInfo.m_similarLaneCount - laneInfo.m_similarLaneIndex - 1, SegmentIndex = i, segmentLaneMarker = segmentLaneMarker, }); if (isSource) { nodeMarkerColorIndex++; } } } laneId = NetManager.instance.m_lanes.m_buffer[laneId].m_nextLane; } } if (nodeMarkers.Count == 0) { return(null); } foreach (NodeLaneMarker laneMarker1 in nodeMarkers) { if (!laneMarker1.IsSource) { continue; } uint[] connections = LaneConnectionManager.Instance.GetLaneConnections( laneMarker1.LaneId, laneMarker1.StartNode); if ((connections == null) || (connections.Length == 0)) { continue; } foreach (NodeLaneMarker laneMarker2 in nodeMarkers) { if (!laneMarker2.IsTarget) { continue; } if (connections.Contains(laneMarker2.LaneId)) { laneMarker1.ConnectedMarkers.Add(laneMarker2); } } } return(nodeMarkers); }