Esempio n. 1
0
        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));
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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];
        }
Esempio n. 7
0
 protected TerrainAwareRoadSegmentMesher(IRoadSegment segment, RoadTemplate template) : base(segment, template)
 {
 }
Esempio n. 8
0
 public EndCapRoadSegmentMesher(IRoadSegment segment, RoadTemplate template, float joinAngle) :
     base(segment, template)
 {
     _joinAngle = joinAngle;
 }
Esempio n. 9
0
 public CrossingRoadSegmentMesher(IRoadSegment segment, float halfHeight, RoadTemplate template)
     : base(segment, template)
 {
     HalfHeight = halfHeight;
 }
Esempio n. 10
0
 public CurvedRoadSegmentMesher(IRoadSegment segment, RoadTemplate template)
     : base(segment, template)
 {
 }
Esempio n. 11
0
 public SimpleRoadSegmentMesher(IRoadSegment segment, RoadTemplate template)
     : base(segment, template)
 {
 }
Esempio n. 12
0
 public RoadNetwork(RoadTemplate template)
 {
     Template  = template;
     _segments = new List <IRoadSegment>();
 }
Esempio n. 13
0
 public void GenerateMesh(RoadTemplate roadTemplate, HeightMap heightMap, List <RoadShaderResources.RoadVertex> vertices, List <ushort> indices)
 {
 }
Esempio n. 14
0
 public StraightRoadSegmentMesher(IRoadSegment segment, float halfHeight, RoadTemplate template)
     : base(segment, halfHeight, template)
 {
 }
Esempio n. 15
0
        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));
            }
        }