Exemple #1
0
        /* Well, the vector density is uniform on the circle, but not on the ellipse. But whatever... */
        private void calculateBeziers()
        {
            if (DENSITY < 4)
            {
                Beziers = null;
            }
            List <Vector3> vectors  = new List <Vector3>();
            List <Vector3> tangents = new List <Vector3>();
            List <Bezier2> beziers  = new List <Bezier2>();

            double angle = (2 * Math.PI) / DENSITY;

            for (int i = 0; i < DENSITY; i++)
            {
                vectors.Add(VectorAtAngle(angle * i));
                tangents.Add(TangentAtAngle(angle * i));
            }

            for (int i = 0; i < DENSITY; i++)
            {
                Bezier3 bezier = new Bezier3();
                bezier.a = vectors[i];
                bezier.d = vectors[(i + 1) % DENSITY]; // line below: false false or something else?
                NetSegment.CalculateMiddlePoints(bezier.a, tangents[i], bezier.d, -1 * tangents[(i + 1) % DENSITY], false, false, out bezier.b, out bezier.c);
                beziers.Add(Bezier2.XZ(bezier));
            }

            Beziers = beziers;
        }
Exemple #2
0
        /* From Elektrix */
        public static bool DoSegmentsIntersect(ushort segment1, ushort segment2, out float t1, out float t2)
        {
            // First segment data
            NetSegment s1     = Segment(segment1);
            Bezier3    bezier = default(Bezier3);

            // Second segment data
            NetSegment s2           = Segment(segment2);
            Bezier3    secondBezier = default(Bezier3);

            // Turn the segment data into a Bezier2 for easier calculations supported by the game
            bezier.a = Node(s1.m_startNode).m_position;
            bezier.d = Node(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 bezier.b, out bezier.c);

            Bezier2 xz = Bezier2.XZ(bezier);

            // Second segment:
            secondBezier.a = Node(s2.m_startNode).m_position;
            secondBezier.d = Node(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(secondBezier.a, s2.m_startDirection, secondBezier.d, s2.m_endDirection, smoothStart, smoothEnd, out secondBezier.b, out secondBezier.c);

            Bezier2 xz2 = Bezier2.XZ(secondBezier);

            return(xz.Intersect(xz2, out t1, out t2, 5));
        }
        private void BezierToSegment(Bezier2 bezier2, WrappedSegment oldSegmentW, WrappedNode startNodeW, WrappedNode endNodeW, bool invert)
        {
            NetSegment oldSegment = oldSegmentW.Get;
            Vector2    startDirection2d;
            Vector2    endDirection2d;
            Vector2    nodePos2d = new Vector2(startNodeW.Position.x, startNodeW.Position.z);

            startDirection2d = bezier2.Tangent(0f);
            endDirection2d   = bezier2.Tangent(1f);

            Vector3 startDirection = (new Vector3(startDirection2d.x, 0, startDirection2d.y));
            Vector3 endDirection   = -(new Vector3(endDirection2d.x, 0, endDirection2d.y));

            /* Unlike from the old algorithm, we use no padding when looking for the segments. That means the obtained segments can be arbitrarily short.
             * In that case, we take one more segment away from the ellipse.*/
            if (VectorDistance(bezier2.a, bezier2.d) < MIN_BEZIER_LENGTH)
            {
                //Debug.Log("Segment is too short. Launching repair mechainsm." + VectorDistance(bezier2.a, bezier2.d));
                nextSegmentInfo(oldSegmentW, ref endNodeW, ref endDirection);
            }

            // Debug
            // EllipseTool.Instance.debugDrawVector(20*startDirection, GetNode(startNodeId).m_position);
            // EllipseTool.Instance.debugDrawVector(20*endDirection, GetNode(endNodeId).m_position);

            startDirection.Normalize();
            endDirection.Normalize();

            if (oldSegment.m_flags.IsFlagSet(NetSegment.Flags.Invert))
            {
                invert = !invert;
            }

            WrappedSegment newSegment = new WrappedSegment();

            newSegment.StartNode      = startNodeW;
            newSegment.EndNode        = endNodeW;
            newSegment.StartDirection = startDirection;
            newSegment.EndDirection   = endDirection;
            newSegment.NetInfo        = oldSegment.Info;
            newSegment.Invert         = invert;

            ActionGroupRoads.Actions.Add(newSegment);
            ActionGroupTMPE.Actions.Add(new EnteringBlockedJunctionAllowedAction(newSegment, true, true));
            ActionGroupTMPE.Actions.Add(new YieldSignAction(newSegment, true));

            /*try
             * {
             *  ushort newSegmentId = NetAccess.CreateSegment(startNodeId, endNodeId,
             * startDirection, endDirection, oldSegment.Info, invert);
             *
             *
             * }
             * catch(Exception e)
             * {
             *  UIWindow2.instance.ThrowErrorMsg("The game failed to create one of the road segments.");
             *  Debug.LogError(e.ToString());
             * }*/
        }
    void Start()
    {
        meshRenderer = GetComponent <MeshRenderer>();
        meshFilter   = GetComponent <MeshFilter>();

        quadraticBezier = new Bezier2(start, handle1, end);
        cubicBezier     = new Bezier3(start, handle1, handle2, end);
    }
Exemple #5
0
 public static bool IsStraight(this Bezier2 beizer)
 {
     return(false);
     // cannot work optimise small beziers for some unknown reason. commenting out this until the problem is fixed.
     //var startDir = (beizer.a - beizer.b).normalized;
     //var endDir = (beizer.c - beizer.d).normalized; // c actually gets past d.
     //return EqualAprox((startDir + endDir).sqrMagnitude, 0f, Epsilon * Epsilon);
     //.LogRet($"IsStraight bezier={beizer.STR()} startDir:{startDir} endDir:{endDir} sum={(startDir + endDir)} ret:");
 }
        public static Bezier3 ShiftTo3D(this Bezier2 bezier)
        {
            Vector3 v1 = new Vector3(bezier.a.x, 0, bezier.a.y);
            Vector3 v2 = new Vector3(bezier.b.x, 0, bezier.b.y);
            Vector3 v3 = new Vector3(bezier.c.x, 0, bezier.c.y);
            Vector3 v4 = new Vector3(bezier.d.x, 0, bezier.d.y);

            return(new Bezier3(v1, v2, v3, v4));
        }
        public static bool IsStraight(this Bezier2 beizer)
        {
            return(false);

            var startDir = (beizer.a - beizer.b).normalized;
            var endDir   = (beizer.c - beizer.d).normalized; // c actually gets past d.

            return(EqualAprox((startDir + endDir).sqrMagnitude, 0f, Epsilon * Epsilon));
            //.LogRet($"IsStraight bezier={beizer.STR()} startDir:{startDir} endDir:{endDir} sum={(startDir + endDir)} ret:");
        }
        /// <summary>
        /// Travels some distance on beizer and calculates the point and tangent at that distance.
        /// </summary>
        /// <param name="distance">distance to travel on the arc in meteres</param>
        /// <param name="tangent">normalized tangent on the curve toward the end of the beizer.</param>
        /// <returns>point on the curve at the given distance.</returns>
        public static Vector2 Travel2(this Bezier2 beizer, float distance, out Vector2 tangent)
        {
            if (beizer.IsStraight())
            {
                tangent = (beizer.d - beizer.a).normalized;
                return(beizer.TravelStraight(distance));
            }
            float t = beizer.Travel(0, distance);

            tangent = beizer.Tangent(t).normalized;
            return(beizer.Position(t));
        }
    public static void DrawBezier2(Vector3 startPosition, Vector3 endPosition, Vector3 control, Color color, Texture2D texture, float width)
    {
        Bezier2 curve     = new Bezier2(startPosition, control, endPosition);
        Vector2 lineStart = startPosition;

        Handles.color = color;
        for (int i = 1; i <= 32; i++)
        {
            Vector2 lineEnd = curve.GetQuadraticPoint(i / (float)16);
            Handles.DrawAAPolyLine(texture, width, lineStart, lineEnd);
            lineStart = lineEnd;
        }
    }
 public Vector2 CalculateCenter() {
     Vector2 pointAcc = Vector3.zero;
     float totalWieght = 0;
     foreach(var segmentID in SegmentList) {
         Bezier2 bezier = segmentID.ToSegment().CalculateSegmentBezier3().ToCSBezier2();
         float weitght = segmentID.ToSegment().m_averageLength;
         for (float t = 0; t < 1; t+=0.1f) {
             var pos = bezier.Position(t);
             pointAcc += pos * weitght;
             totalWieght += weitght;
         }
     }
     var ret = pointAcc / totalWieght;
     return ret;
 }
        /* Turns segments into beziers. */
        private List <Bezier2> makeBeziers(List <ushort> netSegmentsIds)
        {
            List <Bezier2> beziers = new List <Bezier2>();

            for (int i = 0; i < netSegmentsIds.Count; i++)
            {
                NetSegment netSegment  = NetUtil.Segment(netSegmentsIds[i]);
                bool       smoothStart = (NetUtil.Node(netSegment.m_startNode).m_flags & NetNode.Flags.Middle) != NetNode.Flags.None;
                bool       smoothEnd   = (NetUtil.Node(netSegment.m_endNode).m_flags & NetNode.Flags.Middle) != NetNode.Flags.None;
                Bezier3    bezier      = new Bezier3();
                bezier.a = NetUtil.Node(netSegment.m_startNode).m_position;
                bezier.d = NetUtil.Node(netSegment.m_endNode).m_position;
                NetSegment.CalculateMiddlePoints(bezier.a, netSegment.m_startDirection, bezier.d, netSegment.m_endDirection, smoothStart, smoothEnd, out bezier.b, out bezier.c);
                beziers.Add(Bezier2.XZ(bezier));
            }
            return(beziers);
        }
        public static float ArcLength(this Bezier2 bezier, float step = 0.1f)
        {
            if (bezier.IsStraight())
            {
                return((bezier.d - bezier.a).magnitude);
            }
            float ret = 0;
            float t;

            for (t = step; t < 1f; t += step)
            {
                float len = (bezier.Position(t) - bezier.Position(t - step)).magnitude;
                ret += len;
            }
            {
                float len = (bezier.d - bezier.Position(t - step)).magnitude;
                ret += len;
            }
            return(ret);
        }
        public static float ArcLength(this Bezier2 bezier, Vector2 point, float step = 0.1f)
        {
            if (bezier.IsStraight())
            {
                return((point - bezier.a).magnitude);
            }
            float ret = 0;
            float t;

            for (t = step; t <= 1f + Epsilon; t += step)
            {
                var   p0   = bezier.Position(t - step);
                float len  = (bezier.Position(t) - p0).magnitude;
                float len2 = (point - p0).magnitude;
                if (len2 <= len + Epsilon)
                {
                    ret += len2;
                    return(ret);
                }
                ret += len;
            }
            return(ret);
        }
        static Vector2 TravelStraight(this Bezier2 beizer, float length)
        {
            float r = length / beizer.ArcLength();

            return(beizer.a + r * (beizer.d - beizer.a));
        }
Exemple #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;
            }
        }
Exemple #16
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);
        }
 public static string STR(this Bezier2 bezier)
 {
     return($"Bezier2(" + bezier.a + ", " + bezier.b + ", " + bezier.c + ", " + bezier.d + ")");
 }
        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;
            var        flags    = NetNode.Flags.End;
            var        building = 0;

            if (startNodeID != 0)
            {
                flags    = instance.m_nodes.m_buffer[startNodeID].m_flags;
                building = instance.m_nodes.m_buffer[startNodeID].m_building;
            }

            cornerDirection = startDir;
            var halfWidth = (!leftSide) ? (0f - info.m_halfWidth) : info.m_halfWidth;

            smooth = (flags & NetNode.Flags.Middle) != 0;

            if ((flags & NetNode.Flags.Middle) != 0 && startNodeID != 0)
            {
                var segment  = ignoreSegmentID.GetSegment();
                var isStart  = segment.IsStartNode(startNodeID);
                var deltaDir = isStart ? segment.m_startDirection : segment.m_endDirection;
                cornerDirection = NormalizeXZ(cornerDirection - deltaDir);
            }

            var startCornerNormal = Vector3.Cross(cornerDirection, Vector3.up).normalized;

            if (info.m_twistSegmentEnds)
            {
                if (building != 0)
                {
                    var buildingAngle  = Singleton <BuildingManager> .instance.m_buildings.m_buffer[building].m_angle;
                    var buildingNormal = new Vector3(Mathf.Cos(buildingAngle), 0f, Mathf.Sin(buildingAngle));
                    startCornerNormal = Vector3.Dot(startCornerNormal, buildingNormal) < 0f ? -buildingNormal : buildingNormal;
                }
                else if ((flags & NetNode.Flags.Junction) != 0 && startNodeID != 0)
                {
                    var segmentNormal = Vector3.zero;
                    var segmentCount  = 0;
                    for (int i = 0; i < 8; i++)
                    {
                        var segmentId = instance.m_nodes.m_buffer[startNodeID].GetSegment(i);
                        if (segmentId != 0 && segmentId != ignoreSegmentID && (instance.m_segments.m_buffer[segmentId].m_flags & NetSegment.Flags.Untouchable) != 0)
                        {
                            var segmentDir = instance.m_segments.m_buffer[segmentId].m_startNode == startNodeID ? instance.m_segments.m_buffer[segmentId].m_startDirection : instance.m_segments.m_buffer[segmentId].m_endDirection;
                            segmentNormal = new Vector3(segmentDir.z, 0f, 0f - segmentDir.x);
                            segmentCount += 1;
                        }
                    }
                    if (segmentCount == 1)
                    {
                        startCornerNormal = Vector3.Dot(startCornerNormal, segmentNormal) < 0f ? (-segmentNormal) : segmentNormal;
                    }
                }
            }

            var thisBezier = new Bezier3()
            {
                a = startPos + startCornerNormal * halfWidth
            };
            var otherBezier = new Bezier3()
            {
                a = startPos - startCornerNormal * halfWidth
            };

            cornerPos = thisBezier.a;

            if (((flags & NetNode.Flags.Junction) != 0 && info.m_clipSegmentEnds) || (flags & (NetNode.Flags.Bend | NetNode.Flags.Outside)) != 0)
            {
                var endCornerNormal = Vector3.Cross(endDir, Vector3.up).normalized;
                thisBezier.d  = endPos - endCornerNormal * halfWidth;
                otherBezier.d = endPos + endCornerNormal * halfWidth;
                NetSegment.CalculateMiddlePoints(thisBezier.a, cornerDirection, thisBezier.d, endDir, smoothStart: false, smoothEnd: false, out thisBezier.b, out thisBezier.c);
                NetSegment.CalculateMiddlePoints(otherBezier.a, cornerDirection, otherBezier.d, endDir, smoothStart: false, smoothEnd: false, out otherBezier.b, out otherBezier.c);
                var thisBezierXZ  = Bezier2.XZ(thisBezier);
                var otherBezierXZ = Bezier2.XZ(otherBezier);

                float thisOffsetT  = -1f;
                float otherOffsetT = -1f;
                bool  flag         = false;

                var segmentCount    = startNodeID != 0 ? 8 : 0;
                var maxQuarterWidth = info.m_halfWidth * 0.5f;
                var segmentIndex    = 0;

                for (var i = 0; i < segmentCount; i += 1)
                {
                    var currentSegmentId = instance.m_nodes.m_buffer[startNodeID].GetSegment(i);
                    if (currentSegmentId == 0 || currentSegmentId == ignoreSegmentID)
                    {
                        continue;
                    }

                    var currentInfo     = instance.m_segments.m_buffer[currentSegmentId].Info;
                    var segmentStartDir = instance.m_segments.m_buffer[currentSegmentId].GetDirection(startNodeID);

                    if (currentInfo == null || info.m_clipSegmentEnds != currentInfo.m_clipSegmentEnds)
                    {
                        continue;
                    }

                    if (currentInfo.m_netAI.GetSnapElevation() > info.m_netAI.GetSnapElevation())
                    {
                        var turnAngle    = 0.01f - Mathf.Min(info.m_maxTurnAngleCos, currentInfo.m_maxTurnAngleCos);
                        var angleBetween = segmentStartDir.x * startDir.x + segmentStartDir.z * startDir.z;
                        if ((info.m_vehicleTypes & currentInfo.m_vehicleTypes) == 0 || angleBetween >= turnAngle)
                        {
                            continue;
                        }
                    }
                    maxQuarterWidth = Mathf.Max(maxQuarterWidth, currentInfo.m_halfWidth * 0.5f);
                    segmentIndex++;
                }

                if (segmentIndex >= 1 || (flags & NetNode.Flags.Outside) != 0)
                {
                    for (var i = 0; i < segmentCount; i += 1)
                    {
                        var currentSegmentId = instance.m_nodes.m_buffer[startNodeID].GetSegment(i);
                        if (currentSegmentId == 0 || currentSegmentId == ignoreSegmentID)
                        {
                            continue;
                        }

                        ushort currentStartNodeId = instance.m_segments.m_buffer[currentSegmentId].m_startNode;
                        ushort currentEndNodeId   = instance.m_segments.m_buffer[currentSegmentId].m_endNode;
                        var    currentStartDir    = instance.m_segments.m_buffer[currentSegmentId].m_startDirection;
                        var    currentEndDir      = instance.m_segments.m_buffer[currentSegmentId].m_endDirection;
                        if (startNodeID != currentStartNodeId)
                        {
                            var tempNodeId = currentStartNodeId;
                            currentStartNodeId = currentEndNodeId;
                            currentEndNodeId   = tempNodeId;
                            var tempVector = currentStartDir;
                            currentStartDir = currentEndDir;
                            currentEndDir   = tempVector;
                        }

                        var currentInfo   = instance.m_segments.m_buffer[currentSegmentId].Info;
                        var currentEndPos = instance.m_nodes.m_buffer[currentEndNodeId].m_position;

                        if (currentInfo == null || info.m_clipSegmentEnds != currentInfo.m_clipSegmentEnds)
                        {
                            continue;
                        }

                        if (currentInfo.m_netAI.GetSnapElevation() > info.m_netAI.GetSnapElevation())
                        {
                            float turnAngle    = 0.01f - Mathf.Min(info.m_maxTurnAngleCos, currentInfo.m_maxTurnAngleCos);
                            float angleBetween = currentStartDir.x * startDir.x + currentStartDir.z * startDir.z;
                            if ((info.m_vehicleTypes & currentInfo.m_vehicleTypes) == 0 || angleBetween >= turnAngle)
                            {
                                continue;
                            }
                        }

                        if (currentStartDir.z * cornerDirection.x - currentStartDir.x * cornerDirection.z > 0f == leftSide)
                        {
                            float currentHalfWidth = (leftSide ? 1 : -1) * Mathf.Max(maxQuarterWidth, currentInfo.m_halfWidth);

                            var currentStartDirN = Vector3.Cross(currentStartDir, Vector3.up).normalized;
                            var currentEndDirN   = Vector3.Cross(currentEndDir, Vector3.up).normalized;
                            var currentBezier    = new Bezier3()
                            {
                                a = startPos - currentStartDirN * currentHalfWidth,
                                d = currentEndPos + currentEndDirN * currentHalfWidth,
                            };
                            NetSegment.CalculateMiddlePoints(currentBezier.a, currentStartDir, currentBezier.d, currentEndDir, smoothStart: false, smoothEnd: false, out currentBezier.b, out currentBezier.c);

                            var currentBezierXZ = Bezier2.XZ(currentBezier);
                            if (thisBezierXZ.Intersect(currentBezierXZ, out var t, out _, 6))
                            {
                                thisOffsetT = Mathf.Max(thisOffsetT, t);
                            }
                            else if (thisBezierXZ.Intersect(currentBezierXZ.a, currentBezierXZ.a - XZ(currentStartDir) * 16f, out t, out _, 6))
                            {
                                thisOffsetT = Mathf.Max(thisOffsetT, t);
                            }
                            else if (currentBezierXZ.Intersect(thisBezierXZ.d + (thisBezierXZ.d - otherBezierXZ.d) * 0.01f, otherBezierXZ.d, out _, out _, 6))
                            {
                                thisOffsetT = Mathf.Max(thisOffsetT, 1f);
                            }

                            if (cornerDirection.x * currentStartDir.x + cornerDirection.z * currentStartDir.z >= -0.75f)
                            {
                                flag = true;
                            }
                        }
                        else
                        {
                            float num19 = cornerDirection.x * currentStartDir.x + cornerDirection.z * currentStartDir.z;
                            if (num19 >= 0f)
                            {
                                currentStartDir.x -= cornerDirection.x * num19 * 2f;
                                currentStartDir.z -= cornerDirection.z * num19 * 2f;
                            }
                            float currentHalfWidth = (leftSide ? 1 : -1) * Mathf.Max(maxQuarterWidth, currentInfo.m_halfWidth);

                            var currentStartDirN = Vector3.Cross(currentStartDir, Vector3.up).normalized;
                            var currentEndDirN   = Vector3.Cross(currentEndDir, Vector3.up).normalized;
                            var currentBezier    = new Bezier3()
                            {
                                a = startPos + currentStartDirN * currentHalfWidth,
                                d = currentEndPos - currentEndDirN * currentHalfWidth,
                            };
                            NetSegment.CalculateMiddlePoints(currentBezier.a, currentStartDir, currentBezier.d, currentEndDir, smoothStart: false, smoothEnd: false, out currentBezier.b, out currentBezier.c);
                            var currentBezierXZ = Bezier2.XZ(currentBezier);

                            if (otherBezierXZ.Intersect(currentBezierXZ, out var t3, out _, 6))
                            {
                                otherOffsetT = Mathf.Max(otherOffsetT, t3);
                            }
                            else if (otherBezierXZ.Intersect(currentBezierXZ.a, currentBezierXZ.a - XZ(currentStartDir) * 16f, out t3, out _, 6))
                            {
                                otherOffsetT = Mathf.Max(otherOffsetT, t3);
                            }
                            else if (currentBezierXZ.Intersect(thisBezierXZ.d, otherBezierXZ.d + (otherBezierXZ.d - thisBezierXZ.d) * 0.01f, out _, out _, 6))
                            {
                                otherOffsetT = Mathf.Max(otherOffsetT, 1f);
                            }
                        }
        private void BezierToSegment(Bezier2 bezier2, ushort oldSegmentId, ushort startNodeId, ushort endNodeId, bool invert)
        {
            NetSegment oldSegment = NetAccess.Segment(oldSegmentId);
            Vector2    startDirection2d;
            Vector2    endDirection2d;
            Vector2    nodePos2d = new Vector2(NetAccess.Node(startNodeId).m_position.x, NetAccess.Node(startNodeId).m_position.z);

            /*if ( Distance(nodePos2d,bezier2.Position(0f)) < 10e-3d)
             * {
             *  //0f is on the ellipse
             * }
             * else if(Distance(nodePos2d, bezier2.Position(1f)) < 10e-3d)
             * {
             *  //1f is on the ellipse
             *  bezier2 = bezier2.Invert();
             *  invert = true;
             * }
             * else
             * {
             *  throw new Exception(string.Format("Error - no intersection of bezier and point. Dist: {0}, {1}",Distance(nodePos2d,bezier2.Position(0f)), Distance(nodePos2d, bezier2.Position(1f))));
             * }*/
            startDirection2d = bezier2.Tangent(0f);
            endDirection2d   = bezier2.Tangent(1f);

            Vector3 startDirection = (new Vector3(startDirection2d.x, 0, startDirection2d.y));
            Vector3 endDirection   = -(new Vector3(endDirection2d.x, 0, endDirection2d.y));

            /* Unlike from the old algorithm, we use no padding when looking for the segments. That means the obtained segments can be arbitrarily short.
             * In that case, we take one more segment away from the ellipse.*/
            if (VectorDistance(bezier2.a, bezier2.d) < MIN_BEZIER_LENGTH)
            {
                //Debug.Log("Segment is too short. Launching repair mechainsm." + VectorDistance(bezier2.a, bezier2.d));
                if (nextSegmentInfo(endNodeId, oldSegmentId, out ushort endNodeIdNew, out Vector3 endDirectionNew))
                {
                    endNodeId    = endNodeIdNew;
                    endDirection = endDirectionNew;
                    //Debug.Log("The segment length should be " + VectorDistance(GetNode(startNodeId).m_position,GetNode(endNodeId).m_position));
                    //EllipseTool.Instance.debugDrawPositions.Add(GetNode(endNodeIdNew).m_position);
                }
            }

            // Debug
            // EllipseTool.Instance.debugDrawVector(20*startDirection, GetNode(startNodeId).m_position);
            // EllipseTool.Instance.debugDrawVector(20*endDirection, GetNode(endNodeId).m_position);

            startDirection.Normalize();
            endDirection.Normalize();

            if (oldSegment.m_flags.IsFlagSet(NetSegment.Flags.Invert))
            {
                invert = !invert;
            }

            try
            {
                ushort newSegmentId = NetAccess.CreateSegment(startNodeId, endNodeId,
                                                              startDirection, endDirection, oldSegment.Info, invert);

                m_group.Actions.Add(new EnteringBlockedJunctionAllowedAction(newSegmentId, true, true));
                m_group.Actions.Add(new YieldSignAction(newSegmentId, true));
            }
            catch (Exception e)
            {
                UIWindow2.instance.ThrowErrorMsg("The game failed to create one of the road segments.");
                Debug.LogError(e.ToString());
            }
        }
Exemple #20
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);
        }