Ejemplo n.º 1
0
        protected IEnumerable <MarkupStyleDash> CalculateDashed(Bezier3 trajectory, float dashLength, float spaceLength, Func <Bezier3, float, float, IEnumerable <MarkupStyleDash> > calculateDashes)
        {
            var dashesT = new List <float[]>();

            var startSpace = spaceLength / 2;

            for (var i = 0; i < 3; i += 1)
            {
                dashesT.Clear();
                var isDash = false;

                var prevT    = 0f;
                var currentT = 0f;
                var nextT    = trajectory.Travel(currentT, startSpace);

                while (nextT < 1)
                {
                    if (isDash)
                    {
                        dashesT.Add(new float[] { currentT, nextT });
                    }

                    isDash = !isDash;

                    prevT    = currentT;
                    currentT = nextT;
                    nextT    = trajectory.Travel(currentT, isDash ? dashLength : spaceLength);
                }

                float endSpace;
                if (isDash || ((trajectory.Position(1) - trajectory.Position(currentT)).magnitude is float tempLength && tempLength < spaceLength / 2))
                {
                    endSpace = (trajectory.Position(1) - trajectory.Position(prevT)).magnitude;
                }
Ejemplo n.º 2
0
        /// <summary>
        /// Returns E'(t) = E'(tGuess) : Derivative of +/- Error [meters^2] in (straight-line distance between two points on a bezier curve) vs (radius).
        /// </summary>
        /// <param name="bezier"></param>
        /// <param name="t">Where are you guessing the intersection is?</param>
        /// <param name="tCenter">Center of the circle to intersect the curve.</param>
        /// <returns></returns>
        private static float PLTErrorFunctionPrimeXZ(Bezier3 bezier, float t, float tCenter)
        {
            float result = 0f;

            if (t == tCenter)
            {
                return(0f);
            }

            Vector3 _center = bezier.Position(tCenter);
            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)

            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);
        }
Ejemplo n.º 3
0
        public static float CalculateLength(this Bezier3 curve, int steps = 10)
        {
            float   t1  = 0.0f;
            Vector3 b   = curve.Position(t1);
            float   num = 0.0f;

            for (int index = 1; index <= steps; ++index)
            {
                float   t2 = (float)index / (float)steps;
                Vector3 a  = curve.Position(t2);
                num += Vector3.Distance(a, b);
                b    = a;
            }
            return(num);
        }
Ejemplo n.º 4
0
        // FIXME: Lines aren't always drawn
        void RenderUndergroundLane(Bezier3 bezier, Color color, float size)
        {
            Material mat = new Material(Shader.Find("Legacy Shaders/VertexLit"));

            mat.color = color;
            Mesh    quadMesh = new Mesh();
            Vector3 start    = bezier.Position(0f);

            for (int i = 1; i <= 10; i++)
            {
                Vector3 end    = bezier.Position(i / 10f);
                Vector3 normal = Vector3.up;                 //Vector3.Cross(start, end);
                Vector3 side   = Vector3.Cross(normal, end - start);
                side.Normalize();

                Vector3[] vertices = new Vector3[]
                {
                    start + side * (size / 2f) + Vector3.up * 0.1f,
                    start + side * (-size / 2f) + Vector3.up * 0.1f,
                    end + side * (size / 2f) + Vector3.up * 0.1f,
                    end + side * (-size / 2f) + Vector3.up * 0.1f,
                };
                quadMesh.vertices = vertices;

                int[] tri = new int[]
                {
                    0, 1, 3,
                    3, 2, 0
                };
                quadMesh.triangles = tri;

                Vector3[] normals = new Vector3[]
                {
                    normal, normal, normal, normal
                };
                quadMesh.normals = normals;

                if (mat.SetPass(0))
                {
                    Graphics.DrawMeshNow(quadMesh, Matrix4x4.identity);
                }
                //else
                //	System.IO.File.AppendAllText("RenderMesh.txt", "NO GO!!\n");
                //Graphics.DrawMesh(quadMesh, Vector3.zero, Quaternion.identity, mat);

                start = end;
            }
        }
Ejemplo n.º 5
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;
        }
Ejemplo n.º 6
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));
        }
Ejemplo n.º 7
0
        private void CalculatePositionAndRotation(ushort vehicleID, ref Vehicle vehicleData, out Vector3 position, out Vector3 swayPosition, out Quaternion rotation)
        {
            uint targetFrame = vehicleData.GetTargetFrame(m_info, vehicleID);

            Vehicle.Frame frameData  = vehicleData.GetFrameData(targetFrame - 32);
            Vehicle.Frame frameData2 = vehicleData.GetFrameData(targetFrame - 16);
            float         t          = ((float)(targetFrame & 0xF) + Singleton <SimulationManager> .instance.m_referenceTimer) * 0.0625f;
            Bezier3       bezier     = default(Bezier3);

            bezier.a = frameData.m_position;
            bezier.b = frameData.m_position + frameData.m_velocity * 0.333f;
            bezier.c = frameData2.m_position - frameData2.m_velocity * 0.333f;
            bezier.d = frameData2.m_position;
            position = bezier.Position(t);
            Bezier3 bezier2 = default(Bezier3);

            bezier2.a       = frameData.m_swayPosition;
            bezier2.b       = frameData.m_swayPosition + frameData.m_swayVelocity * 0.333f;
            bezier2.c       = frameData2.m_swayPosition - frameData2.m_swayVelocity * 0.333f;
            bezier2.d       = frameData2.m_swayPosition;
            swayPosition    = bezier2.Position(t);
            swayPosition.x *= m_info.m_leanMultiplier / Mathf.Max(1f, m_info.m_generatedInfo.m_wheelGauge);
            swayPosition.z *= m_info.m_nodMultiplier / Mathf.Max(1f, m_info.m_generatedInfo.m_wheelBase);
            rotation        = Quaternion.Lerp(frameData.m_rotation, frameData2.m_rotation, t);
        }
        private List <Vector2> BezierToPoints(List <Segment> list)
        {
            var result = new List <Vector2>();

            result.Add(list[0].startPoint);
            foreach (var seg in list)
            {
                if (seg.controlA == Vector2.zero)
                {
                    result.Add(seg.endPoint);
                }
                else
                {
                    var bezier = new Bezier3(seg.startPoint, seg.controlA, seg.controlB, seg.endPoint);
                    var steps  = Mathf.RoundToInt((seg.endPoint - seg.startPoint).magnitude / 50) + 1;
                    for (var i = 0; i <= steps; i += 1)
                    {
                        if (i == 0)
                        {
                            continue;
                        }
                        result.Add(bezier.Position(i / (float)steps));
                    }
                }
            }
            return(result);
        }
Ejemplo n.º 9
0
        public static float ArcLength(this Bezier3 beizer, float step = 0.1f)
        {
            float ret = 0;
            float t;

            for (t = step; t < 1f; t += step)
            {
                float len = (beizer.Position(t) - beizer.Position(t - step)).magnitude;
                ret += len;
            }
            {
                float len = (beizer.d - beizer.Position(t - step)).magnitude;
                ret += len;
            }
            return(ret);
        }
Ejemplo n.º 10
0
        //used to calculate t in non-fence Curved and Freeform modes
        //for each individual item
        /// <summary>
        /// Solves for t-value which would be a length of *distance* along the curve from original point at t = *tStart*.
        /// </summary>
        /// <param name="bezier"></param>
        /// <param name="tStart"></param>
        /// <param name="distance"></param>
        /// <param name="tolerance"></param>
        /// <param name="tEnd"></param>
        public static void StepDistanceCurve(Bezier3 bezier, float tStart, float distance, float tolerance, out float tEnd)
        {
            float _tCurrent = 0f;

            _tCurrent = bezier.Travel(tStart, distance);
            float _tStepInitial = _tCurrent - tStart;

            Vector3 _posCurrent = bezier.Position(_tCurrent);

            float _distCurrent  = CubicBezierArcLengthXZGauss04(bezier, tStart, _tCurrent);
            float _toleranceSqr = tolerance * tolerance;

            if (Mathf.Pow(distance - _distCurrent, 2f) >= _toleranceSqr)
            {
                float _localSpeed     = CubicSpeedXZ(bezier, _tCurrent);
                float _distDifference = distance - _distCurrent;

                int _counter = 0;
                while (_counter < 12 && (Mathf.Pow(_distDifference, 2f) > _toleranceSqr))
                {
                    _distCurrent    = CubicBezierArcLengthXZGauss04(bezier, tStart, _tCurrent);
                    _distDifference = distance - _distCurrent;
                    _localSpeed     = CubicSpeedXZ(bezier, _tCurrent);

                    _tCurrent = _tCurrent + _distDifference / _localSpeed;
                    _counter++;
                }
            }

            tEnd = _tCurrent;
        }
Ejemplo n.º 11
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);
        }
        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);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Returns E(t) = E(tGuess) : +/- Error [meters^2] in (straight-line distance between two points on a bezier curve) vs (radius).
        /// </summary>
        /// <param name="bezier"></param>
        /// <param name="t">Where are you guessing the intersection is?</param>
        /// <param name="tCenter">Center of the circle to intersect the curve.</param>
        /// <param name="radius">Radius of the circle to intersect the curve.</param>
        /// <returns></returns>
        private static float PLTErrorFunctionXZ(Bezier3 bezier, float t, float tCenter, float radius)
        {
            float result = 100f;

            if (t == tCenter)
            {
                return(0f);
            }

            Vector3 _center = bezier.Position(tCenter);
            float   x_c     = _center.x;
            float   z_c     = _center.z;

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

            result = Mathf.Pow(_x - x_c, 2f) + Mathf.Pow(_z - z_c, 2f) - Mathf.Pow(radius, 2f);

            return(result);
        }
Ejemplo n.º 14
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));
        }
Ejemplo n.º 15
0
        public static Vector3 GetHitPosition(this Bezier3 bezier, Segment3 ray, out float rayT, out float bezierT, out Vector3 position)
        {
            var hitPos = ray.GetRayPosition(bezier.Position(0.5f).y, out rayT);

            bezier.ClosestPositionAndDirection(hitPos, out position, out _, out bezierT);

            for (var i = 0; i < 3 && Mathf.Abs(hitPos.y - position.y) > 1f; i += 1)
            {
                hitPos = ray.GetRayPosition(position.y, out rayT);
                bezier.ClosestPositionAndDirection(hitPos, out position, out _, out bezierT);
            }

            return(hitPos);
        }
Ejemplo n.º 16
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);
            }
        }
Ejemplo n.º 17
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);
        }
Ejemplo n.º 18
0
        protected static void CalcParts(Bezier3 bezier, out int parts, out float[] points, out Vector3[] positons)
        {
            bezier.Divide(out Bezier3 b1, out Bezier3 b2);
            var length = (b1.d - b1.a).magnitude + (b2.d - b2.a).magnitude;

            parts = Math.Min((int)Math.Ceiling(length / MinLength), 10);

            points        = new float[parts + 1];
            points[0]     = 0;
            points[parts] = 1;

            positons        = new Vector3[parts + 1];
            positons[0]     = bezier.a;
            positons[parts] = bezier.d;

            for (var i = 1; i < parts; i += 1)
            {
                points[i]   = (1f / parts) * i;
                positons[i] = bezier.Position(points[i]);
            }
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Specialty Version of PLTErrorFunctionXZ used to link curves. Returns E(t) = E(tGuess) : +/- 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>
        /// <param name="radius">Radius of the circle to intersect the curve.</param>
        /// <returns></returns>
        private static float PLTLinkErrorFunctionXZ(Bezier3 bezier, float t, Vector3 centerPos, float radius)
        {
            float result = 100f;

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

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

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

            result = Mathf.Pow(_x - x_c, 2f) + Mathf.Pow(_z - z_c, 2f) - Mathf.Pow(radius, 2f);

            return(result);
        }
Ejemplo n.º 20
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);
        }
Ejemplo n.º 21
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);
                }
            }
        }
Ejemplo n.º 22
0
        // FIXME: Lines aren't always drawn
        void RenderUndergroundLane(Bezier3 bezier, Color color, float size)
        {
            Material mat = new Material(Shader.Find("Legacy Shaders/VertexLit"));
            mat.color = color;
            Mesh quadMesh = new Mesh();
            Vector3 start = bezier.Position(0f);
            for (int i = 1; i <= 10; i++)
            {
                Vector3 end = bezier.Position(i / 10f);
                Vector3 normal = Vector3.up; //Vector3.Cross(start, end);
                Vector3 side = Vector3.Cross(normal, end - start);
                side.Normalize();

                Vector3[] vertices = new Vector3[]
                {
                    start + side * (size / 2f) + Vector3.up * 0.1f,
                    start + side * (-size / 2f) + Vector3.up * 0.1f,
                    end + side * (size / 2f) + Vector3.up * 0.1f,
                    end + side * (-size / 2f) + Vector3.up * 0.1f,
                };
                quadMesh.vertices = vertices;

                int[] tri = new int[]
                {
                    0, 1, 3,
                    3, 2, 0
                };
                quadMesh.triangles = tri;

                Vector3[] normals = new Vector3[]
                {
                    normal, normal, normal, normal
                };
                quadMesh.normals = normals;

                if (mat.SetPass(0))
                    Graphics.DrawMeshNow(quadMesh, Matrix4x4.identity);
                start = end;
            }
        }
Ejemplo n.º 23
0
        public string ExportSegment(NetSegment a_seg, ref int segId, ref System.Reflection.PropertyInfo[] properties)
        {
            var startNodeId    = a_seg.m_startNode;
            var endNodeId      = a_seg.m_endNode;
            var startDirection = a_seg.m_startDirection;
            var endDirection   = a_seg.m_endDirection;

            if ((a_seg.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
            {
                startNodeId    = a_seg.m_endNode;
                endNodeId      = a_seg.m_startNode;
                startDirection = a_seg.m_endDirection;
                endDirection   = a_seg.m_startDirection;
            }

            var road_name = net_manager.GetSegmentName((ushort)segId);

            if (road_name == null || road_name == "")
            {
                road_name = "no name " + segId.ToString();
            }

            var    startPos   = net_manager.m_nodes.m_buffer[startNodeId].m_position;
            LatLng startRwoLL = GamePosition2LatLng(startPos);

            var    endPos   = net_manager.m_nodes.m_buffer[endNodeId].m_position;
            LatLng endRwoLL = GamePosition2LatLng(endPos);

            string wkt = "";

            if (Vector3.Angle(startDirection, -endDirection) > 3f)
            {
                Vector3 a = Vector3.zero;
                Vector3 b = Vector3.zero;
                NetSegment.CalculateMiddlePoints(startPos, startDirection, endPos, endDirection, false, false, out a, out b);
                var bezier = new Bezier3(startPos, a, b, endPos);

                var p1      = bezier.Position(0.25f);
                var p1RwoLL = GamePosition2LatLng(p1);
                var p2      = bezier.Position(0.5f);
                var p2RwoLL = GamePosition2LatLng(p2);
                var p3      = bezier.Position(0.5f);
                var p3RwoLL = GamePosition2LatLng(p3);

                LatLng[] listOfPositions = new LatLng[] { startRwoLL, p1RwoLL, p2RwoLL, p3RwoLL, endRwoLL };

                wkt = CreateWkt(listOfPositions);
            }
            else
            {
                wkt = CreateWkt(new LatLng[] { startRwoLL, endRwoLL });
            }

            float tmpY  = tm.SampleRawHeightSmoothWithWater(startPos, false, 0f);
            float elevS = startPos.y - tmpY;

            tmpY = tm.SampleRawHeightSmoothWithWater(endPos, false, 0f);
            float elevE = endPos.y - tmpY;

            string rowTxt = string.Format("{0},{1},{2},{3},{4}", segId, road_name, wkt, elevS, elevE);

            string field_info = "";

            foreach (var prop in properties)
            {
                var prop_val = prop.GetValue(a_seg, null);
                if (prop_val.ToString().Contains(","))
                {
                    prop_val = "\"" + prop_val.ToString() + "\"";
                }
                field_info += string.Format(",{0}", prop_val);
            }
            rowTxt += field_info;
            return(rowTxt);
        }
Ejemplo n.º 24
0
        private bool TrySnapNodeDirections(ushort node, Vector3 newPosition, Vector3 moveDelta, out Vector3 newMoveDelta, out bool autoCurve)
        {
            string snapType = "";

            m_segmentGuide = default;

            NetManager netManager = NetManager.instance;

            NetSegment[] segmentBuffer = netManager.m_segments.m_buffer;
            NetNode[]    nodeBuffer    = netManager.m_nodes.m_buffer;

            float minSqDistance = nodeBuffer[node].Info.GetMinNodeDistance() / 2f;

            minSqDistance *= minSqDistance;

            autoCurve    = false;
            newMoveDelta = moveDelta;
            float distanceSq = minSqDistance;

            bool snap = false;

            // Snap to curve
            for (int i = 0; i < 8; i++)
            {
                ushort segmentA = nodeBuffer[node].GetSegment(i);
                if (segmentA != 0)
                {
                    for (int j = i + 1; j < 8; j++)
                    {
                        ushort segmentB = nodeBuffer[node].GetSegment(j);

                        if (segmentB != 0 && segmentB != segmentA)
                        {
                            NetSegment segment = default;
                            segment.m_startNode = segmentBuffer[segmentA].m_startNode == node ? segmentBuffer[segmentA].m_endNode : segmentBuffer[segmentA].m_startNode;
                            segment.m_endNode   = segmentBuffer[segmentB].m_startNode == node ? segmentBuffer[segmentB].m_endNode : segmentBuffer[segmentB].m_startNode;

                            segment.m_startDirection = (nodeBuffer[segment.m_endNode].m_position - nodeBuffer[segment.m_startNode].m_position).normalized;
                            segment.m_endDirection   = -segment.m_startDirection;

                            segment.GetClosestPositionAndDirection(newPosition, out Vector3 testPos, out Vector3 direction);
                            // Straight
                            if (TrySnapping(testPos, newPosition, minSqDistance, ref distanceSq, moveDelta, ref newMoveDelta))
                            {
                                autoCurve      = true;
                                m_segmentGuide = segment;
                                snapType       = "Straight";
                                snap           = true;
                            }

                            for (int k = 0; k < 8; k++)
                            {
                                ushort segmentC = nodeBuffer[segment.m_startNode].GetSegment(k);
                                if (segmentC != 0 && segmentC != segmentA)
                                {
                                    for (int l = 0; l < 8; l++)
                                    {
                                        ushort segmentD = nodeBuffer[segment.m_endNode].GetSegment(l);

                                        if (segmentD != 0 && segmentD != segmentB)
                                        {
                                            segment.m_startDirection = segmentBuffer[segmentC].m_startNode == segment.m_startNode ? -segmentBuffer[segmentC].m_startDirection : -segmentBuffer[segmentC].m_endDirection;
                                            segment.m_endDirection   = segmentBuffer[segmentD].m_startNode == segment.m_endNode ? -segmentBuffer[segmentD].m_startDirection : -segmentBuffer[segmentD].m_endDirection;

                                            Vector2 A     = VectorUtils.XZ(nodeBuffer[segment.m_endNode].m_position - nodeBuffer[segment.m_startNode].m_position).normalized;
                                            Vector2 B     = VectorUtils.XZ(segment.m_startDirection);
                                            float   side1 = A.x * B.y - A.y * B.x;

                                            B = VectorUtils.XZ(segment.m_endDirection);
                                            float side2 = A.x * B.y - A.y * B.x;

                                            if (Mathf.Sign(side1) != Mathf.Sign(side2) ||
                                                (side1 != side2 && (side1 == 0 || side2 == 0)) ||
                                                Vector2.Dot(A, VectorUtils.XZ(segment.m_startDirection)) < 0 ||
                                                Vector2.Dot(A, VectorUtils.XZ(segment.m_endDirection)) > 0)
                                            {
                                                continue;
                                            }

                                            Bezier3 bezier = default;
                                            bezier.a = Singleton <NetManager> .instance.m_nodes.m_buffer[segment.m_startNode].m_position;
                                            bezier.d = Singleton <NetManager> .instance.m_nodes.m_buffer[segment.m_endNode].m_position;
                                            bool smoothStart = (Singleton <NetManager> .instance.m_nodes.m_buffer[segment.m_startNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None;
                                            bool smoothEnd   = (Singleton <NetManager> .instance.m_nodes.m_buffer[segment.m_endNode].m_flags & NetNode.Flags.Middle) != NetNode.Flags.None;
                                            NetSegment.CalculateMiddlePoints(bezier.a, segment.m_startDirection, bezier.d, segment.m_endDirection, smoothStart, smoothEnd, out bezier.b, out bezier.c);

                                            testPos = bezier.Position(0.5f);
                                            // Curve Middle
                                            if (TrySnapping(testPos, newPosition, minSqDistance, ref distanceSq, moveDelta, ref newMoveDelta))
                                            {
                                                autoCurve      = true;
                                                m_segmentGuide = segment;
                                                snapType       = "Curve Middle";
                                                snap           = true;
                                            }
                                            else
                                            {
                                                segment.GetClosestPositionAndDirection(newPosition, out testPos, out direction);
                                                // Curve
                                                if (TrySnapping(testPos, newPosition, minSqDistance, ref distanceSq, moveDelta, ref newMoveDelta))
                                                {
                                                    autoCurve      = true;
                                                    m_segmentGuide = segment;
                                                    snapType       = "Curve";
                                                    snap           = true;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            // Snap to tangent
            for (int i = 0; i < 8; i++)
            {
                ushort segment = nodeBuffer[node].GetSegment(i);
                if (segment != 0)
                {
                    ushort  testNode = segmentBuffer[segment].m_startNode == node ? segmentBuffer[segment].m_endNode : segmentBuffer[segment].m_startNode;
                    Vector3 testPos  = nodeBuffer[testNode].m_position;

                    for (int j = 0; j < 8; j++)
                    {
                        ushort segmentA = nodeBuffer[testNode].GetSegment(j);
                        if (segmentA != 0 && segmentA != segment)
                        {
                            // Straight
                            Vector3 startDir = segmentBuffer[segmentA].m_startNode == testNode ? segmentBuffer[segmentA].m_startDirection : segmentBuffer[segmentA].m_endDirection;
                            Vector3 offset   = Line2.Offset(startDir, testPos - newPosition);
                            offset = newPosition + offset - testPos;
                            float num = offset.x * startDir.x + offset.z * startDir.z;

                            if (TrySnapping(testPos + startDir * num, newPosition, minSqDistance, ref distanceSq, moveDelta, ref newMoveDelta))
                            {
                                m_segmentGuide = default;

                                m_segmentGuide.m_startNode = node;
                                m_segmentGuide.m_endNode   = testNode;

                                m_segmentGuide.m_startDirection = startDir;
                                m_segmentGuide.m_endDirection   = -startDir;
                                snapType  = "Tangent Straight";
                                autoCurve = false;
                                snap      = true;
                            }
                            else
                            {
                                // 90°
                                startDir = new Vector3(-startDir.z, startDir.y, startDir.x);
                                offset   = Line2.Offset(startDir, testPos - newPosition);
                                offset   = newPosition + offset - testPos;
                                num      = offset.x * startDir.x + offset.z * startDir.z;

                                if (TrySnapping(testPos + startDir * num, newPosition, minSqDistance, ref distanceSq, moveDelta, ref newMoveDelta))
                                {
                                    m_segmentGuide = default;

                                    m_segmentGuide.m_startNode = node;
                                    m_segmentGuide.m_endNode   = testNode;

                                    m_segmentGuide.m_startDirection = startDir;
                                    m_segmentGuide.m_endDirection   = -startDir;
                                    snapType  = "Tangent 90°";
                                    autoCurve = false;
                                    snap      = true;
                                }
                            }
                        }
                    }
                }
            }

            if (snap)
            {
                DebugUtils.Log("Snapping " + snapType + " " + autoCurve);
            }

            return(snap);
        }
        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);
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Create curved zone blocks.
        /// </summary>
        /// <param name="info">Network prefab</param>
        /// <param name="randomizer">Randomizer</param>
        /// <param name="segment">Network segment</param>
        private static void CurvedZoneBlocks(NetInfo info, Randomizer randomizer, ref NetSegment segment)
        {
#pragma warning disable IDE0018 // Inline variable declaration

            // TODO: Basically game code with some NExT2 modifications.  Could do with a good refactor, and possible replacement with Transpiler.

            var minHalfWidth = MIN_HALFWIDTH_TINY_CURVE;

            NetManager instance       = Singleton <NetManager> .instance;
            Vector3    startPosition  = instance.m_nodes.m_buffer[(int)segment.m_startNode].m_position;
            Vector3    endPosition    = instance.m_nodes.m_buffer[(int)segment.m_endNode].m_position;
            Vector3    startDirection = segment.m_startDirection;
            Vector3    endDirection   = segment.m_endDirection;


            float num      = startDirection.x * endDirection.x + startDirection.z * endDirection.z;
            float num2     = Mathf.Max(minHalfWidth, info.m_halfWidth); // minHalfWidth here.
            float num3     = 32f;
            int   distance = Mathf.RoundToInt(num2);

            float num4  = VectorUtils.LengthXZ(endPosition - startPosition);
            bool  flag2 = startDirection.x * endDirection.z - startDirection.z * endDirection.x > 0f;
            bool  flag3 = num <-0.8f || num4> 50f;
            if (flag2)
            {
                num2 = -num2;
                num3 = -num3;
            }
            Vector3 vector  = startPosition - new Vector3(startDirection.z, 0f, -startDirection.x) * num2;
            Vector3 vector2 = endPosition + new Vector3(endDirection.z, 0f, -endDirection.x) * num2;
            Vector3 vector3;
            Vector3 vector4;
            NetSegment.CalculateMiddlePoints(vector, startDirection, vector2, endDirection, true, true, out vector3, out vector4);
            if (flag3)
            {
                float num5 = num * 0.025f + 0.04f;
                float num6 = num * 0.025f + 0.06f;
                if (num < -0.9f)
                {
                    num6 = num5;
                }
                Bezier3 bezier = new Bezier3(vector, vector3, vector4, vector2);
                vector  = bezier.Position(num5);
                vector3 = bezier.Position(0.5f - num6);
                vector4 = bezier.Position(0.5f + num6);
                vector2 = bezier.Position(1f - num5);
            }
            else
            {
                Bezier3 bezier2 = new Bezier3(vector, vector3, vector4, vector2);
                vector3 = bezier2.Position(0.86f);
                vector  = bezier2.Position(0.14f);
            }
            float   num7;
            Vector3 vector5 = VectorUtils.NormalizeXZ(vector3 - vector, out num7);
            int     num8    = Mathf.FloorToInt(num7 / 8f + 0.01f);
            float   num9    = num7 * 0.5f + (float)(num8 - 8) * ((!flag2) ? -4f : 4f);
            if (num8 != 0)
            {
                float   angle     = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z);
                Vector3 position3 = vector + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3);
                if (flag2)
                {
                    Singleton <ZoneManager> .instance.CreateBlock(
                        out segment.m_blockStartRight,
                        ref randomizer,
                        position3,
                        angle,
                        num8,
                        distance,
                        segment.m_buildIndex);
                }
                else
                {
                    Singleton <ZoneManager> .instance.CreateBlock(
                        out segment.m_blockStartLeft,
                        ref randomizer,
                        position3,
                        angle,
                        num8,
                        distance,
                        segment.m_buildIndex);
                }
            }
            if (flag3)
            {
                vector5 = VectorUtils.NormalizeXZ(vector2 - vector4, out num7);
                num8    = Mathf.FloorToInt(num7 / 8f + 0.01f);
                num9    = num7 * 0.5f + (float)(num8 - 8) * ((!flag2) ? -4f : 4f);
                if (num8 != 0)
                {
                    float   angle2    = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z);
                    Vector3 position4 = vector4 + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3);
                    if (flag2)
                    {
                        Singleton <ZoneManager> .instance.CreateBlock(
                            out segment.m_blockEndRight,
                            ref randomizer,
                            position4,
                            angle2,
                            num8,
                            distance,
                            segment.m_buildIndex + 1u);
                    }
                    else
                    {
                        Singleton <ZoneManager> .instance.CreateBlock(
                            out segment.m_blockEndLeft,
                            ref randomizer,
                            position4,
                            angle2,
                            num8,
                            distance,
                            segment.m_buildIndex + 1u);
                    }
                }
            }
            Vector3 vector6 = startPosition + new Vector3(startDirection.z, 0f, -startDirection.x) * num2;
            Vector3 vector7 = endPosition - new Vector3(endDirection.z, 0f, -endDirection.x) * num2;
            Vector3 b;
            Vector3 c;
            NetSegment.CalculateMiddlePoints(vector6, startDirection, vector7, endDirection, true, true, out b, out c);
            Bezier3 bezier3 = new Bezier3(vector6, b, c, vector7);
            Vector3 vector8 = bezier3.Position(0.5f);
            Vector3 vector9 = bezier3.Position(0.25f);
            vector9 = Line2.Offset(VectorUtils.XZ(vector6), VectorUtils.XZ(vector8), VectorUtils.XZ(vector9));
            Vector3 vector10 = bezier3.Position(0.75f);
            vector10 = Line2.Offset(VectorUtils.XZ(vector7), VectorUtils.XZ(vector8), VectorUtils.XZ(vector10));
            Vector3 vector11 = vector6;
            Vector3 a        = vector7;
            float   d;
#pragma warning disable IDE0059 // Unnecessary assignment of a value
            float num10;
            if (Line2.Intersect(VectorUtils.XZ(startPosition), VectorUtils.XZ(vector6), VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), out d, out num10))
            {
                vector6 = startPosition + (vector6 - startPosition) * d;
            }
            if (Line2.Intersect(VectorUtils.XZ(endPosition), VectorUtils.XZ(vector7), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10))
            {
                vector7 = endPosition + (vector7 - endPosition) * d;
            }
            if (Line2.Intersect(VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10))
#pragma warning restore IDE0059 // Unnecessary assignment of a value
            {
                vector8 = vector11 - vector9 + (vector8 - vector11) * d;
            }
            float   num11;
            Vector3 vector12 = VectorUtils.NormalizeXZ(vector8 - vector6, out num11);
            int     num12    = Mathf.FloorToInt(num11 / 8f + 0.01f);
            float   num13    = num11 * 0.5f + (float)(num12 - 8) * ((!flag2) ? 4f : -4f);
            if (num12 != 0)
            {
                float   angle3    = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z);
                Vector3 position5 = vector6 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3);
                if (flag2)
                {
                    Singleton <ZoneManager> .instance.CreateBlock(
                        out segment.m_blockStartLeft,
                        ref randomizer,
                        position5,
                        angle3,
                        num12,
                        distance,
                        segment.m_buildIndex);
                }
                else
                {
                    Singleton <ZoneManager> .instance.CreateBlock(
                        out segment.m_blockStartRight,
                        ref randomizer,
                        position5,
                        angle3,
                        num12,
                        distance,
                        segment.m_buildIndex);
                }
            }
            vector12 = VectorUtils.NormalizeXZ(vector7 - vector8, out num11);
            num12    = Mathf.FloorToInt(num11 / 8f + 0.01f);
            num13    = num11 * 0.5f + (float)(num12 - 8) * ((!flag2) ? 4f : -4f);
            if (num12 != 0)
            {
                float   angle4    = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z);
                Vector3 position6 = vector8 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3);
                if (flag2)
                {
                    Singleton <ZoneManager> .instance.CreateBlock(
                        out segment.m_blockEndLeft,
                        ref randomizer,
                        position6,
                        angle4,
                        num12,
                        distance,
                        segment.m_buildIndex + 1u);
                }
                else
                {
                    Singleton <ZoneManager> .instance.CreateBlock(
                        out segment.m_blockEndRight,
                        ref randomizer,
                        position6,
                        angle4,
                        num12,
                        distance,
                        segment.m_buildIndex + 1u);
                }
            }
#pragma warning restore IDE0018 // Inline variable declaration
        }
Ejemplo n.º 27
0
        public static bool RenderInstancePrefix(CitizenInstance __instance, RenderManager.CameraInfo cameraInfo, ushort instanceID, ref bool __result)
        {
            if ((__instance.m_flags & Flags.Character) == 0)
            {
                __result = false;
                return(false);
            }
            CitizenInfo info = __instance.Info;

            if (info == null)
            {
                __result = false;
                return(false);
            }
            uint  num         = (uint)(instanceID << 4) / 65536u;
            uint  num2        = Singleton <SimulationManager> .instance.m_referenceFrameIndex - num;
            Frame frameData   = __instance.GetFrameData(num2 - 32);
            float maxDistance = Mathf.Min(RenderManager.LevelOfDetailFactor * 800f, info.m_maxRenderDistance + cameraInfo.m_height * 0.5f);

            if (!cameraInfo.CheckRenderDistance(frameData.m_position, maxDistance))
            {
                __result = false;
                return(false);
            }
            if (!cameraInfo.Intersect(frameData.m_position, 10f))
            {
                __result = false;
                return(false);
            }
            Frame frameData2 = __instance.GetFrameData(num2 - 16);
            float t          = ((float)(double)(num2 & 0xF) + Singleton <SimulationManager> .instance.m_referenceTimer) * 0.0625f;
            bool  flag       = frameData2.m_underground && frameData.m_underground;
            bool  flag2      = frameData2.m_insideBuilding && frameData.m_insideBuilding;
            bool  flag3      = frameData2.m_transition || frameData.m_transition;

            if ((flag2 && !flag3) || (flag && !flag3 && (cameraInfo.m_layerMask & (1 << Singleton <CitizenManager> .instance.m_undergroundLayer)) == 0))
            {
                __result = false;
                return(false);
            }
            Bezier3 bezier = default(Bezier3);

            bezier.a = frameData.m_position;
            bezier.b = frameData.m_position + frameData.m_velocity * 0.333f;
            bezier.c = frameData2.m_position - frameData2.m_velocity * 0.333f;
            bezier.d = frameData2.m_position;
            Vector3    vector     = bezier.Position(t);
            Quaternion quaternion = Quaternion.Lerp(frameData.m_rotation, frameData2.m_rotation, t);
            Color      color      = info.m_citizenAI.GetColor(instanceID, ref __instance, Singleton <InfoManager> .instance.CurrentMode);

            var action = new Action(() =>
            {
                if (cameraInfo.CheckRenderDistance(vector, info.m_lodRenderDistance))
                {
                    InstanceID empty        = InstanceID.Empty;
                    empty.CitizenInstance   = instanceID;
                    CitizenInfo citizenInfo = info.ObtainPrefabInstance <CitizenInfo>(empty, 255);
                    if (citizenInfo != null)
                    {
                        Vector3 velocity = Vector3.Lerp(frameData.m_velocity, frameData2.m_velocity, t);
                        citizenInfo.m_citizenAI.SetRenderParameters(cameraInfo, instanceID, ref __instance, vector, quaternion, velocity, color, (flag || flag3) && (cameraInfo.m_layerMask & (1 << Singleton <CitizenManager> .instance.m_undergroundLayer)) != 0);
                        return;
                    }
                }
                if (flag || flag3)
                {
                    info.m_undergroundLodLocations[info.m_undergroundLodCount].SetTRS(vector, quaternion, Vector3.one);
                    info.m_undergroundLodColors[info.m_undergroundLodCount] = color.linear;
                    info.m_undergroundLodMin = Vector3.Min(info.m_undergroundLodMin, vector);
                    info.m_undergroundLodMax = Vector3.Max(info.m_undergroundLodMax, vector);
                    if (++info.m_undergroundLodCount == info.m_undergroundLodLocations.Length)
                    {
                        RenderUndergroundLod(cameraInfo, info);
                    }
                }
                if (!flag || flag3)
                {
                    info.m_lodLocations[info.m_lodCount].SetTRS(vector, quaternion, Vector3.one);
                    info.m_lodColors[info.m_lodCount] = color.linear;
                    info.m_lodMin = Vector3.Min(info.m_lodMin, vector);
                    info.m_lodMax = Vector3.Max(info.m_lodMax, vector);
                    if (++info.m_lodCount == info.m_lodLocations.Length)
                    {
                        RenderLod(cameraInfo, info);
                    }
                }
            });

#if UseTask
            Patcher.Dispatcher.Add(action);
#else
            action.Invoke();
#endif
            __result = true;
            return(false);
        }
Ejemplo n.º 28
0
        public void CustomCheckNextLane(ushort vehicleID, ref Vehicle vehicleData, ref float maxSpeed, PathUnit.Position position, uint laneID, byte offset, PathUnit.Position prevPos, uint prevLaneID, byte prevOffset, Bezier3 bezier)
        {
            if ((Options.prioritySignsEnabled || Options.timedLightsEnabled) && Options.simAccuracy <= 1)
            {
                try {
                    VehicleStateManager.Instance().UpdateVehiclePos(vehicleID, ref vehicleData, ref prevPos, ref position);
                } catch (Exception e) {
                    Log.Error("TrainAI CustomCheckNextLane Error: " + e.ToString());
                }
            }

            NetManager instance = Singleton <NetManager> .instance;

            Vehicle.Frame lastFrameData = vehicleData.GetLastFrameData();
            Vector3       a             = lastFrameData.m_position;
            Vector3       a2            = lastFrameData.m_position;
            Vector3       b             = lastFrameData.m_rotation * new Vector3(0f, 0f, this.m_info.m_generatedInfo.m_wheelBase * 0.5f);

            a  += b;
            a2 -= b;
            float num = 0.5f * lastFrameData.m_velocity.sqrMagnitude / this.m_info.m_braking;
            float a3  = Vector3.Distance(a, bezier.a);
            float b2  = Vector3.Distance(a2, bezier.a);

            if (Mathf.Min(a3, b2) >= num - 5f)
            {
                if (!instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].CheckSpace(1000f, vehicleID))
                {
                    maxSpeed = 0f;
                    return;
                }
                Vector3  vector = bezier.Position(0.5f);
                Segment3 segment;
                if (Vector3.SqrMagnitude(vehicleData.m_segment.a - vector) < Vector3.SqrMagnitude(bezier.a - vector))
                {
                    segment = new Segment3(vehicleData.m_segment.a, vector);
                }
                else
                {
                    segment = new Segment3(bezier.a, vector);
                }
                if (segment.LengthSqr() >= 3f)
                {
                    segment.a += (segment.b - segment.a).normalized * 2.5f;
                    if (CustomTrainAI.CheckOverlap(vehicleID, ref vehicleData, segment, vehicleID))
                    {
                        maxSpeed = 0f;
                        return;
                    }
                }
                segment = new Segment3(vector, bezier.d);
                if (segment.LengthSqr() >= 1f && CustomTrainAI.CheckOverlap(vehicleID, ref vehicleData, segment, vehicleID))
                {
                    maxSpeed = 0f;
                    return;
                }
                ushort targetNodeId;
                if (offset < position.m_offset)
                {
                    targetNodeId = instance.m_segments.m_buffer[(int)position.m_segment].m_startNode;
                }
                else
                {
                    targetNodeId = instance.m_segments.m_buffer[(int)position.m_segment].m_endNode;
                }
                ushort prevTargetNodeId;
                if (prevOffset == 0)
                {
                    prevTargetNodeId = instance.m_segments.m_buffer[(int)prevPos.m_segment].m_startNode;
                }
                else
                {
                    prevTargetNodeId = instance.m_segments.m_buffer[(int)prevPos.m_segment].m_endNode;
                }
                if (targetNodeId == prevTargetNodeId)
                {
                    float oldMaxSpeed = maxSpeed;
#if DEBUG
                    bool debug = false;                    // targetNodeId == 14527 || targetNodeId == 15048;
                    if (debug)
                    {
                        Log._Debug($"Train {vehicleID} wants to change segment. seg. {prevPos.m_segment} -> node {targetNodeId} -> seg. {position.m_segment}");
                    }
#else
                    bool debug = false;
#endif
                    bool mayChange = CustomVehicleAI.MayChangeSegment(vehicleID, ref vehicleData, ref lastFrameData, false, ref prevPos, prevTargetNodeId, prevLaneID, ref position, targetNodeId, laneID, out maxSpeed, debug);
                    if (!mayChange)
                    {
                        return;
                    }
                    maxSpeed = oldMaxSpeed;
                }
            }
        }
 public override string ToString() => $"{platformLine.Position(0.5f)} (w={width} | {vehicleType} | {subbuildingId} | {laneId} | DIR = {directionPath} ({directionPath.GetAngleXZ()}°))";
        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());
        }
Ejemplo n.º 31
0
 private List<Vector2> BezierToPoints(List<Segment> list)
 {
     var result = new List<Vector2>();
     result.Add(list[0].startPoint);
     foreach (var seg in list)
     {
         if (seg.controlA == Vector2.zero)
         {
             result.Add(seg.endPoint);
         }
         else
         {
             var bezier = new Bezier3(seg.startPoint,seg.controlA,seg.controlB,seg.endPoint);
             var steps = Mathf.RoundToInt((seg.endPoint - seg.startPoint).magnitude / 50) + 1;
             for (var i = 0; i <= steps; i += 1)
             {
                 if (i == 0)
                 {
                     continue;
                 }
                 result.Add(bezier.Position(i / (float)steps));
             }
         }
     }
     return result;
 }
Ejemplo n.º 32
0
        private osmWay AddWay(int i, NetSegment netSegment)
        {
            var nm = Singleton<NetManager>.instance;
            if (netSegment.m_startNode == 0 || netSegment.m_endNode == 0)
            {
                return null;
            }
            var startNode = netSegment.m_startNode;
            var endNode = netSegment.m_endNode;
            var startDirection = netSegment.m_startDirection;
            var endDirection = netSegment.m_endDirection;

            if ((netSegment.m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None)
            {
                startNode = netSegment.m_endNode;
                endNode = netSegment.m_startNode;
                startDirection = netSegment.m_endDirection;
                endDirection = netSegment.m_startDirection;
            }
            osmWayND[] nd;
            if (Vector3.Angle(startDirection, -endDirection) > 3f)
            {
                var start = nm.m_nodes.m_buffer[startNode].m_position;
                var end = nm.m_nodes.m_buffer[endNode].m_position;
                Vector3 a = Vector3.zero;
                Vector3 b = Vector3.zero;
                NetSegment.CalculateMiddlePoints(start, startDirection, end, endDirection, false, false, out a, out b);

                var bezier = new Bezier3(start, a, b, end);

                nd = new osmWayND[5];
                nd[0] = new osmWayND { @ref = startNode };
                nd[1] = new osmWayND { @ref = AddNode(bezier.Position(0.25f)) };
                nd[2] = new osmWayND { @ref = AddNode(bezier.Position(0.5f)) };
                nd[3] = new osmWayND { @ref = AddNode(bezier.Position(0.75f)) };
                nd[4] = new osmWayND { @ref = endNode };
            }
            else
            {
                nd = new osmWayND[2];
                nd[0] = new osmWayND { @ref = startNode };
                nd[1] = new osmWayND { @ref = endNode };
            }

            byte elevation = (byte)(Mathf.Clamp((nm.m_nodes.m_buffer[startNode].m_elevation + nm.m_nodes.m_buffer[endNode].m_elevation) / 2, 0, 255));
            var tags = new List<osmWayTag>();
            if (!mapping.GetTags(elevation, netSegment, tags))
            {
                return null;
            }
            return new osmWay { changeset = 50000000, id = (uint)i, timestamp = DateTime.Now, user = "******", version = 1, nd = nd, tag = tags.ToArray() };
        }
Ejemplo n.º 33
0
        private OSMWay CreateWay(int index, NetSegment segment)
        {
            OSMWay returnWay = null;
            NetSegment.Flags segmentFlags = segment.m_flags;
            NetManager netManager = Singleton<NetManager>.instance;
            List<OSMWayND> wayPaths = new List<OSMWayND>();
            List<OSMWayTag> wayTags;
            ushort startNodeId = segment.m_startNode, endNodeId = segment.m_endNode;

            if(startNodeId != 0 && endNodeId != 0)
            {
                Vector3 startNodeDirection = segment.m_startDirection;
                Vector3 endNodeDirection = segment.m_endDirection;

                if(segmentFlags.IsFlagSet(NetSegment.Flags.Invert))
                {
                    startNodeId = segment.m_endNode;
                    endNodeId = segment.m_startNode;
                    startNodeDirection = segment.m_endDirection;
                    endNodeDirection = segment.m_startDirection;
                }

                NetNode startNode = netManager.m_nodes.m_buffer[startNodeId];
                NetNode endNode = netManager.m_nodes.m_buffer[endNodeId];
                Vector3 startNodePosition = startNode.m_position;
                Vector3 endNodePosition = endNode.m_position;

                wayPaths.Add(new OSMWayND { @ref = startNodeId });

                if (Vector3.Angle(startNodeDirection, -endNodeDirection) > 3f)
                {
                    Vector3 midPointA = Vector3.zero, midPointB = Vector3.zero;
                    NetSegment.CalculateMiddlePoints(startNodePosition, startNodeDirection, endNodePosition, endNodeDirection, false, false, out midPointA, out midPointB);
                    Bezier3 bezier = new Bezier3(startNodePosition, midPointA, midPointB, endNodePosition);

                    osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.25f)));
                    osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.5f)));
                    osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.75f)));

                    wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 3 });
                    wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 2 });
                    wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 1 });
                }

                wayPaths.Add(new OSMWayND { @ref = endNodeId });

                if(Tagger.CreateWayTags(segment, out wayTags))
                {
                    returnWay = new OSMWay { changeset = 50000000, id = (uint)index, timestamp = DateTime.Now, user = "******", nd = wayPaths.ToArray(), tag = wayTags.ToArray(), version = 1 };
                }
                else
                {
                    UniqueLogger.AddLog("Road names missing from search", segment.Info.name, "");
                }
            }

            return returnWay;
        }
Ejemplo n.º 34
0
        private OSMWay CreateWay(int index, NetSegment segment, ushort segmentId)
        {
            OSMWay returnWay = null;
            NetSegment.Flags segmentFlags = segment.m_flags;
            NetManager netManager = Singleton<NetManager>.instance;
            List<OSMWayND> wayPaths = new List<OSMWayND>();
            List<OSMWayTag> wayTags;
            ushort startNodeId = segment.m_startNode, endNodeId = segment.m_endNode;

            if(startNodeId != 0 && endNodeId != 0)
            {
                Vector3 startNodeDirection = segment.m_startDirection;
                Vector3 endNodeDirection = segment.m_endDirection;

                if(segmentFlags.IsFlagSet(NetSegment.Flags.Invert))
                {
                    startNodeId = segment.m_endNode;
                    endNodeId = segment.m_startNode;
                    startNodeDirection = segment.m_endDirection;
                    endNodeDirection = segment.m_startDirection;
                }

                NetNode startNode = netManager.m_nodes.m_buffer[startNodeId];
                NetNode endNode = netManager.m_nodes.m_buffer[endNodeId];
                Vector3 startNodePosition = startNode.m_position;
                Vector3 endNodePosition = endNode.m_position;

                wayPaths.Add(new OSMWayND { @ref = startNodeId });

                if (Vector3.Angle(startNodeDirection, -endNodeDirection) > 3f)
                {
                    Vector3 midPointA = Vector3.zero, midPointB = Vector3.zero;
                    NetSegment.CalculateMiddlePoints(startNodePosition, startNodeDirection, endNodePosition, endNodeDirection, false, false, out midPointA, out midPointB);
                    Bezier3 bezier = new Bezier3(startNodePosition, midPointA, midPointB, endNodePosition);

                    osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.25f)));
                    osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.5f)));
                    osmNodes.Add(CreateNode(unindexedNodeOffset++, bezier.Position(0.75f)));

                    wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 3 });
                    wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 2 });
                    wayPaths.Add(new OSMWayND { @ref = (uint)unindexedNodeOffset - 1 });
                }

                wayPaths.Add(new OSMWayND { @ref = endNodeId });

                if(Tagger.CreateWayTags(segment, out wayTags))
                {
                    if (haveRoadNamerMod)
                    {
                        // If road namer mod is available, then attempt to get the name asscociated with the segment, if any
                        string roadName = RoadNamerManager.Instance().getSegmentName((ushort)(segmentId));
                        if (roadName != null)
                        {
                            //If a name is available, add a name tag
                            wayTags.Add(new OSMWayTag { k = "name", v = StringUtilities.RemoveTags(roadName) });
                        }
                    }
                    returnWay = new OSMWay { changeset = 50000000, id = (uint)index, timestamp = DateTime.Now, user = "******", nd = wayPaths.ToArray(), tag = wayTags.ToArray(), version = 1 };
                }
                else
                {
                    UniqueLogger.AddLog("Road names missing from search", segment.Info.name, "");
                }
            }

            return returnWay;
        }
        private static void CreateZoneBlocksTiny_Curve(NetInfo info, Randomizer randomizer, ref NetSegment segment)
        {
            var minHalfWidth = MIN_HALFWIDTH_TINY_CURVE;

            NetManager instance = Singleton<NetManager>.instance;
            Vector3 startPosition = instance.m_nodes.m_buffer[(int)segment.m_startNode].m_position;
            Vector3 endPosition = instance.m_nodes.m_buffer[(int)segment.m_endNode].m_position;
            Vector3 startDirection = segment.m_startDirection;
            Vector3 endDirection = segment.m_endDirection;
            float num = startDirection.x * endDirection.x + startDirection.z * endDirection.z;
            float num2 = Mathf.Max(minHalfWidth, info.m_halfWidth);
            float num3 = 32f;

            float num4 = VectorUtils.LengthXZ(endPosition - startPosition);
            bool flag2 = startDirection.x * endDirection.z - startDirection.z * endDirection.x > 0f;
            bool flag3 = num < -0.8f || num4 > 50f;
            if (flag2)
            {
                num2 = -num2;
                num3 = -num3;
            }
            Vector3 vector = startPosition - new Vector3(startDirection.z, 0f, -startDirection.x) * num2;
            Vector3 vector2 = endPosition + new Vector3(endDirection.z, 0f, -endDirection.x) * num2;
            Vector3 vector3;
            Vector3 vector4;
            NetSegment.CalculateMiddlePoints(vector, startDirection, vector2, endDirection, true, true, out vector3, out vector4);
            if (flag3)
            {
                float num5 = num * 0.025f + 0.04f;
                float num6 = num * 0.025f + 0.06f;
                if (num < -0.9f)
                {
                    num6 = num5;
                }
                Bezier3 bezier = new Bezier3(vector, vector3, vector4, vector2);
                vector = bezier.Position(num5);
                vector3 = bezier.Position(0.5f - num6);
                vector4 = bezier.Position(0.5f + num6);
                vector2 = bezier.Position(1f - num5);
            }
            else
            {
                Bezier3 bezier2 = new Bezier3(vector, vector3, vector4, vector2);
                vector3 = bezier2.Position(0.86f);
                vector = bezier2.Position(0.14f);
            }
            float num7;
            Vector3 vector5 = VectorUtils.NormalizeXZ(vector3 - vector, out num7);
            int num8 = Mathf.FloorToInt(num7 / 8f + 0.01f);
            float num9 = num7 * 0.5f + (float)(num8 - 8) * ((!flag2) ? -4f : 4f);
            if (num8 != 0)
            {
                float angle = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z);
                Vector3 position3 = vector + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3);
                if (flag2)
                {
                    Singleton<ZoneManager>.instance.CreateBlock(
                        out segment.m_blockStartRight, 
                        ref randomizer, 
                        position3, 
                        angle, 
                        num8, 
                        segment.m_buildIndex);
                }
                else
                {
                    Singleton<ZoneManager>.instance.CreateBlock(
                        out segment.m_blockStartLeft, 
                        ref randomizer, 
                        position3, 
                        angle, 
                        num8, 
                        segment.m_buildIndex);
                }
            }
            if (flag3)
            {
                vector5 = VectorUtils.NormalizeXZ(vector2 - vector4, out num7);
                num8 = Mathf.FloorToInt(num7 / 8f + 0.01f);
                num9 = num7 * 0.5f + (float)(num8 - 8) * ((!flag2) ? -4f : 4f);
                if (num8 != 0)
                {
                    float angle2 = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z);
                    Vector3 position4 = vector4 + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3);
                    if (flag2)
                    {
                        Singleton<ZoneManager>.instance.CreateBlock(
                            out segment.m_blockEndRight, 
                            ref randomizer, 
                            position4, 
                            angle2, 
                            num8, 
                            segment.m_buildIndex + 1u);
                    }
                    else
                    {
                        Singleton<ZoneManager>.instance.CreateBlock(
                            out segment.m_blockEndLeft, 
                            ref randomizer, 
                            position4, 
                            angle2, 
                            num8, 
                            segment.m_buildIndex + 1u);
                    }
                }
            }
            Vector3 vector6 = startPosition + new Vector3(startDirection.z, 0f, -startDirection.x) * num2;
            Vector3 vector7 = endPosition - new Vector3(endDirection.z, 0f, -endDirection.x) * num2;
            Vector3 b;
            Vector3 c;
            NetSegment.CalculateMiddlePoints(vector6, startDirection, vector7, endDirection, true, true, out b, out c);
            Bezier3 bezier3 = new Bezier3(vector6, b, c, vector7);
            Vector3 vector8 = bezier3.Position(0.5f);
            Vector3 vector9 = bezier3.Position(0.25f);
            vector9 = Line2.Offset(VectorUtils.XZ(vector6), VectorUtils.XZ(vector8), VectorUtils.XZ(vector9));
            Vector3 vector10 = bezier3.Position(0.75f);
            vector10 = Line2.Offset(VectorUtils.XZ(vector7), VectorUtils.XZ(vector8), VectorUtils.XZ(vector10));
            Vector3 vector11 = vector6;
            Vector3 a = vector7;
            float d;
            float num10;
            if (Line2.Intersect(VectorUtils.XZ(startPosition), VectorUtils.XZ(vector6), VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), out d, out num10))
            {
                vector6 = startPosition + (vector6 - startPosition) * d;
            }
            if (Line2.Intersect(VectorUtils.XZ(endPosition), VectorUtils.XZ(vector7), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10))
            {
                vector7 = endPosition + (vector7 - endPosition) * d;
            }
            if (Line2.Intersect(VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10))
            {
                vector8 = vector11 - vector9 + (vector8 - vector11) * d;
            }
            float num11;
            Vector3 vector12 = VectorUtils.NormalizeXZ(vector8 - vector6, out num11);
            int num12 = Mathf.FloorToInt(num11 / 8f + 0.01f);
            float num13 = num11 * 0.5f + (float)(num12 - 8) * ((!flag2) ? 4f : -4f);
            if (num12 != 0)
            {
                float angle3 = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z);
                Vector3 position5 = vector6 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3);
                if (flag2)
                {
                    Singleton<ZoneManager>.instance.CreateBlock(
                        out segment.m_blockStartLeft, 
                        ref randomizer, 
                        position5, 
                        angle3, 
                        num12, 
                        segment.m_buildIndex);
                }
                else
                {
                    Singleton<ZoneManager>.instance.CreateBlock(
                        out segment.m_blockStartRight, 
                        ref randomizer, 
                        position5, 
                        angle3, 
                        num12, 
                        segment.m_buildIndex);
                }
            }
            vector12 = VectorUtils.NormalizeXZ(vector7 - vector8, out num11);
            num12 = Mathf.FloorToInt(num11 / 8f + 0.01f);
            num13 = num11 * 0.5f + (float)(num12 - 8) * ((!flag2) ? 4f : -4f);
            if (num12 != 0)
            {
                float angle4 = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z);
                Vector3 position6 = vector8 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3);
                if (flag2)
                {
                    Singleton<ZoneManager>.instance.CreateBlock(
                        out segment.m_blockEndLeft, 
                        ref randomizer, 
                        position6, 
                        angle4, 
                        num12, 
                        segment.m_buildIndex + 1u);
                }
                else
                {
                    Singleton<ZoneManager>.instance.CreateBlock(
                        out segment.m_blockEndRight, 
                        ref randomizer, 
                        position6, 
                        angle4, 
                        num12, 
                        segment.m_buildIndex + 1u);
                }
            }
        }
        private void CreateZoneBlocks(int segment, ref NetSegment data, NetInfo info)
        {
            var instance = Singleton<NetManager>.instance;
            var randomizer = new Randomizer(segment);
            var position = instance.m_nodes.m_buffer[data.m_startNode].m_position;
            var position2 = instance.m_nodes.m_buffer[data.m_endNode].m_position;
            var startDirection = data.m_startDirection;
            var endDirection = data.m_endDirection;
            var num = startDirection.x * endDirection.x + startDirection.z * endDirection.z;
            var flag = !NetSegment.IsStraight(position, startDirection, position2, endDirection);
            var num2 = Mathf.Max(8f, info.m_halfWidth);
            var num3 = 32f;
            if (flag)
            {
                var num4 = VectorUtils.LengthXZ(position2 - position);
                var flag2 = startDirection.x * endDirection.z - startDirection.z * endDirection.x > 0f;
                var flag3 = num < -0.8f || num4 > 50f;
                if (flag2)
                {
                    num2 = -num2;
                    num3 = -num3;
                }
                var vector = position - new Vector3(startDirection.z, 0f, -startDirection.x) * num2;
                var vector2 = position2 + new Vector3(endDirection.z, 0f, -endDirection.x) * num2;
                Vector3 vector3;
                Vector3 vector4;
                NetSegment.CalculateMiddlePoints(vector, startDirection, vector2, endDirection, true, true, out vector3, out vector4);
                if (flag3)
                {
                    var num5 = num * 0.025f + 0.04f;
                    var num6 = num * 0.025f + 0.06f;
                    if (num < -0.9f)
                    {
                        num6 = num5;
                    }
                    var bezier = new Bezier3(vector, vector3, vector4, vector2);
                    vector = bezier.Position(num5);
                    vector3 = bezier.Position(0.5f - num6);
                    vector4 = bezier.Position(0.5f + num6);
                    vector2 = bezier.Position(1f - num5);
                }
                else
                {
                    var bezier2 = new Bezier3(vector, vector3, vector4, vector2);
                    vector3 = bezier2.Position(0.86f);
                    vector = bezier2.Position(0.14f);
                }
                float num7;
                var vector5 = VectorUtils.NormalizeXZ(vector3 - vector, out num7);
                var num8 = Mathf.FloorToInt(num7 / 8f + 0.01f);
                var num9 = num7 * 0.5f + (num8 - 8) * ((!flag2) ? -4f : 4f);
                if (num8 != 0)
                {
                    var angle = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z);
                    var position3 = vector + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3);
                    if (flag2)
                    {
                        Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartRight, ref randomizer, position3, angle, num8, data.m_buildIndex);
                    }
                    else
                    {
                        Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartLeft, ref randomizer, position3, angle, num8, data.m_buildIndex);
                    }
                }
                if (flag3)
                {
                    vector5 = VectorUtils.NormalizeXZ(vector2 - vector4, out num7);
                    num8 = Mathf.FloorToInt(num7 / 8f + 0.01f);
                    num9 = num7 * 0.5f + (num8 - 8) * ((!flag2) ? -4f : 4f);
                    if (num8 != 0)
                    {
                        var angle2 = (!flag2) ? Mathf.Atan2(vector5.x, -vector5.z) : Mathf.Atan2(-vector5.x, vector5.z);
                        var position4 = vector4 + new Vector3(vector5.x * num9 - vector5.z * num3, 0f, vector5.z * num9 + vector5.x * num3);
                        if (flag2)
                        {
                            Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndRight, ref randomizer, position4, angle2, num8, data.m_buildIndex + 1u);
                        }
                        else
                        {
                            Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndLeft, ref randomizer, position4, angle2, num8, data.m_buildIndex + 1u);
                        }
                    }
                }
                var vector6 = position + new Vector3(startDirection.z, 0f, -startDirection.x) * num2;
                var vector7 = position2 - new Vector3(endDirection.z, 0f, -endDirection.x) * num2;
                Vector3 b;
                Vector3 c;
                NetSegment.CalculateMiddlePoints(vector6, startDirection, vector7, endDirection, true, true, out b, out c);
                var bezier3 = new Bezier3(vector6, b, c, vector7);
                var vector8 = bezier3.Position(0.5f);
                var vector9 = bezier3.Position(0.25f);
                vector9 = Line2.Offset(VectorUtils.XZ(vector6), VectorUtils.XZ(vector8), VectorUtils.XZ(vector9));
                var vector10 = bezier3.Position(0.75f);
                vector10 = Line2.Offset(VectorUtils.XZ(vector7), VectorUtils.XZ(vector8), VectorUtils.XZ(vector10));
                var vector11 = vector6;
                var a = vector7;
                float d;
                float num10;
                if (Line2.Intersect(VectorUtils.XZ(position), VectorUtils.XZ(vector6), VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), out d, out num10))
                {
                    vector6 = position + (vector6 - position) * d;
                }
                if (Line2.Intersect(VectorUtils.XZ(position2), VectorUtils.XZ(vector7), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10))
                {
                    vector7 = position2 + (vector7 - position2) * d;
                }
                if (Line2.Intersect(VectorUtils.XZ(vector11 - vector9), VectorUtils.XZ(vector8 - vector9), VectorUtils.XZ(a - vector10), VectorUtils.XZ(vector8 - vector10), out d, out num10))
                {
                    vector8 = vector11 - vector9 + (vector8 - vector11) * d;
                }
                float num11;
                var vector12 = VectorUtils.NormalizeXZ(vector8 - vector6, out num11);
                var num12 = Mathf.FloorToInt(num11 / 8f + 0.01f);
                var num13 = num11 * 0.5f + (num12 - 8) * ((!flag2) ? 4f : -4f);
                if (num12 != 0)
                {
                    var angle3 = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z);
                    var position5 = vector6 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3);
                    if (flag2)
                    {
                        Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartLeft, ref randomizer, position5, angle3, num12, data.m_buildIndex);
                    }
                    else
                    {
                        Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartRight, ref randomizer, position5, angle3, num12, data.m_buildIndex);
                    }
                }
                vector12 = VectorUtils.NormalizeXZ(vector7 - vector8, out num11);
                num12 = Mathf.FloorToInt(num11 / 8f + 0.01f);
                num13 = num11 * 0.5f + (num12 - 8) * ((!flag2) ? 4f : -4f);

                if (num12 == 0) return;

                var angle4 = (!flag2) ? Mathf.Atan2(-vector12.x, vector12.z) : Mathf.Atan2(vector12.x, -vector12.z);
                var position6 = vector8 + new Vector3(vector12.x * num13 + vector12.z * num3, 0f, vector12.z * num13 - vector12.x * num3);
                if (flag2)
                {
                    Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndLeft, ref randomizer, position6, angle4, num12, data.m_buildIndex + 1u);
                }
                else
                {
                    Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndRight, ref randomizer, position6, angle4, num12, data.m_buildIndex + 1u);
                }
            }
            else
            {
                num2 += num3;
                var vector13 = new Vector2(position2.x - position.x, position2.z - position.z);
                var magnitude = vector13.magnitude;
                var num14 = Mathf.FloorToInt(magnitude / 8f + 0.1f);
                var num15 = (num14 <= 8) ? num14 : (num14 + 1 >> 1);
                var num16 = (num14 <= 8) ? 0 : (num14 >> 1);
                if (num15 > 0)
                {
                    var num17 = Mathf.Atan2(startDirection.x, -startDirection.z);
                    var position7 = position + new Vector3(startDirection.x * 32f - startDirection.z * num2, 0f, startDirection.z * 32f + startDirection.x * num2);
                    Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartLeft, ref randomizer, position7, num17, num15, data.m_buildIndex);
                    position7 = position + new Vector3(startDirection.x * (num15 - 4) * 8f + startDirection.z * num2, 0f, startDirection.z * (num15 - 4) * 8f - startDirection.x * num2);
                    Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockStartRight, ref randomizer, position7, num17 + 3.14159274f, num15, data.m_buildIndex);
                }

                if (num16 <= 0) return;

                var num18 = magnitude - num14 * 8f;
                var num19 = Mathf.Atan2(endDirection.x, -endDirection.z);
                var position8 = position2 + new Vector3(endDirection.x * (32f + num18) - endDirection.z * num2, 0f, endDirection.z * (32f + num18) + endDirection.x * num2);
                Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndLeft, ref randomizer, position8, num19, num16, data.m_buildIndex + 1u);
                position8 = position2 + new Vector3(endDirection.x * ((num16 - 4) * 8f + num18) + endDirection.z * num2, 0f, endDirection.z * ((num16 - 4) * 8f + num18) - endDirection.x * num2);
                Singleton<ZoneManager>.instance.CreateBlock(out data.m_blockEndRight, ref randomizer, position8, num19 + 3.14159274f, num16, data.m_buildIndex + 1u);
            }
        }
Ejemplo n.º 37
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);
        }