예제 #1
0
        /// <summary>
        /// Specialty Version of PLTErrorFunctionPrimeXZ used to link curves. Returns E'(t) = E'(tGuess) : Derivative of +/- Error [meters^2] in (straight-line distance between startPoint and point on bezier curve) vs (radius).
        /// </summary>
        /// <param name="bezier"></param>
        /// <param name="t">Where are you guessing the intersection is?</param>
        /// <param name="centerPos">Center of the circle to intersect the curve.</param>
        /// <returns></returns>
        private static float PLTLinkErrorFunctionPrimeXZ(Bezier3 bezier, float t, Vector3 centerPos)
        {
            float result = 0f;

            Vector3 _center = centerPos;
            float   x_c     = _center.x;
            float   z_c     = _center.z;

            Vector3 _guessPos = bezier.Position(t);
            float   _x        = _guessPos.x; //x(t)
            float   _z        = _guessPos.z; //z(t)

            if (_guessPos == centerPos)
            {
                return(0f);
            }

            Vector3 _derivPos = bezier.Tangent(t);
            float   _xPrime   = _derivPos.x; //x'(t)
            float   _zPrime   = _derivPos.z; //z'(t)

            result = 2 * (_x - x_c) * _xPrime + 2 * (_z - z_c) * _zPrime;

            return(result);
        }
예제 #2
0
        /// <summary>
        /// Travels some distance on bezier and calculates the point and tangent at that distance.
        /// </summary>
        /// <param name="distance">distance to travel on the arc in meters</param>
        /// <param name="tangent">normalized tangent on the curve toward the end of the bezier.</param>
        /// <returns>point on the curve at the given distance.</returns>
        public static Vector3 Travel2(this Bezier3 beizer, float distance, out Vector3 tangent)
        {
            float t = beizer.Travel(0, distance);

            tangent = beizer.Tangent(t).normalized;
            return(beizer.Position(t));
        }
예제 #3
0
        public static Vector3 CalcShift(Bezier3 basic, float t, float shift)
        {
            var pos      = basic.Position(t);
            var dir      = basic.Tangent(t);
            var shiftPos = CalcShift(pos, dir, shift);

            return(shiftPos);
        }
예제 #4
0
        // Token: 0x06000023 RID: 35 RVA: 0x00002A64 File Offset: 0x00000C64
        public bool NodeInsertion(ushort segmentID, float cut)
        {
            Bezier3    bezier  = default(Bezier3);
            NetSegment segment = this.GetSegment(segmentID);

            bezier.a = Singleton <NetManager> .instance.m_nodes.m_buffer[(int)segment.m_startNode].m_position;
            bezier.d = Singleton <NetManager> .instance.m_nodes.m_buffer[(int)segment.m_endNode].m_position;
            bool    smoothStart = (Singleton <NetManager> .instance.m_nodes.m_buffer[(int)segment.m_startNode].m_flags & NetNode.Flags.Middle) > NetNode.Flags.None;
            bool    smoothEnd   = (Singleton <NetManager> .instance.m_nodes.m_buffer[(int)segment.m_endNode].m_flags & NetNode.Flags.Middle) > NetNode.Flags.None;
            Vector3 b;
            Vector3 c;

            NetSegment.CalculateMiddlePoints(bezier.a, segment.m_startDirection, bezier.d, segment.m_endDirection, smoothStart, smoothEnd, out b, out c);
            bezier.b = b;
            bezier.c = c;
            Vector3 position       = bezier.Position(cut);
            ushort  startNode      = segment.m_startNode;
            Vector3 startDirection = segment.m_startDirection;
            Vector3 endDirection   = -bezier.Tangent(cut).normalized;
            ushort  endNode        = segment.m_endNode;
            Vector3 endDirection2  = segment.m_endDirection;
            Vector3 normalized     = bezier.Tangent(cut).normalized;
            ushort  num;

            this.Manager.CreateNode(out num, ref Singleton <SimulationManager> .instance.m_randomizer, segment.Info, position, Singleton <SimulationManager> .instance.m_currentBuildIndex);
            Singleton <SimulationManager> .instance.m_currentBuildIndex += 1u;
            bool   invert = (segmentID.ToSegment().m_flags & NetSegment.Flags.Invert) > NetSegment.Flags.None;
            ushort num2;

            this.Manager.CreateSegment(out num2, ref Singleton <SimulationManager> .instance.m_randomizer, segment.Info, startNode, num, startDirection, endDirection, Singleton <SimulationManager> .instance.m_currentBuildIndex, Singleton <SimulationManager> .instance.m_currentBuildIndex, invert);
            Singleton <SimulationManager> .instance.m_currentBuildIndex += 1u;
            ushort num3;

            this.Manager.CreateSegment(out num3, ref Singleton <SimulationManager> .instance.m_randomizer, segment.Info, num, endNode, normalized, endDirection2, Singleton <SimulationManager> .instance.m_currentBuildIndex, Singleton <SimulationManager> .instance.m_currentBuildIndex, invert);
            Singleton <SimulationManager> .instance.m_currentBuildIndex += 1u;
            this.Manager.UpdateNode(num);
            this.Manager.UpdateSegment(num2);
            this.Manager.UpdateSegment(num3);
            this.NetworkSkinsFixNewPrefab(segmentID, num2, segment.Info);
            this.NetworkSkinsFixNewPrefab(segmentID, num3, segment.Info);
            this.Manager.ReleaseSegment(segmentID, true);
            this.m_newSeg1 = num2;
            this.m_newSeg2 = num3;
            return(true);
        }
예제 #5
0
        //returns the integrand of the arc length function for a cubic bezier curve
        //constrained to the XZ-plane
        //at a specific t
        private static float CubicSpeedXZ(Bezier3 bezier, float t)
        {
            float   result   = 0f;
            Vector3 _tangent = bezier.Tangent(t);
            float   _derivX  = _tangent.x;
            float   _derivZ  = _tangent.z;

            result = Mathf.Sqrt(Mathf.Pow(_derivX, 2f) + Mathf.Pow(_derivZ, 2f));
            return(result);
        }
        private Vector3 TransformVertex(Bezier3 bezier, Vector3 vertex, float length, float width)
        {
            float t        = Utility.Map(0, 1, -length / 2, length / 2, vertex.z);
            var   position = bezier.Position(t);
            var   tangent  = bezier.Tangent(t);
            var   dir      = Vector3.Cross(Vector3.up, tangent);
            var   sideDir  = dir.normalized * vertex.x + (vertex.x < 0 ? dir.normalized * width : -dir.normalized * width);

            position.y += vertex.y;
            position   += sideDir;
            return(position);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
            }
        }
예제 #9
0
        public static void GetClosestPositionAndDirectionAndPoint(NetSegment s, Vector3 point, out Vector3 pos, out Vector3 dir, out float length)
        {
            Bezier3 curve = default;

            curve.a = Singleton <NetManager> .instance.m_nodes.m_buffer[s.m_startNode].m_position;
            curve.d = Singleton <NetManager> .instance.m_nodes.m_buffer[s.m_endNode].m_position;
            bool smoothStart = (Singleton <NetManager> .instance.m_nodes.m_buffer[s.m_startNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None;
            bool smoothEnd   = (Singleton <NetManager> .instance.m_nodes.m_buffer[s.m_endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None;

            NetSegment.CalculateMiddlePoints(curve.a, s.m_startDirection, curve.d, s.m_endDirection, smoothStart, smoothEnd, out curve.b, out curve.c);
            float   closestDistance = 1E+11f;
            float   pointPerc       = 0f;
            Vector3 targetA         = curve.a;

            for (int i = 1; i <= 16; i++)
            {
                Vector3 vector = curve.Position(i / 16f);
                float   dist   = Segment3.DistanceSqr(targetA, vector, point, out float distSign);
                if (dist < closestDistance)
                {
                    closestDistance = dist;
                    pointPerc       = (i - 1f + distSign) / 16f;
                }
                targetA = vector;
            }
            float precision = 0.03125f;

            for (int j = 0; j < 4; j++)
            {
                Vector3 a2      = curve.Position(Mathf.Max(0f, pointPerc - precision));
                Vector3 vector2 = curve.Position(pointPerc);
                Vector3 b       = curve.Position(Mathf.Min(1f, pointPerc + precision));
                float   num6    = Segment3.DistanceSqr(a2, vector2, point, out float num7);
                float   num8    = Segment3.DistanceSqr(vector2, b, point, out float num9);
                if (num6 < num8)
                {
                    pointPerc = Mathf.Max(0f, pointPerc - (precision * (1f - num7)));
                }
                else
                {
                    pointPerc = Mathf.Min(1f, pointPerc + (precision * num9));
                }
                precision *= 0.5f;
            }
            pos    = curve.Position(pointPerc);
            dir    = VectorUtils.NormalizeXZ(curve.Tangent(pointPerc));
            length = pointPerc;
        }
예제 #10
0
        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));
        }
        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());
        }
예제 #12
0
        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);
        }
예제 #13
0
        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 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);
        }
예제 #15
0
        // simplified assuming its called by NetSegment.CalculateCornerOffset.
        public static void CalculateCorner(
            NetInfo info, Vector3 startPos, Vector3 endPos, Vector3 startDir, Vector3 endDir,
            ushort ignoreSegmentID, ushort startNodeID, bool heightOffset, bool leftSide,
            out Vector3 cornerPos, out Vector3 cornerDirection, out bool smooth)
        {
            NetManager instance = Singleton <NetManager> .instance;
            Bezier3    bezier   = default(Bezier3);
            Bezier3    bezier2  = default(Bezier3);

            NetNode.Flags flags = NetNode.Flags.End;
            flags = instance.m_nodes.m_buffer[(int)startNodeID].m_flags;
            ushort startNodeBuildingID = startNodeID.ToNode().m_building;

            cornerDirection = startDir;
            smooth          = flags.IsFlagSet(NetNode.Flags.Middle);

            float hw = info.m_halfWidth;

            if (!leftSide)
            {
                hw = -hw;
            }

            if (flags.IsFlagSet(NetNode.Flags.Middle))
            {
                for (int i = 0; i < 8; ++i)
                {
                    ushort segmentID = startNodeID.ToNode().GetSegment(i);
                    if (segmentID == 0 || segmentID == ignoreSegmentID)
                    {
                        continue;
                    }
                    Vector3 dir = segmentID.ToSegment().GetDirection(startNodeID);
                    cornerDirection = VectorUtils.NormalizeXZ(cornerDirection - dir);
                    break;
                }
            }

            Vector3 dirAcross = Vector3.Cross(cornerDirection, Vector3.up).normalized;
            Vector3 VV1       = dirAcross;

            if (info.m_twistSegmentEnds)
            {
                if (startNodeBuildingID != 0)
                {
                    float   angle = Singleton <BuildingManager> .instance.m_buildings.m_buffer[(int)startNodeBuildingID].m_angle;
                    Vector3 v     = new Vector3(Mathf.Cos(angle), 0f, Mathf.Sin(angle));
                    VV1 = (Vector3.Dot(VV1, v) < 0f) ? (-v) : v;
                }
                else if (flags.IsFlagSet(NetNode.Flags.Junction))
                {
                    Vector3 v = default;
                    int     untouchableCount = 0;
                    for (int i = 0; i < 8; i++)
                    {
                        ushort segmentID = startNodeID.ToNode().GetSegment(i);
                        if (segmentID == 0 || segmentID == ignoreSegmentID)
                        {
                            continue;
                        }

                        if (segmentID.ToSegment().m_flags.IsFlagSet(NetSegment.Flags.Untouchable))
                        {
                            Vector3 dir = segmentID.ToSegment().GetDirection(startNodeID);
                            v = new Vector3(dir.z, 0f, -dir.x); // rotate vector by 90 degree and remove vertical element.
                            untouchableCount++;
                        }
                    }
                    if (untouchableCount == 1)
                    {
                        VV1 = ((Vector3.Dot(VV1, v) < 0f) ? (-v) : v);
                    }
                }
            }

            bezier.a  = startPos + VV1 * hw;
            bezier2.a = startPos - VV1 * hw;
            cornerPos = bezier.a;
            if (
                (flags.IsFlagSet(NetNode.Flags.Junction) && info.m_clipSegmentEnds) ||
                flags.IsFlagSet(NetNode.Flags.Bend | NetNode.Flags.End)
                )
            {
                VV1       = Vector3.Cross(endDir, Vector3.up).normalized;
                bezier.d  = endPos - VV1 * hw;
                bezier2.d = endPos + VV1 * hw;
                NetSegment.CalculateMiddlePoints(bezier.a, cornerDirection, bezier.d, endDir, false, false, out bezier.b, out bezier.c);
                NetSegment.CalculateMiddlePoints(bezier2.a, cornerDirection, bezier2.d, endDir, false, false, out bezier2.b, out bezier2.c);
                Bezier2 bezier3 = Bezier2.XZ(bezier);
                Bezier2 bezier4 = Bezier2.XZ(bezier2);
                float   num5    = -1f;
                float   num6    = -1f;
                bool    flag    = false;
                float   a       = info.m_halfWidth * 0.5f;

                int segmentCount = 0;
                for (int i = 0; i < 8; ++i)
                {
                    ushort segmentID = startNodeID.ToNode().GetSegment(i);
                    if (segmentID == 0 || segmentID == ignoreSegmentID)
                    {
                        continue;
                    }
                    Vector3 vector4 = instance.m_segments.m_buffer[(int)segmentID].GetDirection(startNodeID);
                    NetInfo netInfo = instance.m_segments.m_buffer[(int)segmentID].Info;
                    if (netInfo == null)
                    {
                        continue;
                    }
                    if (info.m_clipSegmentEnds != netInfo.m_clipSegmentEnds)
                    {
                        continue;
                    }
                    if (netInfo.m_netAI.GetSnapElevation() > info.m_netAI.GetSnapElevation())
                    {
                        float num10 = 0.01f - Mathf.Min(info.m_maxTurnAngleCos, netInfo.m_maxTurnAngleCos);
                        float num11 = vector4.x * startDir.x + vector4.z * startDir.z;
                        if ((info.m_vehicleTypes & netInfo.m_vehicleTypes) == VehicleInfo.VehicleType.None || num11 >= num10)
                        {
                            continue;
                        }
                    }
                    a = Mathf.Max(a, netInfo.m_halfWidth * 0.5f);
                    segmentCount++;
                }
                if (segmentCount >= 1 || flags.IsFlagSet(NetNode.Flags.Outside))
                {
                    for (int i = 0; i < 8; ++i)
                    {
                        ushort segmentID = startNodeID.ToNode().GetSegment(i);
                        if (segmentID == 0 || segmentID == ignoreSegmentID)
                        {
                            continue;
                        }
                        ushort  startNode2 = instance.m_segments.m_buffer[(int)segmentID].m_startNode;
                        ushort  num12      = instance.m_segments.m_buffer[(int)segmentID].m_endNode;
                        Vector3 vector6    = instance.m_segments.m_buffer[(int)segmentID].m_startDirection;
                        Vector3 vector7    = instance.m_segments.m_buffer[(int)segmentID].m_endDirection;
                        if (startNodeID != startNode2)
                        {
                            num12 = startNode2;
                            //swap
                            Vector3 temp = vector6;
                            vector6 = vector7;
                            vector7 = temp;
                        }
                        NetInfo netInfo = instance.m_segments.m_buffer[(int)segmentID].Info;
                        if (netInfo == null)
                        {
                            continue;
                        }
                        if (info.m_clipSegmentEnds != netInfo.m_clipSegmentEnds)
                        {
                            continue;
                        }
                        Vector3 vector5 = instance.m_nodes.m_buffer[(int)num12].m_position;
                        if (netInfo.m_netAI.GetSnapElevation() > info.m_netAI.GetSnapElevation())
                        {
                            float num14 = 0.01f - Mathf.Min(info.m_maxTurnAngleCos, netInfo.m_maxTurnAngleCos);
                            float num15 = vector6.x * startDir.x + vector6.z * startDir.z;
                            if ((info.m_vehicleTypes & netInfo.m_vehicleTypes) == VehicleInfo.VehicleType.None || num15 >= num14)
                            {
                                continue;
                            }
                        }
                        if (vector6.z * cornerDirection.x - vector6.x * cornerDirection.z > 0f == leftSide)
                        {
                            Bezier3 bezier5 = default(Bezier3);
                            float   num16   = Mathf.Max(a, netInfo.m_halfWidth);
                            if (!leftSide)
                            {
                                num16 = -num16;
                            }
                            VV1       = Vector3.Cross(vector6, Vector3.up).normalized;
                            bezier5.a = startPos - VV1 * num16;
                            VV1       = Vector3.Cross(vector7, Vector3.up).normalized;
                            bezier5.d = vector5 + VV1 * num16;
                            NetSegment.CalculateMiddlePoints(bezier5.a, vector6, bezier5.d, vector7, false, false, out bezier5.b, out bezier5.c);
                            Bezier2 b2 = Bezier2.XZ(bezier5);
                            float   b3;
                            float   num17;
                            if (bezier3.Intersect(b2, out b3, out num17, 6))
                            {
                                num5 = Mathf.Max(num5, b3);
                            }
                            else if (bezier3.Intersect(b2.a, b2.a - VectorUtils.XZ(vector6) * 16f, out b3, out num17, 6))
                            {
                                num5 = Mathf.Max(num5, b3);
                            }
                            else if (b2.Intersect(bezier3.d + (bezier3.d - bezier4.d) * 0.01f, bezier4.d, out b3, out num17, 6))
                            {
                                num5 = Mathf.Max(num5, 1f);
                            }
                            float num18 = cornerDirection.x * vector6.x + cornerDirection.z * vector6.z;
                            if (num18 >= -0.75f)
                            {
                                flag = true;
                            }
                        }

                        Bezier3 bezier6 = default(Bezier3);
                        float   num19   = cornerDirection.x * vector6.x + cornerDirection.z * vector6.z;
                        if (num19 >= 0f)
                        {
                            vector6.x -= cornerDirection.x * num19 * 2f;
                            vector6.z -= cornerDirection.z * num19 * 2f;
                        }
                        float num20 = Mathf.Max(a, netInfo.m_halfWidth);
                        if (!leftSide)
                        {
                            num20 = -num20;
                        }
                        VV1       = Vector3.Cross(vector6, Vector3.up).normalized;
                        bezier6.a = startPos + VV1 * num20;
                        VV1       = Vector3.Cross(vector7, Vector3.up).normalized;
                        bezier6.d = vector5 - VV1 * num20;
                        NetSegment.CalculateMiddlePoints(bezier6.a, vector6, bezier6.d, vector7, false, false, out bezier6.b, out bezier6.c);
                        Bezier2 b4 = Bezier2.XZ(bezier6);
                        float   b5;
                        float   num21;
                        if (bezier4.Intersect(b4, out b5, out num21, 6))
                        {
                            num6 = Mathf.Max(num6, b5);
                            continue;
                        }
                        if (bezier4.Intersect(b4.a, b4.a - VectorUtils.XZ(vector6) * 16f, out b5, out num21, 6))
                        {
                            num6 = Mathf.Max(num6, b5);
                            continue;
                        }
                        if (b4.Intersect(bezier3.d, bezier4.d + (bezier4.d - bezier3.d) * 0.01f, out b5, out num21, 6))
                        {
                            num6 = Mathf.Max(num6, 1f);
                            continue;
                        }
                        continue;
                    }
                    if ((flags & NetNode.Flags.Junction) != NetNode.Flags.None)
                    {
                        if (!flag)
                        {
                            num5 = Mathf.Max(num5, num6);
                        }
                    }
                    else if ((flags & NetNode.Flags.Bend) != NetNode.Flags.None && !flag)
                    {
                        num5 = Mathf.Max(num5, num6);
                    }
                    if ((flags & NetNode.Flags.Outside) != NetNode.Flags.None)
                    {
                        float   num22    = 8640f;
                        Vector2 vector9  = new Vector2(-num22, -num22);
                        Vector2 vector10 = new Vector2(-num22, num22);
                        Vector2 vector11 = new Vector2(num22, num22);
                        Vector2 vector12 = new Vector2(num22, -num22);
                        float   b6;
                        float   num23;
                        if (bezier3.Intersect(vector9, vector10, out b6, out num23, 6))
                        {
                            num5 = Mathf.Max(num5, b6);
                        }
                        if (bezier3.Intersect(vector10, vector11, out b6, out num23, 6))
                        {
                            num5 = Mathf.Max(num5, b6);
                        }
                        if (bezier3.Intersect(vector11, vector12, out b6, out num23, 6))
                        {
                            num5 = Mathf.Max(num5, b6);
                        }
                        if (bezier3.Intersect(vector12, vector9, out b6, out num23, 6))
                        {
                            num5 = Mathf.Max(num5, b6);
                        }
                        num5 = Mathf.Clamp01(num5);
                    }
                    else
                    {
                        if (num5 < 0f)
                        {
                            if (info.m_halfWidth < 4f)
                            {
                                num5 = 0f;
                            }
                            else
                            {
                                num5 = bezier3.Travel(0f, 8f);
                            }
                        }
                        float num24 = info.m_minCornerOffset;
                        if ((flags & (NetNode.Flags.AsymForward | NetNode.Flags.AsymBackward)) != NetNode.Flags.None)
                        {
                            num24 = Mathf.Max(num24, 8f);
                        }
                        num5 = Mathf.Clamp01(num5);
                        float num25 = VectorUtils.LengthXZ(bezier.Position(num5) - bezier.a);
                        num5 = bezier3.Travel(num5, Mathf.Max(num24 - num25, 2f));
                        if (info.m_straightSegmentEnds)
                        {
                            if (num6 < 0f)
                            {
                                if (info.m_halfWidth < 4f)
                                {
                                    num6 = 0f;
                                }
                                else
                                {
                                    num6 = bezier4.Travel(0f, 8f);
                                }
                            }
                            num6  = Mathf.Clamp01(num6);
                            num25 = VectorUtils.LengthXZ(bezier2.Position(num6) - bezier2.a);
                            num6  = bezier4.Travel(num6, Mathf.Max(info.m_minCornerOffset - num25, 2f));
                            num5  = Mathf.Max(num5, num6);
                        }
                    }
                    float y = cornerDirection.y;
                    cornerDirection   = bezier.Tangent(num5);
                    cornerDirection.y = 0f;
                    cornerDirection.Normalize();
                    if (!info.m_flatJunctions)
                    {
                        cornerDirection.y = y;
                    }
                    cornerPos   = bezier.Position(num5);
                    cornerPos.y = startPos.y;
                }
            }
            else if ((flags & NetNode.Flags.Junction) != NetNode.Flags.None && info.m_minCornerOffset >= 0.01f)
            {
                VV1       = Vector3.Cross(endDir, Vector3.up).normalized;
                bezier.d  = endPos - VV1 * hw;
                bezier2.d = endPos + VV1 * hw;
                NetSegment.CalculateMiddlePoints(bezier.a, cornerDirection, bezier.d, endDir, false, false, out bezier.b, out bezier.c);
                NetSegment.CalculateMiddlePoints(bezier2.a, cornerDirection, bezier2.d, endDir, false, false, out bezier2.b, out bezier2.c);
                Bezier2 bezier7 = Bezier2.XZ(bezier);
                Bezier2 bezier8 = Bezier2.XZ(bezier2);
                float   num26;
                if (info.m_halfWidth < 4f)
                {
                    num26 = 0f;
                }
                else
                {
                    num26 = bezier7.Travel(0f, 8f);
                }
                num26 = Mathf.Clamp01(num26);
                float num27 = VectorUtils.LengthXZ(bezier.Position(num26) - bezier.a);
                num26 = bezier7.Travel(num26, Mathf.Max(info.m_minCornerOffset - num27, 2f));
                if (info.m_straightSegmentEnds)
                {
                    float num28;
                    if (info.m_halfWidth < 4f)
                    {
                        num28 = 0f;
                    }
                    else
                    {
                        num28 = bezier8.Travel(0f, 8f);
                    }
                    num28 = Mathf.Clamp01(num28);
                    num27 = VectorUtils.LengthXZ(bezier2.Position(num28) - bezier2.a);
                    num28 = bezier8.Travel(num28, Mathf.Max(info.m_minCornerOffset - num27, 2f));
                    num26 = Mathf.Max(num26, num28);
                }
                float y2 = cornerDirection.y;
                cornerDirection   = bezier.Tangent(num26);
                cornerDirection.y = 0f;
                cornerDirection.Normalize();
                if (!info.m_flatJunctions)
                {
                    cornerDirection.y = y2;
                }
                cornerPos   = bezier.Position(num26);
                cornerPos.y = startPos.y;
            }
            if (heightOffset && startNodeID != 0)
            {
                cornerPos.y += (float)instance.m_nodes.m_buffer[(int)startNodeID].m_heightOffset * 0.015625f;
            }
        }
        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);
        }
예제 #17
0
        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);
                }
            }
        }
예제 #18
0
        public void PopulateGroupData(
            ushort segmentID, uint laneID, NetInfo.Lane laneInfo, bool destroyed,
            NetNode.Flags startFlags, NetNode.Flags endFlags,
            float startAngle, float endAngle,
            bool invert, bool terrainHeight, 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 hasProps)
        {
            NetLaneProps laneProps = laneInfo.m_laneProps;

            if (laneProps?.m_props == null)
            {
                return;
            }
            bool backward = (laneInfo.m_finalDirection & NetInfo.Direction.Both) == NetInfo.Direction.Backward || (laneInfo.m_finalDirection & NetInfo.Direction.AvoidBoth) == NetInfo.Direction.AvoidForward;
            bool reverse  = backward != invert;

            if (backward)  //swap
            {
                NetNode.Flags flags = startFlags;
                startFlags = endFlags;
                endFlags   = flags;
            }
            int nProps = laneProps.m_props.Length;

            for (int i = 0; i < nProps; i++)
            {
                NetLaneProps.Prop prop = laneProps.m_props[i];
                if (!prop.CheckFlags(m_flags, startFlags, endFlags) || m_length < prop.m_minLength)
                {
                    continue;
                }
                int repeatCountTimes2 = 2;
                if (prop.m_repeatDistance > 1f)
                {
                    repeatCountTimes2 *= Mathf.Max(1, Mathf.RoundToInt(m_length / prop.m_repeatDistance));
                }
                float halfSegmentOffset = prop.m_segmentOffset * 0.5f;
                if (m_length != 0f)
                {
                    halfSegmentOffset = Mathf.Clamp(halfSegmentOffset + prop.m_position.z / m_length, -0.5f, 0.5f);
                }
                if (reverse)
                {
                    halfSegmentOffset = 0f - halfSegmentOffset;
                }
                PropInfo finalProp = prop.m_finalProp;
                if ((object)finalProp != null)
                {
                    hasProps = true;
                    if (finalProp.m_prefabDataLayer == layer || finalProp.m_effectLayer == layer)
                    {
                        Color      color = Color.white;
                        Randomizer r     = new Randomizer((int)laneID + i);
                        for (int j = 1; j <= repeatCountTimes2; j += 2)
                        {
                            if (r.Int32(100u) >= prop.m_probability)
                            {
                                continue;
                            }
                            float    t         = halfSegmentOffset + (float)j / (float)repeatCountTimes2;
                            PropInfo variation = finalProp.GetVariation(ref r);
                            float    scale     = variation.m_minScale + (float)r.Int32(10000u) * (variation.m_maxScale - variation.m_minScale) * 0.0001f;
                            if (prop.m_colorMode == NetLaneProps.ColorMode.Default)
                            {
                                color = variation.GetColor(ref r);
                            }
                            if (!variation.m_isDecal && destroyed)
                            {
                                continue;
                            }
                            Vector3 pos = m_bezier.Position(t);
                            Vector3 tan = m_bezier.Tangent(t);
                            if (!(tan != Vector3.zero))
                            {
                                continue;
                            }
                            if (reverse)
                            {
                                tan = -tan;
                            }
                            tan.y = 0f;
                            if (prop.m_position.x != 0f)
                            {
                                tan    = Vector3.Normalize(tan);
                                pos.x += tan.z * prop.m_position.x;
                                pos.z -= tan.x * prop.m_position.x;
                            }
                            float normalAngle = Mathf.Atan2(tan.x, 0f - tan.z);
                            if (prop.m_cornerAngle != 0f || prop.m_position.x != 0f)
                            {
                                float angleDiff = endAngle - startAngle;
                                if (angleDiff > Mathf.PI)
                                {
                                    angleDiff -= Mathf.PI * 2f;
                                }
                                if (angleDiff < -Mathf.PI)
                                {
                                    angleDiff += Mathf.PI * 2f;
                                }
                                var angle2 = startAngle + angleDiff * t - normalAngle;
                                if (angle2 > Mathf.PI)
                                {
                                    angle2 -= Mathf.PI * 2f;
                                }
                                if (angle2 < -Mathf.PI)
                                {
                                    angle2 += Mathf.PI * 2f;
                                }
                                normalAngle += angle2 * prop.m_cornerAngle;
                                if (angle2 != 0f && prop.m_position.x != 0f)
                                {
                                    float d = Mathf.Tan(angle2);
                                    pos.x += tan.x * d * prop.m_position.x;
                                    pos.z += tan.z * d * prop.m_position.x;
                                }
                            }
                            if (terrainHeight)
                            {
                                if (variation.m_requireWaterMap)
                                {
                                    pos.y = Singleton <TerrainManager> .instance.SampleRawHeightSmoothWithWater(pos, timeLerp : false, 0f);
                                }
                                else
                                {
                                    pos.y = Singleton <TerrainManager> .instance.SampleDetailHeight(pos);
                                }
                            }
                            pos.y += prop.m_position.y;
                            InstanceID id = default(InstanceID);
                            id.NetSegment = segmentID;
                            PropInstance.PopulateGroupData(angle: normalAngle + prop.m_angle * (Mathf.PI / 180f), info: variation, layer: layer, id: id, position: pos, scale: scale, color: color, vertexIndex: ref vertexIndex, triangleIndex: ref triangleIndex, groupPosition: groupPosition, data: data, min: ref min, max: ref max, maxRenderDistance: ref maxRenderDistance, maxInstanceDistance: ref maxInstanceDistance);
                        }
                    }
                }
                if (destroyed)
                {
                    continue;
                }
                TreeInfo finalTree = prop.m_finalTree;
                if ((object)finalTree == null)
                {
                    continue;
                }
                hasProps = true;
                if (finalTree.m_prefabDataLayer != layer)
                {
                    continue;
                }
                Randomizer r2 = new Randomizer((int)laneID + i);
                for (int k = 1; k <= repeatCountTimes2; k += 2)
                {
                    if (r2.Int32(100u) >= prop.m_probability)
                    {
                        continue;
                    }
                    float    t          = halfSegmentOffset + (float)k / (float)repeatCountTimes2;
                    TreeInfo variation2 = finalTree.GetVariation(ref r2);
                    float    scale2     = variation2.m_minScale + (float)r2.Int32(10000u) * (variation2.m_maxScale - variation2.m_minScale) * 0.0001f;
                    float    brightness = variation2.m_minBrightness + (float)r2.Int32(10000u) * (variation2.m_maxBrightness - variation2.m_minBrightness) * 0.0001f;
                    Vector3  vector3    = m_bezier.Position(t);
                    if (prop.m_position.x != 0f)
                    {
                        Vector3 vector4 = m_bezier.Tangent(t);
                        if (reverse)
                        {
                            vector4 = -vector4;
                        }
                        vector4.y  = 0f;
                        vector4    = Vector3.Normalize(vector4);
                        vector3.x += vector4.z * prop.m_position.x;
                        vector3.z -= vector4.x * prop.m_position.x;
                    }
                    if (terrainHeight)
                    {
                        vector3.y = Singleton <TerrainManager> .instance.SampleDetailHeight(vector3);
                    }
                    vector3.y += prop.m_position.y;
                    TreeInstance.PopulateGroupData(variation2, vector3, scale2, brightness, RenderManager.DefaultColorLocation, ref vertexIndex, ref triangleIndex, groupPosition, data, ref min, ref max, ref maxRenderDistance, ref maxInstanceDistance);
                }
            }
        }