Esempio n. 1
0
        protected override Vector3 ToCorner(RoadSegmentEndPoint neighbor, bool atEnd)
        {
            var neighborNormal    = GetNeighborNormal(neighbor, atEnd);
            var toCornerDirection = neighbor.To switch
            {
                null => DirectionNormalNoZ,                                                      // if I have no neighbor, use my own normal
                StraightRoadSegment _ => Vector3.Normalize(DirectionNormalNoZ + neighborNormal), // if my neighbor is also a straight road segment, meet in the middle
                _ => neighborNormal,                                                             // otherwise use my unflexible neighbor's normal
            };

            // This shouldn't happen but sometimes does in broken maps (Heartland Shield for example).
            if (toCornerDirection.LengthSquared() < 0.1f)
            {
                toCornerDirection = DirectionNormalNoZ;
            }

            // When two road segments meet in an angled curve, their meeting edge is tilted and thus longer than the width of the road
            // -> divide by cosine
            // For straight roads ending in a curve or crossing:
            // -> the angles in the crossing texture may not well match the actual angles of the incoming roads
            //    (especially for X-crossings, since there's only one texture for 4-road crossings which assumes 90° everywhere)
            // -> the meeting edge may become quite tilted and noticeably longer than road width,
            //    while the road shown in the texture of the crossing always has the fixed road width
            // -> to avoid visible breaks between the road segment and the crossing texture, distort the edge so its tilted seam is 'roadwidth' long
            var cosine         = Vector3.Dot(DirectionNormalNoZ, toCornerDirection);
            var toCornerLength = neighbor.To is StraightRoadSegment ? HalfHeight / cosine : HalfHeight;

            return(toCornerDirection * toCornerLength);
        }
Esempio n. 2
0
        protected override Vector3 ToCorner(RoadSegmentEndPoint neighbor, bool atEnd)
        {
            var neighborNormal   = GetNeighborNormal(neighbor, atEnd);
            var segment          = (StraightRoadSegment)Segment;
            var oppositeNeighbor = atEnd ? segment.Start.To : segment.End.To;

            var toCornerDirection = neighbor.To switch
            {
                null when oppositeNeighbor is CrossingRoadSegment crossing =>   // special handling to reproduce (somewhat strange) behavior of the original engine
                OriginalNormal(crossing.Position),
                null =>                                                         // if I have no neighbor, use my own normal
                DirectionNormalNoZ,
                StraightRoadSegment _ =>                                        // if my neighbor is also a straight road segment, meet in the middle
                Vector3.Normalize(DirectionNormalNoZ + neighborNormal),
                _ => neighborNormal,                                            // otherwise use my unflexible neighbor's normal
            };

            Vector3 OriginalNormal(Vector3 crossingPosition)
            {
                var originalDirection = atEnd ?
                                        segment.EndPosition - crossingPosition :
                                        crossingPosition - segment.StartPosition;

                var originalDirectionNoZ = Vector3.Normalize(originalDirection.WithZ(0));

                return(Vector3.Cross(originalDirectionNoZ, Vector3.UnitZ));
            }

            // This shouldn't happen but sometimes does in broken maps (Heartland Shield for example).
            var toCornerLengthSquared = toCornerDirection.LengthSquared();

            if (float.IsNaN(toCornerLengthSquared) || toCornerLengthSquared < 0.1f)
            {
                toCornerDirection = DirectionNormalNoZ;
            }

            // When two road segments meet in an angled curve, their meeting edge is tilted and thus longer than the width of the road
            // -> divide by cosine
            // For straight roads ending in a curve or crossing:
            // -> the angles in the crossing texture may not well match the actual angles of the incoming roads
            //    (especially for X-crossings, since there's only one texture for 4-road crossings which assumes 90° everywhere)
            // -> the meeting edge may become quite tilted and noticeably longer than road width,
            //    while the road shown in the texture of the crossing always has the fixed road width
            // -> to avoid visible breaks between the road segment and the crossing texture, distort the edge so its tilted seam is 'roadwidth' long
            var cosine         = Vector3.Dot(DirectionNormalNoZ, toCornerDirection);
            var toCornerLength = neighbor.To is StraightRoadSegment ? HalfHeight / cosine : HalfHeight;

            return(toCornerDirection * toCornerLength);
        }
Esempio n. 3
0
        private static IncomingRoadData GetIncomingRoadData(RoadTopologyNode node, RoadTopologyEdge incomingEdge, StraightRoadSegment edgeSegment)
        {
            var isStart       = incomingEdge.Start.Position == node.Position;
            var fromPosition  = isStart ? edgeSegment.EndPosition : edgeSegment.StartPosition;
            var segmentVector = (edgeSegment.EndPosition - edgeSegment.StartPosition) * (isStart ? 1 : -1);
            var direction     = segmentVector.LengthSquared() < 0.01f ? Vector3.UnitX : Vector3.Normalize(segmentVector);

            return(new IncomingRoadData(
                       incomingEdge,
                       fromPosition,
                       direction,
                       MathF.Atan2(direction.Y, direction.X)));
        }