コード例 #1
0
ファイル: Tile.cs プロジェクト: twpol/msts-tools
        public void DrawLayer(TileRenderLayer layer, Graphics graphics, float x, float y, float w, float h)
        {
            switch (layer)
            {
            //case TileRenderLayer.Tiles:
            //    graphics.DrawRectangle(Pens.Black, x, y, w, h);
            //    break;
            case TileRenderLayer.Terrain:
                graphics.DrawImage(RenderTerrain(w), x, y, w, h);
                //graphics.DrawRectangle(Pens.Black, x, y, w, h);
                break;

            case TileRenderLayer.Track:
                foreach (TileTrackShape trackSection in Tile.Objects.Where(o => o is TileTrackShape))
                {
                    //graphics.FillRectangle(Brushes.Black, x + w * (float)((1024 + obj.X) / 2048), y + h * (float)((1024 - obj.Z) / 2048), 1, 1);
                    var trackShape = TrackService.TrackShapes[trackSection.TrackShape];

                    var needPoints = trackShape.MainRoute > -1;
                    foreach (var path in trackShape.Paths)
                    {
                        // Rotation matrix for quaternion (a, b, c, d).
                        //   [a^2+b^2-c^2-d^2  2bc-2ad          2bd+2ac        ]
                        //   [2bc+2ad          a^2-b^2+c^2-d^2  2cd-2ab        ]
                        //   [2bd-2ac          2cd+2ab          a^2-b^2-c^2+d^2]
                        var rxx = trackSection.DX * trackSection.DX + trackSection.DY * trackSection.DY - trackSection.DZ * trackSection.DZ - trackSection.DW * trackSection.DW;
                        var rxz = 2 * trackSection.DY * trackSection.DW - 2 * trackSection.DX * trackSection.DZ;
                        var rzx = 2 * trackSection.DY * trackSection.DW + 2 * trackSection.DX * trackSection.DZ;
                        var rzz = trackSection.DX * trackSection.DX - trackSection.DY * trackSection.DY - trackSection.DZ * trackSection.DZ + trackSection.DW * trackSection.DW;
                        {
                            // [ C  0  S] [xx yx zx] [ xxC+xzS  yxC+yzS  zxC+zzS]
                            // [ 0  1  0].[xy yy zy]=[ xy       yy       zy     ]
                            // [-S  0  C] [xz yz zz] [-xxS+xzC -yxS+yzC -zxS+zzC]
                            var angle = path.Rotation * Math.PI / 180;
                            var rxx2  = rxx * Math.Cos(angle) + rxz * Math.Sin(angle);
                            var rxz2  = rxz * Math.Cos(angle) - rxx * Math.Sin(angle);
                            var rzx2  = rzx * Math.Cos(angle) + rzz * Math.Sin(angle);
                            var rzz2  = rzz * Math.Cos(angle) - rzx * Math.Sin(angle);
                            rxx = rxx2; rxz = rxz2; rzx = rzx2; rzz = rzz2;
                        }

                        var startX = trackSection.X - rxx * path.X - rzx * path.Z;
                        var startZ = trackSection.Z - rxz * path.X - rzz * path.Z;

                        if (needPoints)
                        {
                            graphics.FillEllipse(Brushes.Black,
                                                 (float)(x + w * (1024 + startX) / 2048) - 3,
                                                 (float)(y + h * (1024 - startZ) / 2048) - 3,
                                                 6,
                                                 6);
                            needPoints = false;
                        }

                        foreach (var section in path.Sections)
                        {
                            if (section.IsCurve)
                            {
                                var angle = section.Angle * Math.PI / 180;
                                // Rotate 90 degrees left or right base ioon +ve or -ve angle (-ve angle = left).
                                var curveCenterX = startX - rxx * section.Radius * Math.Sign(section.Angle);
                                var curveCenterZ = startZ - rxz * section.Radius * Math.Sign(section.Angle);
                                // Rotate the center->start vector by the curve's angle.
                                var curveEndX = curveCenterX + (startX - curveCenterX) * Math.Cos(-angle) - (startZ - curveCenterZ) * Math.Sin(-angle);
                                var curveEndZ = curveCenterZ + (startX - curveCenterX) * Math.Sin(-angle) + (startZ - curveCenterZ) * Math.Cos(-angle);
                                // Work out the display angle.
                                var angleStart = (float)(Math.Asin((curveCenterX - startX) / section.Radius) * 180 / Math.PI);

                                graphics.DrawArc(trackShape.IsRoadShape ? Pens.Gray : Pens.Black,
                                                 (float)(x + w * (1024 + curveCenterX - section.Radius) / 2048),
                                                 (float)(y + h * (1024 - curveCenterZ - section.Radius) / 2048),
                                                 (float)(w * section.Radius / 1024),
                                                 (float)(h * section.Radius / 1024),
                                                 (startZ < curveCenterZ ? 90 + angleStart : 270 - angleStart),
                                                 (float)section.Angle);

                                // [ C  0  S] [xx yx zx] [ xxC+xzS  yxC+yzS  zxC+zzS]
                                // [ 0  1  0].[xy yy zy]=[ xy       yy       zy     ]
                                // [-S  0  C] [xz yz zz] [-xxS+xzC -yxS+yzC -zxS+zzC]
                                var rxx2 = rxx * Math.Cos(angle) + rxz * Math.Sin(angle);
                                var rxz2 = rxz * Math.Cos(angle) - rxx * Math.Sin(angle);
                                var rzx2 = rzx * Math.Cos(angle) + rzz * Math.Sin(angle);
                                var rzz2 = rzz * Math.Cos(angle) - rzx * Math.Sin(angle);
                                rxx    = rxx2; rxz = rxz2; rzx = rzx2; rzz = rzz2;
                                startX = curveEndX;
                                startZ = curveEndZ;
                            }
                            else
                            {
                                var straightEndX = startX - rzx * section.Length;
                                var straightEndZ = startZ - rzz * section.Length;

                                graphics.DrawLine(trackShape.IsRoadShape ? Pens.Gray : Pens.Black,
                                                  (float)(x + w * (1024 + startX) / 2048),
                                                  (float)(y + h * (1024 - startZ) / 2048),
                                                  (float)(x + w * (1024 + straightEndX) / 2048),
                                                  (float)(y + h * (1024 - straightEndZ) / 2048));

                                startX = straightEndX;
                                startZ = straightEndZ;
                            }
                        }
                    }
                }
                break;

            case TileRenderLayer.Markers:
                foreach (TileObject obj in Tile.Objects.Where(o => !(o is TileTrackShape) && !(o is TilePlatform) && !(o is TileSiding) && !(o is TileSignal)))
                {
                    graphics.FillRectangle(Brushes.Yellow, x + w * (float)((1024 + obj.X) / 2048), y + h * (float)((1024 - obj.Z) / 2048), 1, 1);
                    var labeledObj = obj as TileLabeledObject;
                    if (labeledObj != null)
                    {
                        graphics.DrawString(labeledObj.Label, SystemFonts.MessageBoxFont, Brushes.Yellow, x + w * (float)((1024 + obj.X) / 2048), y + h * (float)((1024 - obj.Z) / 2048));
                    }
                }
                break;

            case TileRenderLayer.Platforms:
                foreach (TilePlatform platform in Tile.Objects.Where(o => o is TilePlatform))
                {
                    var mx = (float)(x + w * (1024 + platform.X) / 2048);
                    var my = (float)(y + h * (1024 - platform.Z) / 2048);
                    graphics.FillPolygon(Brushes.DarkBlue, new PointF[] { new PointF(mx + 6, my - 8), new PointF(mx + 8, my - 6), new PointF(mx - 6, my + 8), new PointF(mx - 8, my + 6) });
                    graphics.DrawLine(Pens.Blue, mx - 8, my + 6, mx + 6, my - 8);
                }
                break;

            case TileRenderLayer.PlatformNames:
                foreach (TilePlatform platform in Tile.Objects.Where(o => o is TilePlatform))
                {
                    graphics.DrawString(platform.Label, SystemFonts.MessageBoxFont, Brushes.Blue, x + w * (float)((1024 + platform.X) / 2048), y + h * (float)((1024 - platform.Z) / 2048));
                }
                break;

            case TileRenderLayer.Sidings:
                foreach (TileSiding siding in Tile.Objects.Where(o => o is TileSiding))
                {
                    var mx = (float)(x + w * (1024 + siding.X) / 2048);
                    var my = (float)(y + h * (1024 - siding.Z) / 2048);
                    graphics.FillPolygon(Brushes.DarkGreen, new PointF[] { new PointF(mx + 6, my - 8), new PointF(mx + 8, my - 6), new PointF(mx - 6, my + 8), new PointF(mx - 8, my + 6) });
                    graphics.DrawLine(Pens.Green, mx - 8, my + 6, mx + 6, my - 8);
                }
                break;

            case TileRenderLayer.SidingNames:
                foreach (TileSiding siding in Tile.Objects.Where(o => o is TileSiding))
                {
                    graphics.DrawString(siding.Label, SystemFonts.MessageBoxFont, Brushes.Green, x + w * (float)((1024 + siding.X) / 2048), y + h * (float)((1024 - siding.Z) / 2048));
                }
                break;

            case TileRenderLayer.Signals:
                foreach (TileSignal signal in Tile.Objects.Where(o => o is TileSignal))
                {
                    var mx = (float)(x + w * (1024 + signal.X) / 2048);
                    var my = (float)(y + h * (1024 - signal.Z) / 2048);
                    graphics.FillEllipse(Brushes.DarkRed, mx - 3, my - 3, 6, 6);
                }
                break;

            case TileRenderLayer.Mileposts:
                break;

            case TileRenderLayer.FuelPoints:
                break;
            }
        }
コード例 #2
0
ファイル: Tile.cs プロジェクト: twpol/msts-tools
        //public void PrepareLayer(TileLayer layer) {
        //    switch (layer) {
        //        case TileLayer.Tiles:
        //            break;
        //        case TileLayer.Terrain:
        //            string tileElevation = String.Format(CultureInfo.InvariantCulture, @"{0}\Tiles\{1}_y.raw", _route.RoutePath, _tileName);
        //            string tileShadow = String.Format(CultureInfo.InvariantCulture, @"{0}\Tiles\{1}_n.raw", _route.RoutePath, _tileName);
        //            string tileUnknown = String.Format(CultureInfo.InvariantCulture, @"{0}\Tiles\{1}_e.raw", _route.RoutePath, _tileName);
        //            string tileFile = String.Format(CultureInfo.InvariantCulture, @"{0}\Tiles\{1}.t", _route.RoutePath, _tileName);

        //            var image = new Bitmap(256, 256);
        //            using (var g = Graphics.FromImage(image)) {
        //                var terrainWidth = 256;
        //                var terrainHeight = 256;
        //                var terrainFloor = 0f;
        //                var terrainScale = 1f;
        //                try {
        //                    var tile = new UndoRedoSimisFile(tileFile, _simisProvider);
        //                    tile.Read();
        //                    terrainWidth = terrainHeight = (int)tile.Tree["terrain"]["terrain_samples"]["terrain_nsamples"][0].ToValue<uint>();
        //                    Debug.Assert(terrainWidth == 256);
        //                    Debug.Assert(terrainHeight == 256);
        //                    if (tile.Tree["terrain"]["terrain_samples"].Contains("terrain_sample_rotation")) {
        //                        Debug.Assert(tile.Tree["terrain"]["terrain_samples"]["terrain_sample_rotation"][0].ToValue<float>() == 0);
        //                    }
        //                    terrainFloor = tile.Tree["terrain"]["terrain_samples"]["terrain_sample_floor"][0].ToValue<float>();
        //                    terrainScale = tile.Tree["terrain"]["terrain_samples"]["terrain_sample_scale"][0].ToValue<float>();
        //                    var terrain_sample_size = tile.Tree["terrain"]["terrain_samples"]["terrain_sample_size"][0].ToValue<float>();
        //                    Debug.Assert(terrain_sample_size == 8 || terrain_sample_size == 16 || terrain_sample_size == 32);
        //                } catch (Exception e) {
        //                    g.DrawString(e.ToString(), SystemFonts.CaptionFont, Brushes.Black, 0, 0);
        //                    _terrainImage = image;
        //                    return;
        //                }

        //                var terrainData = new uint[terrainWidth * terrainHeight];
        //                using (var streamElevation = new FileStream(tileElevation, FileMode.Open, FileAccess.Read)) {
        //                    var readerElevation = new BinaryReader(streamElevation);
        //                    try {
        //                        for (var i = 0; i < terrainWidth * terrainHeight; i++) {
        //                            var value = (int)(1024 + 32 + (terrainFloor + (double)readerElevation.ReadUInt16() * terrainScale) / 4) % 512;
        //                            terrainData[i] = (uint)(value < 256 ? value * 0x00000100 : (value - 256) * 0x00010001 + 0x0000FF00);
        //                        }
        //                    } catch (EndOfStreamException) {
        //                    }
        //                }
        //                unsafe {
        //                    fixed (uint* ptr = terrainData) {
        //                        var terrainImage = new Bitmap(terrainWidth, terrainHeight, 4 * terrainWidth, PixelFormat.Format32bppRgb, new IntPtr(ptr));
        //                        g.DrawImage(terrainImage, 0, 0, image.Width, image.Height);
        //                    }
        //                }

        //                //g.DrawString(TileName, SystemFonts.CaptionFont, Brushes.White, 0, image.Height - 4 * 15);
        //                //g.DrawString(TileCoordinate.ToString(), SystemFonts.CaptionFont, Brushes.White, 0, image.Height - 3 * 15);
        //                //g.DrawString(Coordinates.ConvertToIgh(TileCoordinate, 0, 1).ToString(), SystemFonts.CaptionFont, Brushes.White, 0, image.Height - 2 * 15);
        //                //g.DrawString(Coordinates.ConvertToLatLon(Coordinates.ConvertToIgh(TileCoordinate, 0, 1)).ToString(), SystemFonts.CaptionFont, Brushes.White, 0, image.Height - 1 * 15);
        //            }

        //            _terrainImage = image;
        //            break;
        //        case TileLayer.Roads:
        //            // TODO: Roads and track use the same basic data, can we split anything out here?
        //            break;
        //        case TileLayer.Track:
        //            //foreach (var trackVectors in Route.Track.TrackVectors.Values) {
        //            //    if (trackVectors.Vectors.Any(v => v.TileX == TileCoordinate.X && v.TileZ == TileCoordinate.Z)) {
        //            //        var sections = new List<TileObject>(from vector in trackVectors.Vectors.Union(new RouteTrackVector[] { Route.Track.TrackNodes[trackVectors.PinEnd] })
        //            //                                                select new TileObject() { X = vector.X + 2048 * (vector.TileX - TileCoordinate.X), Y = vector.Y, Z = vector.Z + 2048 * (vector.TileZ - TileCoordinate.Z) });
        //            //        TrackNodes.Add(new TileTrackNode() {
        //            //            ID = trackVectors.ID, IsRoad = false, Label = "", Vectors = sections,
        //            //            X = sections[0].X, Y = sections[0].Y, Z = sections[0].Z
        //            //        });
        //            //    }
        //            //}
        //            break;
        //    }
        //}

        public void DrawLayer(TileRenderLayer layer, Graphics graphics, float x, float y, float w, float h)
        {
            //    switch (layer) {
            //        case TileLayer.Tiles:
            //            graphics.DrawRectangle(Pens.LightGray, x, y, w, h);
            //            break;
            //        case TileLayer.Terrain:
            //            if (_terrainImage != null) {
            //                graphics.DrawImage(_terrainImage, x, y, w, h);
            //            }
            //            break;
            //        case TileLayer.Roads:
            //        case TileLayer.Track:
            //            foreach (var trackNode in _trackNodes) {
            //                if (layer != (trackNode.IsRoad ? TileLayer.Roads : TileLayer.Track)) {
            //                    continue;
            //                }
            //                var brush = trackNode.IsRoad ? Brushes.Gray : Brushes.Black;
            //                //var col = (int)(64 * (trackNode.ID % 4));
            //                //var brush = new SolidBrush(Color.FromArgb(col, col, col));
            //                var pen = new Pen(brush);

            //                if (!String.IsNullOrEmpty(trackNode.Label)) {
            //                    graphics.DrawString(trackNode.Label, SystemFonts.CaptionFont, brush,
            //                        (int)(x + w * (0 + (trackNode.X + 1024) / 2048)),
            //                        (int)(y + h * (1 - (trackNode.Z + 1024) / 2048)));
            //                }
            //                TileObject previousLocation = trackNode;
            //                //graphics.FillEllipse(brush,
            //                //    (float)(x + w * (1024 + trackNode.X) / 2048) - 1,
            //                //    (float)(y + h * (1024 - trackNode.Z) / 2048) - 1,
            //                //    2,
            //                //    2);

            //                foreach (var section in trackNode.Vectors) {
            //                    graphics.DrawLine(pen,
            //                        (float)(x + w * (1024 + previousLocation.X) / 2048),
            //                        (float)(y + h * (1024 - previousLocation.Z) / 2048),
            //                        (float)(x + w * (1024 + section.X) / 2048),
            //                        (float)(y + h * (1024 - section.Z) / 2048));
            //                    //graphics.FillEllipse(brush,
            //                    //    (float)(x + w * (1024 + section.X) / 2048) - 1,
            //                    //    (float)(y + h * (1024 - section.Z) / 2048) - 1,
            //                    //    2,
            //                    //    2);

            //                    previousLocation = section;
            //                }
            //            }
            //            //foreach (var trackSection in TrackSections) {
            //            //    if (!String.IsNullOrEmpty(trackSection.Label)) {
            //            //        graphics.DrawString(trackSection.Label, SystemFonts.CaptionFont, Brushes.Black,
            //            //            (int)(x + w * (0 + (trackSection.X + 1024) / 2048)),
            //            //            (int)(y + h * (1 - (trackSection.Z + 1024) / 2048)));
            //            //    }
            //            //    if (trackSection.Track == null) {
            //            //        continue;
            //            //    }
            //            //    if (layer != (trackSection.Track.IsRoadShape ? TileLayer.Roads : TileLayer.Track)) {
            //            //        continue;
            //            //    }


            //            //}
            //            break;
            //        case TileLayer.Markers:
            //            foreach (var marker in _markers) {
            //                var mx = (int)(x + w * marker.X);
            //                var my = (int)(y + h * marker.Z);
            //                var fm = graphics.MeasureString(marker.Label, SystemFonts.CaptionFont);
            //                graphics.FillEllipse(Brushes.DarkBlue, mx - 2, my - 2, 4, 4);
            //                graphics.DrawLine(Pens.DarkBlue, mx, my, mx, my - 4 * fm.Height);
            //                graphics.FillRectangle(Brushes.DarkBlue, mx - fm.Width / 2, my - 5 * fm.Height, fm.Width - 1, fm.Height - 1);
            //                graphics.DrawString(marker.Label, SystemFonts.CaptionFont, Brushes.White, mx - fm.Width / 2, my - 5 * fm.Height);
            //            }
            //            break;
            //        case TileLayer.PlatformNames:
            //            break;
            //        case TileLayer.SidingNames:
            //            break;
            //        case TileLayer.Mileposts:
            //            break;
            //        case TileLayer.FuelPoints:
            //            break;
            //    }
        }