Exemplo 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
                CrossingRoadSegment _ => neighborNormal,                         // if my neighbor is an unflexible crossing, use its normal
                _ => Vector3.Normalize(DirectionNormalNoZ + neighborNormal) / 2, // otherwise, meet in the middle
            };

            // 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 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 CrossingRoadSegment ? HalfHeight : HalfHeight / cosine;

            return(toCornerDirection * toCornerLength);
        }
Exemplo n.º 2
0
 public TRoadSegment(Vector3 position, RoadSegmentEndPoint top, RoadSegmentEndPoint right, RoadSegmentEndPoint bottom)
 {
     Position = position;
     Top      = top;
     Right    = right;
     Bottom   = bottom;
 }
Exemplo n.º 3
0
 public XRoadSegment(
     RoadSegmentEndPoint left,
     RoadSegmentEndPoint top,
     RoadSegmentEndPoint right,
     RoadSegmentEndPoint bottom)
 {
     Left   = left;
     Top    = top;
     Right  = right;
     Bottom = bottom;
 }
Exemplo n.º 4
0
        protected override Vector3 ToCorner(RoadSegmentEndPoint neighbor, bool atEnd)
        {
            var curve = Segment as CurvedRoadSegment;

            if (atEnd)
            {
                return(0.5f * (curve.TopRight - curve.BottomRight));
            }
            else
            {
                return(0.5f * (curve.TopLeft - curve.BottomLeft));
            }
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Generate vector from the start/end position of an edge to the corner of the mesh's base geometry
        /// </summary>
        /// <param name="neighbor"></param>
        /// <param name="atEnd"></param>
        /// <returns></returns>
        private Vector3 ToCorner(RoadSegmentEndPoint neighbor, bool atEnd)
        {
            var neighborDirection = (atEnd ? -1 : 1) * neighbor?.IncomingDirection ?? Vector3.Zero;
            var neighborNormal    = Vector3.Cross(Vector3.Normalize(neighborDirection.WithZ(0)), Vector3.UnitZ);
            var toCornerDirection = neighbor.To switch
            {
                null => DirectionNormalNoZ,                          // if I have no neighbor, use my own normal
                CrossingRoadSegment _ => neighborNormal,             // if my neighbor is an unflexible crossing, use its normal
                _ => (DirectionNormalNoZ + neighborNormal) / 2,      // otherwise, meet in the middle
            };

            // 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 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 CrossingRoadSegment ? HalfHeight : HalfHeight / cosine;

            return(toCornerDirection * toCornerLength);
        }
Exemplo n.º 7
0
 /// <summary>
 /// Generate vector from the start/end position of an edge to the corner of the mesh's base geometry
 /// </summary>
 /// <param name="neighbor"></param>
 /// <param name="atEnd"></param>
 /// <returns></returns>
 protected abstract Vector3 ToCorner(RoadSegmentEndPoint neighbor, bool atEnd);
Exemplo n.º 8
0
        //helper method used by crossings and curves
        protected Vector3 GetNeighborNormal(RoadSegmentEndPoint neighbor, bool atEnd)
        {
            var neighborDirection = (atEnd ? -1 : 1) * neighbor?.IncomingDirection ?? Vector3.Zero;

            return(Vector3.Cross(Vector3.Normalize(neighborDirection.WithZ(0)), Vector3.UnitZ));
        }
Exemplo n.º 9
0
 public IncomingRoadData(
     RoadTopologyEdge topologyEdge,
     RoadSegmentEndPoint targetEndPoint,
     in Vector3 outDirection,