/// <summary> /// Initializes/recalculates bezier bounds. /// </summary> /// <param name="hitH">vertical raycast hit position.</param> private void CalculateBounds() { Bezier3 bezier0 = Bezier; // 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; } }
void CalculateBounds() { float angle = Vector3.Angle(m_bezier.a, m_bezier.b); if (Mathf.Approximately(angle, 0f) || Mathf.Approximately(angle, 180f)) { angle = Vector3.Angle(m_bezier.b, m_bezier.c); if (Mathf.Approximately(angle, 0f) || Mathf.Approximately(angle, 180f)) { angle = Vector3.Angle(m_bezier.c, m_bezier.d); if (Mathf.Approximately(angle, 0f) || Mathf.Approximately(angle, 180f)) { // linear bezier Bounds bounds = m_bezier.GetBounds(); bounds.Expand(1f); m_bounds = new Bounds[] { bounds }; return; } } } // split bezier in 10 parts to correctly raycast curves Bezier3 bezier; int amount = 10; m_bounds = new Bounds[amount]; float size = 1f / amount; for (int i = 0; i < amount; i++) { bezier = m_bezier.Cut(i * size, (i + 1) * size); Bounds bounds = bezier.GetBounds(); bounds.Expand(1f); m_bounds[i] = bounds; } }
/// <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; } }
public static bool Prefix(ref NetSegment __instance, ushort segmentID, Segment3 ray, float snapElevation, bool nameOnly, out float t, out float priority, ref bool __result) { // NON-STOCK CODE STARTS float laneOffset = 0; float startOffset = 0; float endOffset = 0; bool IsCSURSLane = CSURUtil.IsCSURSLane(__instance.Info.m_netAI.m_info, ref laneOffset, ref startOffset, ref endOffset); if (CSURUtil.IsCSUROffset(__instance.Info.m_netAI.m_info) && !IsCSURSLane) { __result = NetSegmentRayCastMasked(__instance, segmentID, ray, -1000f, false, out t, out priority); return(false); } // NON-STOCK CODE ENDS NetInfo info = __instance.Info; t = 0f; priority = 0f; if (nameOnly && (__instance.m_flags & NetSegment.Flags.NameVisible2) == NetSegment.Flags.None) { __result = false; return(false); } Bounds bounds = __instance.m_bounds; bounds.Expand(16f); if (!bounds.IntersectRay(new Ray(ray.a, ray.b - ray.a))) { __result = false; return(false); } NetManager instance = Singleton <NetManager> .instance; Bezier3 bezier = default(Bezier3); bezier.a = instance.m_nodes.m_buffer[__instance.m_startNode].m_position; bezier.d = instance.m_nodes.m_buffer[__instance.m_endNode].m_position; bool result = false; if (nameOnly) { RenderManager instance2 = Singleton <RenderManager> .instance; if (instance2.GetInstanceIndex((uint)(49152 + segmentID), out uint instanceIndex)) { InstanceManager.NameData nameData = instance2.m_instances[instanceIndex].m_nameData; Vector3 position = instance2.m_instances[instanceIndex].m_position; Matrix4x4 dataMatrix = instance2.m_instances[instanceIndex].m_dataMatrix2; float num = Vector3.Distance(position, ray.a); if (nameData != null && num < 1000f) { float snapElevation2 = info.m_netAI.GetSnapElevation(); bezier.a.y += snapElevation2; bezier.d.y += snapElevation2; NetSegment.CalculateMiddlePoints(bezier.a, __instance.m_startDirection, bezier.d, __instance.m_endDirection, true, true, out bezier.b, out bezier.c); float num2 = Mathf.Max(1f, Mathf.Abs(dataMatrix.m33 - dataMatrix.m30)); float d = num * 0.0002f + 0.05f / (1f + num * 0.001f); Vector2 vector = nameData.m_size * d; float t2 = Mathf.Max(0f, 0.5f - vector.x / num2 * 0.5f); float t3 = Mathf.Min(1f, 0.5f + vector.x / num2 * 0.5f); bezier = bezier.Cut(t2, t3); float num3 = bezier.DistanceSqr(ray, out float u, out float _); if (num3 < vector.y * vector.y * 0.25f) { Vector3 b = bezier.Position(u); if (Segment1.Intersect(ray.a.y, ray.b.y, b.y, out u)) { num3 = Vector3.SqrMagnitude(ray.Position(u) - b); if (num3 < vector.y * vector.y * 0.25f) { t = u; result = true; } } } } } } else { info.m_netAI.GetRayCastHeights(segmentID, ref __instance, out float leftMin, out float rightMin, out float max); bezier.a.y += max; bezier.d.y += max; bool flag = (instance.m_nodes.m_buffer[__instance.m_startNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; bool flag2 = (instance.m_nodes.m_buffer[__instance.m_endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; NetSegment.CalculateMiddlePoints(bezier.a, __instance.m_startDirection, bezier.d, __instance.m_endDirection, flag, flag2, out bezier.b, out bezier.c); // NON-STOCK CODE STARTS if (IsCSURSLane) { float vehicleLaneNum = CSURUtil.CountCSURSVehicleLanes(info); float otherLaneNum = CSURUtil.CountCSURSOtherLanes(info); float laneNum = vehicleLaneNum + otherLaneNum; startOffset = startOffset * 3.75f - laneNum * 1.875f + 1.875f + otherLaneNum * 3.75f; endOffset = endOffset * 3.75f - laneNum * 1.875f + 1.875f + otherLaneNum * 3.75f; if ((__instance.m_flags & NetSegment.Flags.Invert) != 0) { startOffset = -startOffset; endOffset = -endOffset; } //EG: before patch: point1-point4 is 1.5*3.75 //After patch, point1-point4 is (1 1.3333 1.6667 2)*3.75 Vector3 newBezierA = bezier.a + (new Vector3(__instance.m_startDirection.z, 0, -__instance.m_startDirection.x).normalized) * (startOffset); Vector3 newBezierBDir = VectorUtils.NormalizeXZ(bezier.Tangent(0.333f)); Vector3 newBezierB = bezier.b + (new Vector3(newBezierBDir.z, 0, -newBezierBDir.x).normalized) * (startOffset * 0.667f + endOffset * 0.333f); Vector3 newBezierCDir = VectorUtils.NormalizeXZ(bezier.Tangent(0.667f)); Vector3 newBezierC = bezier.c + (new Vector3(newBezierCDir.z, 0, -newBezierCDir.x).normalized) * (startOffset * 0.333f + endOffset * 0.667f); Vector3 newBezierD = bezier.d + (new Vector3(-__instance.m_endDirection.z, 0, __instance.m_endDirection.x).normalized) * (endOffset); bezier.a = newBezierA; bezier.b = newBezierB; bezier.c = newBezierC; bezier.d = newBezierD; } float minNodeDistance = info.GetMinNodeDistance(); float collisionHalfWidth = info.m_netAI.GetCollisionHalfWidth(); float num4 = (float)(int)instance.m_nodes.m_buffer[__instance.m_startNode].m_elevation; float num5 = (float)(int)instance.m_nodes.m_buffer[__instance.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 num6 = Mathf.Min(leftMin, rightMin); t = 1000000f; priority = 1000000f; Segment3 segment = default(Segment3); segment.a = bezier.a; 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); Vector3 vector2 = segment.Position(v2); if (num7 < priority && Segment1.Intersect(ray.a.y, ray.b.y, vector2.y, out u2)) { Vector3 vector3 = ray.Position(u2); num7 = Vector3.SqrMagnitude(vector3 - vector2); 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 (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) { Segment2 segment2 = default(Segment2); 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; } } } segment.a = segment.b; } priority = Mathf.Max(0f, Mathf.Sqrt(priority) - collisionHalfWidth); } __result = result; return(false); }
public static bool RayCast(ref NetSegment mysegment, ushort segmentID, Segment3 ray, float snapElevation, bool nameOnly, out float t, out float priority) { if (CSUROffset.IsCSUROffset(mysegment.Info.m_netAI.m_info)) { return(NetSegmentRayCastMasked(mysegment, segmentID, ray, -1000f, false, out t, out priority)); } NetInfo info = mysegment.Info; t = 0f; priority = 0f; if (nameOnly && (mysegment.m_flags & NetSegment.Flags.NameVisible2) == NetSegment.Flags.None) { return(false); } 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; if (nameOnly) { RenderManager instance2 = Singleton <RenderManager> .instance; if (instance2.GetInstanceIndex((uint)(49152 + segmentID), out uint instanceIndex)) { InstanceManager.NameData nameData = instance2.m_instances[instanceIndex].m_nameData; Vector3 position = instance2.m_instances[instanceIndex].m_position; Matrix4x4 dataMatrix = instance2.m_instances[instanceIndex].m_dataMatrix2; float num = Vector3.Distance(position, ray.a); if (nameData != null && num < 1000f) { float snapElevation2 = info.m_netAI.GetSnapElevation(); bezier.a.y += snapElevation2; bezier.d.y += snapElevation2; NetSegment.CalculateMiddlePoints(bezier.a, mysegment.m_startDirection, bezier.d, mysegment.m_endDirection, true, true, out bezier.b, out bezier.c); float num2 = Mathf.Max(1f, Mathf.Abs(dataMatrix.m33 - dataMatrix.m30)); float d = num * 0.0002f + 0.05f / (1f + num * 0.001f); Vector2 vector = nameData.m_size * d; float t2 = Mathf.Max(0f, 0.5f - vector.x / num2 * 0.5f); float t3 = Mathf.Min(1f, 0.5f + vector.x / num2 * 0.5f); bezier = bezier.Cut(t2, t3); float num3 = bezier.DistanceSqr(ray, out float u, out float _); if (num3 < vector.y * vector.y * 0.25f) { Vector3 b = bezier.Position(u); if (Segment1.Intersect(ray.a.y, ray.b.y, b.y, out u)) { num3 = Vector3.SqrMagnitude(ray.Position(u) - b); if (num3 < vector.y * vector.y * 0.25f) { t = u; result = true; } } } } } } else { 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) != NetNode.Flags.None; bool flag2 = (instance.m_nodes.m_buffer[mysegment.m_endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None; 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_netAI.GetCollisionHalfWidth(); float num4 = (float)(int)instance.m_nodes.m_buffer[mysegment.m_startNode].m_elevation; float num5 = (float)(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 num6 = Mathf.Min(leftMin, rightMin); t = 1000000f; priority = 1000000f; Segment3 segment = default(Segment3); segment.a = bezier.a; 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); Vector3 vector2 = segment.Position(v2); if (num7 < priority && Segment1.Intersect(ray.a.y, ray.b.y, vector2.y, out u2)) { Vector3 vector3 = ray.Position(u2); num7 = Vector3.SqrMagnitude(vector3 - vector2); 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 (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) { Segment2 segment2 = default(Segment2); 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; } } } segment.a = segment.b; } priority = Mathf.Max(0f, Mathf.Sqrt(priority) - collisionHalfWidth); } return(result); }