コード例 #1
0
        private static void InsertEndCapSegments(IReadOnlyDictionary <RoadTopologyEdge, StraightRoadSegment> edgeSegments, RoadTemplateList roadTemplateList)
        {
            foreach (var edge in edgeSegments.Reverse())
            {
                // the end cap flag is only relevant when the edge is not connected to another edge on this end
                bool hasEndCapAtStart = edge.Key.StartType.HasFlag(RoadType.EndCap) && edge.Value.Start.To == null;
                bool hasEndCapAtEnd   = edge.Key.EndType.HasFlag(RoadType.EndCap) && edge.Value.End.To == null;

                // single edges without any connected edges can only have one end cap (at the end position), even when the flag is present at both nodes
                if (hasEndCapAtEnd)
                {
                    EndCapRoadSegment.CreateEndCap(
                        GetIncomingRoadData(edge.Key.End, edge.Key, edgeSegments[edge.Key]),
                        edge.Value.EndPosition,
                        edge.Key.Template,
                        edgeSegments,
                        roadTemplateList);
                }
                else if (hasEndCapAtStart)
                {
                    EndCapRoadSegment.CreateEndCap(
                        GetIncomingRoadData(edge.Key.Start, edge.Key, edgeSegments[edge.Key]),
                        edge.Value.StartPosition,
                        edge.Key.Template,
                        edgeSegments,
                        roadTemplateList);
                }
            }
        }
コード例 #2
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
                EndCapRoadSegment _ => neighborNormal,                           // or end cap, 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);
        }