public void AddSegment(RoadTemplate template, MapObject start, MapObject end) { // ignore duplicate segments (e.g. in Alpine Assault) if (Edges.Any(e => (e.Start.Position == start.Position && e.End.Position == end.Position) || (e.End.Position == start.Position && e.Start.Position == end.Position))) { return; } var startNode = GetOrCreateNode(start.Position); var endNode = GetOrCreateNode(end.Position); if (endNode == startNode) { // create a new dummy node, otherwise this edge gets counted twice as incoming edge of startNode // add a small offset to make sure that other map objects use the 'normal' node endNode = GetOrCreateNode(end.Position + 0.001f * Vector3.UnitX); } var edge = new RoadTopologyEdge( template, startNode, start.RoadType, endNode, end.RoadType, Edges.Count); Edges.Add(edge); startNode.Edges.Add(edge); endNode.Edges.Add(edge); }
private static SizeF GetSize(RoadTextureType type, RoadTemplate template) { var stubLength = 0.5f * (1f - template.RoadWidthInTexture); float width, height; switch (type) { case RoadTextureType.TCrossing: width = template.RoadWidthInTexture + stubLength + OverlapLength; height = template.RoadWidthInTexture + 2 * stubLength + 2 * OverlapLength; break; case RoadTextureType.XCrossing: width = template.RoadWidthInTexture + 2 * stubLength + 2 * OverlapLength; height = width; break; case RoadTextureType.AsymmetricYCrossing: width = 1.2f + template.RoadWidthInTexture / 2f; height = 1.33f + OverlapLength; break; case RoadTextureType.SymmetricYCrossing: width = 1.59f; height = 1.065f + OverlapLength; break; default: throw new ArgumentOutOfRangeException("Unknown RoadTextureType: " + type); } return(new SizeF(width * template.RoadWidth, height * template.RoadWidth)); }
public static void CreateCrossing( IEnumerable <IncomingRoadData> roads, Vector3 crossingPosition, RoadTemplate template, IReadOnlyDictionary <RoadTopologyEdge, StraightRoadSegment> edgeSegments) { var type = ChooseCrossingType(roads); switch (type) { case RoadTextureType.TCrossing: CreateTCrossing(roads, crossingPosition, template, edgeSegments); break; case RoadTextureType.XCrossing: CreateXCrossing(roads, crossingPosition, template, edgeSegments); break; case RoadTextureType.AsymmetricYCrossing: CreateYAsymmCrossing(roads, crossingPosition, template, edgeSegments); break; case RoadTextureType.SymmetricYCrossing: CreateYSymmCrossing(roads, crossingPosition, template, edgeSegments); break; default: throw new ArgumentException("Failed to choose crossing type", nameof(roads)); } }
public RoadSegmentMesher CreateMesher(RoadTemplate template) { var targetSize = GetSize(Type, template); var halfHeight = targetSize.Height / 2; return(new CrossingRoadSegmentMesher(this, halfHeight, template)); }
public void AddSegment(RoadTemplate template, MapObject start, MapObject end) { var startNode = GetOrCreateNode(start.Position); var endNode = GetOrCreateNode(end.Position); if (endNode == startNode) { // create a new dummy node, otherwise this edge gets counted twice as incoming edge of startNode // add a small offset to make sure that other map objects use the 'normal' node endNode = GetOrCreateNode(end.Position + 0.001f * Vector3.UnitX); } var edge = new RoadTopologyEdge( template, startNode, start.RoadType, endNode, end.RoadType, Edges.Count); Edges.Add(edge); startNode.Edges.Add(edge); endNode.Edges.Add(edge); }
protected RoadSegmentMesher(IRoadSegment segment, RoadTemplate template) { Segment = segment; Template = template; var startNoZ = Segment.StartPosition.WithZ(0); var endNoZ = Segment.EndPosition.WithZ(0); DirectionNoZ = Vector3.Normalize(endNoZ - startNoZ); DirectionNormalNoZ = Vector3.Cross(DirectionNoZ, Vector3.UnitZ); TextureBounds = TextureAtlas.ForRoadWidth(Template.RoadWidthInTexture)[Segment.Type]; }
protected TerrainAwareRoadSegmentMesher(IRoadSegment segment, RoadTemplate template) : base(segment, template) { }
public EndCapRoadSegmentMesher(IRoadSegment segment, RoadTemplate template, float joinAngle) : base(segment, template) { _joinAngle = joinAngle; }
public CrossingRoadSegmentMesher(IRoadSegment segment, float halfHeight, RoadTemplate template) : base(segment, template) { HalfHeight = halfHeight; }
public CurvedRoadSegmentMesher(IRoadSegment segment, RoadTemplate template) : base(segment, template) { }
public SimpleRoadSegmentMesher(IRoadSegment segment, RoadTemplate template) : base(segment, template) { }
public RoadNetwork(RoadTemplate template) { Template = template; _segments = new List <IRoadSegment>(); }
public void GenerateMesh(RoadTemplate roadTemplate, HeightMap heightMap, List <RoadShaderResources.RoadVertex> vertices, List <ushort> indices) { }
public StraightRoadSegmentMesher(IRoadSegment segment, float halfHeight, RoadTemplate template) : base(segment, halfHeight, template) { }
public void GenerateMesh(RoadTemplate template, HeightMap heightMap, List <RoadShaderResources.RoadVertex> vertices, List <ushort> indices) { const float heightBias = 1f; const float createNewVerticesHeightDeltaThreshold = 0.002f; var rightToPosition = Position - Right.Position; var startPosition = Position + rightToPosition; startPosition.Z = heightMap.GetHeight(startPosition.X, startPosition.Y); var endPosition = new Vector3( Right.Position.X, Right.Position.Y, heightMap.GetHeight(Right.Position.X, Right.Position.Y)); var distance = Vector3.Distance(startPosition, endPosition); var direction = Vector3.Normalize(rightToPosition); var centerToEdgeDirection = Vector3.Cross(Vector3.UnitZ, direction); var up = Vector3.Cross(direction, centerToEdgeDirection); var halfWidth = template.RoadWidth / 2; var initialVertexCount = vertices.Count; void AddVertexPair(in Vector3 position, float distanceAlongRoad) { var u = MathUtility.Lerp(0.71f, 0.96f, distanceAlongRoad / template.RoadWidth); var p0 = position - centerToEdgeDirection * halfWidth; p0.Z += heightBias; vertices.Add(new RoadShaderResources.RoadVertex { Position = p0, Normal = up, UV = new Vector2(u, 0.37f) }); var p1 = position + centerToEdgeDirection * halfWidth; p1.Z += heightBias; vertices.Add(new RoadShaderResources.RoadVertex { Position = p1, Normal = up, UV = new Vector2(u, 0.62f) }); } AddVertexPair(startPosition, 0); var previousPoint = startPosition; var previousPointDistance = 0; for (var currentDistance = 10; currentDistance < distance; currentDistance += 10) { var position = startPosition + direction * currentDistance; var actualHeight = heightMap.GetHeight(position.X, position.Y); var interpolatedHeight = MathUtility.Lerp(previousPoint.Z, endPosition.Z, (currentDistance - previousPointDistance) / distance); if (Math.Abs(actualHeight - interpolatedHeight) > createNewVerticesHeightDeltaThreshold) { AddVertexPair(position, currentDistance); previousPoint = position; previousPointDistance = currentDistance; } } // Add last chunk. AddVertexPair(endPosition, distance); for (var i = initialVertexCount; i < vertices.Count - 2; i += 2) { indices.Add((ushort)(i + 0)); indices.Add((ushort)(i + 1)); indices.Add((ushort)(i + 2)); indices.Add((ushort)(i + 1)); indices.Add((ushort)(i + 2)); indices.Add((ushort)(i + 3)); } }