Fixed unity terrain generation bug.

This commit is contained in:
2015-03-19 12:34:58 +02:00
parent 8f9f935796
commit 68140b11a7
40 changed files with 326 additions and 245 deletions

View File

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using TransportGame.MapViewer.Model;
namespace TransportGame.MapViewer.Business
{
public static class BitmapExtensions
{
/// <summary>
/// Gets a wpf bitmap source from a bitmap.
/// </summary>
/// <param name="this">The bitmap</param>
/// <returns>The bitmap source</returns>
public static BitmapSource ToBitmapSource(this Bitmap24 @this)
{
return BitmapSource.Create(@this.Width, @this.Height,
96, 96, PixelFormats.Rgb24, null, @this.Raw, @this.Width * 3);
}
}
}

View File

@ -1,11 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using TransportGame.MapViewer.Model;
using TransportGame.Model;
namespace TransportGame.MapViewer
@ -23,8 +18,8 @@ namespace TransportGame.MapViewer
/// <summary>
/// Gets or sets the scale
/// </summary>
private int _scale;
public int Scale
private float _scale;
public float Scale
{
get
{
@ -45,7 +40,7 @@ namespace TransportGame.MapViewer
public MapRenderer()
{
Scale = 4;
Scale = 1;
}
///<summary>
@ -54,72 +49,46 @@ namespace TransportGame.MapViewer
///<param name="file"></param>
///<param name="map"></param>
///<param name="layers"></param>
public Color[,] Render(Map map, Layers layers = Layers.All)
public Bitmap24 Render(Map map, Layers layers = Layers.All)
{
lock (this)
{
// Create texture on which to draw
Color[,] pixels = new Color[map.Width * Scale, map.Height * Scale];
Bitmap24 bitmap = new Bitmap24(Convert.ToInt32(map.Width * Scale), Convert.ToInt32(map.Height * Scale));
// First layer - cells
DrawCells(pixels, map, (layers & Layers.Elevation) > 0);
DrawCells(bitmap, map, (layers & Layers.Elevation) > 0);
// Done
return pixels;
return bitmap;
}
}
private void DrawCells(Color[,] pixels, Map map, bool elevation)
private void DrawCells(Bitmap24 bitmap, Map map, bool elevation)
{
for (int x = 0; x < pixels.GetLength(0); x++)
for (int y = 0; y < pixels.GetLength(1); y++)
for (int x = 0; x < bitmap.Width; x++)
for (int y = 0; y < bitmap.Height; y++)
{
int mapX = x / Scale;
int mapY = y / Scale;
int mapX = Convert.ToInt32(x / Scale);
int mapY = Convert.ToInt32(y / Scale);
// Draw water
if (map.IsWater(mapX, mapY))
pixels[x, y] = WaterColor;
bitmap[x, y] = WaterColor;
// Draw elevation
else if (elevation)
{
float alpha = (map[mapX, mapY] - map.Biome.HeightRange.Minimum) / (map.Biome.HeightRange.Maximum - map.Biome.HeightRange.Minimum);
pixels[x, y] = Color.Multiply(ElevationTerrainColor, alpha);
float alpha = map[mapX, mapY]; // map height range is [0,1]
bitmap[x, y] = Color.Multiply(ElevationTerrainColor, alpha);
}
// Draw terrain
else
{
pixels[x, y] = TerrainColor;
bitmap[x, y] = TerrainColor;
}
}
}
public async Task<BitmapSource> RenderToImageSource(Map map, Layers layers = Layers.All)
{
var colors = await Task.Run(() => Render(map, layers));
colors[0, 0] = Colors.Red;
colors[colors.GetLength(0) - 1, 0] = Colors.Red;
// Convert to raw pixels
byte[] raw = new byte[colors.GetLength(0) * colors.GetLength(1) * 3];
for (int x = 0; x < colors.GetLength(0); x++)
for (int y = 0; y < colors.GetLength(1); y++)
{
int pixelIndex = x + y * colors.GetLength(0);
raw[3 * pixelIndex] = colors[x, y].R;
raw[3 * pixelIndex + 1] = colors[x, y].G;
raw[3 * pixelIndex + 2] = colors[x, y].B;
}
// Create bitmap source
BitmapSource bmp = BitmapSource.Create(colors.GetLength(0), colors.GetLength(1),
96, 96, PixelFormats.Rgb24, null, raw, colors.GetLength(0) * 3);
return bmp;
}
}
}

View File

@ -21,6 +21,7 @@
<Button Name="buttonSave" ToolTip="Saves as image" Click="buttonSave_Click">
<Image Source="pack://application:,,,/Resources/picture_save.png" />
</Button>
<Separator />
<Button Name="buttonZoomIn" ToolTip="Zoom in" Click="buttonZoomIn_Click">
@ -31,7 +32,7 @@
</Button>
<TextBlock VerticalAlignment="Center">
<Run Text="{Binding ZoomLevel}" /><Run>00%</Run>
<Run Text="{Binding ZoomLevel}" /><Run>%</Run>
</TextBlock>
</ToolBar>
@ -114,8 +115,8 @@
<TextBlock Grid.Row="0" Grid.Column="0" >Name:</TextBlock>
<TextBox Grid.Row="0" Grid.Column="1" IsReadOnly="True" Text="{Binding Map.Biome.Name,Mode=OneWay}" />
<TextBlock Grid.Row="1" Grid.Column="0" >Height range:</TextBlock>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding Map.Biome.HeightRange,Mode=OneWay}" />
<TextBlock Grid.Row="1" Grid.Column="0" >Height:</TextBlock>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Text="{Binding Map.Biome.Height,Mode=OneWay}" />
<TextBlock Grid.Row="2" Grid.Column="0" >Moisture:</TextBlock>
<TextBox Grid.Row="2" Grid.Column="1" IsReadOnly="True" Text="{Binding Map.Biome.Moisture,Mode=OneWay}" />

View File

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using Microsoft.Win32;
using TransportGame.MapViewer.Business;
using TransportGame.MapViewer.Storage;
using TransportGame.Model;
@ -152,15 +153,15 @@ namespace TransportGame.MapViewer
/// <summary>
/// Gets or sets the zoom level
/// </summary>
public int ZoomLevel
public float ZoomLevel
{
get
{
return Renderer.Scale;
return Renderer.Scale * 100f;
}
set
{
Renderer.Scale = value;
Renderer.Scale = value / 100f;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("ZoomLevel"));
}
@ -215,7 +216,8 @@ namespace TransportGame.MapViewer
try
{
RenderedMap = await Renderer.RenderToImageSource(Map, _layers);
var renderResult = await Task.Run(() => Renderer.Render(Map, _layers));
RenderedMap = renderResult.ToBitmapSource();
}
catch (Exception ex)
{
@ -260,10 +262,10 @@ namespace TransportGame.MapViewer
private async void buttonZoomIn_Click(object sender, RoutedEventArgs e)
{
// Zoom
ZoomLevel++;
ZoomLevel *= 2;
// Update IsEnabled
if (ZoomLevel >= 10)
if (ZoomLevel >= 400)
buttonZoomIn.IsEnabled = false;
buttonZoomOut.IsEnabled = true;
@ -275,10 +277,10 @@ namespace TransportGame.MapViewer
private async void buttonZoomOut_Click(object sender, RoutedEventArgs e)
{
// Zoom
ZoomLevel--;
ZoomLevel /=2;
// Update IsEnabled
if (ZoomLevel <= 1)
if (ZoomLevel <= 10)
buttonZoomOut.IsEnabled = false;
buttonZoomIn.IsEnabled = true;
@ -332,8 +334,7 @@ namespace TransportGame.MapViewer
filename = dialog.FileName;
return true;
}
#endregion
}
}

View File

@ -59,6 +59,8 @@
<Compile Include="..\..\..\Game\Assets\Scripts\Model\Map.cs">
<Link>Model\Map.cs</Link>
</Compile>
<Compile Include="Business\BitmapExtensions.cs" />
<Compile Include="Model\Bitmap24.cs" />
<Compile Include="Storage\MapStorage.cs" />
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>

View File

@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
namespace TransportGame.MapViewer.Model
{
public class Bitmap24
{
/// <summary>
/// Gets the width of the bitmap
/// </summary>
public int Width { get; private set; }
/// <summary>
/// Gets the height of the bitmap
/// </summary>
public int Height { get; private set; }
/// <summary>
/// Gets the raw bytes of the bitmap
/// </summary>
public byte[] Raw { get; private set; }
/// <summary>
/// Initializes a bitmap
/// </summary>
/// <param name="w"></param>
/// <param name="h"></param>
public Bitmap24(int w, int h)
{
Width = w;
Height = h;
Raw = new byte[w * h * 3];
}
/// <summary>
/// Gets or sets a pixel
/// </summary>
/// <param name="x">x coordinate of pixel</param>
/// <param name="y">y coordinate of pixel</param>
public Color this[int x, int y]
{
get
{
int index = RawIndexOf(x, y);
return Color.FromRgb(Raw[index], Raw[index + 1], Raw[index + 2]);
}
set
{
int index = RawIndexOf(x, y);
Raw[index] = value.R;
Raw[index + 1] = value.G;
Raw[index + 2] = value.B;
}
}
private int RawIndexOf(int x, int y)
{
if (x < 0 || x >= Width)
throw new ArgumentOutOfRangeException("x is out of range");
if (y < 0 || y >= Height)
throw new ArgumentOutOfRangeException("x is out of range");
return 3 * (x + y * Width);
}
}
}