-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathImageMapBiome.cs
More file actions
146 lines (124 loc) · 5.52 KB
/
Copy pathImageMapBiome.cs
File metadata and controls
146 lines (124 loc) · 5.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using UnityEngine;
namespace BetterContinents
{
internal class ImageMapBiome : ImageMapBase
{
private Heightmap.Biome[] Map;
public ImageMapBiome(string filePath) : base(filePath) { }
public ImageMapBiome(string filePath, byte[] sourceData) : base(filePath, sourceData) { }
private struct ColorBiome
{
public Color32 color;
public Heightmap.Biome biome;
public ColorBiome(Color32 color, Heightmap.Biome biome)
{
this.color = color;
this.biome = biome;
}
}
private static readonly ColorBiome[] BiomeColorMapping = new ColorBiome[]
{
/*
Ocean #0000FF
Meadows #00FF00
Black Forest #007F00
Swamp #7F7F00
Mountains #FFFFFF
Plains #FFFF00
Mistlands #7F7F7F
Deep North #00FFFF
Ash Lands #FF0000
*/
new ColorBiome(new Color32(0, 0, 255, 255), Heightmap.Biome.Ocean),
new ColorBiome(new Color32(0, 255, 0, 255), Heightmap.Biome.Meadows),
new ColorBiome(new Color32(0, 127, 0, 255), Heightmap.Biome.BlackForest),
new ColorBiome(new Color32(127, 127, 0, 255), Heightmap.Biome.Swamp),
new ColorBiome(new Color32(255, 255, 255, 255), Heightmap.Biome.Mountain),
new ColorBiome(new Color32(255, 255, 0, 255), Heightmap.Biome.Plains),
new ColorBiome(new Color32(127, 127, 127, 255), Heightmap.Biome.Mistlands),
new ColorBiome(new Color32(0, 255, 255, 255), Heightmap.Biome.DeepNorth),
new ColorBiome(new Color32(255, 0, 0, 255), Heightmap.Biome.AshLands),
};
protected override bool LoadTextureToMap(Image image)
{
int ColorDistance(Color32 a, Color32 b) =>
(a.r - b.r) * (a.r - b.r) + (a.g - b.g) * (a.g - b.g) + (a.b - b.b) * (a.b - b.b);
var typedImage = (Image<Rgba32>) image;
Map = new Heightmap.Biome[typedImage.Width * typedImage.Height];
var st = new Stopwatch();
st.Start();
var colorMapping = new Dictionary<Color32, Heightmap.Biome>(new Color32Comparer());
for (int y = 0; y < typedImage.Height; y++)
{
var pixelRowSpan = typedImage.GetPixelRowSpan(y);
for (int x = 0; x < typedImage.Width; x++)
{
var color = Convert(pixelRowSpan[x]);
if (!colorMapping.TryGetValue(color, out var biome))
{
biome = BiomeColorMapping.OrderBy(d => ColorDistance(color, d.color)).First().biome;
colorMapping.Add(color, biome);
}
Map[y * typedImage.Width + x] = biome;
}
}
BetterContinents.Log($"Time to calculate biomes from {FilePath}: {st.ElapsedMilliseconds} ms");
return true;
}
public Heightmap.Biome GetValue(float x, float y)
{
float xa = x * (this.Size - 1);
float ya = y * (this.Size - 1);
int xi = Mathf.FloorToInt(xa);
int yi = Mathf.FloorToInt(ya);
float xd = xa - xi;
float yd = ya - yi;
// "Interpolate" the 4 corners (sum the weights of the biomes at the four corners)
Heightmap.Biome GetBiome(int _x, int _y) => this.Map[Mathf.Clamp(_y, 0, this.Size - 1) * this.Size + Mathf.Clamp(_x, 0, this.Size - 1)];
var biomes = new Heightmap.Biome[4];
var biomeWeights = new float[4];
int numBiomes = 0;
int topBiomeIdx = 0;
void SampleBiomeWeighted(int xs, int ys, float weight)
{
var biome = GetBiome(xs, ys);
int i = 0;
for (; i < numBiomes; ++i)
{
if (biomes[i] == biome)
{
if (biomeWeights[i] + weight > biomeWeights[topBiomeIdx])
topBiomeIdx = i;
biomeWeights[i] += weight;
return;
}
}
if (i == numBiomes)
{
if (biomeWeights[numBiomes] + weight > biomeWeights[topBiomeIdx])
topBiomeIdx = numBiomes;
biomes[numBiomes] = biome;
biomeWeights[numBiomes++] = weight;
}
}
SampleBiomeWeighted(xi + 0, yi + 0, (1 - xd) * (1 - yd));
SampleBiomeWeighted(xi + 1, yi + 0, xd * (1 - yd));
SampleBiomeWeighted(xi + 0, yi + 1, (1 - xd) * yd);
SampleBiomeWeighted(xi + 1, yi + 1, xd * yd);
return biomes[topBiomeIdx];
// // Get the rounded value for the diff, so we can choose which of the 4 corner value to return
// int xo = Mathf.RoundToInt(xd);
// int yo = Mathf.RoundToInt(yd);
//
// int xf = Mathf.Clamp(xi + xo, 0, this.Size - 1);
// int yf = Mathf.Clamp(yi + yo, 0, this.Size - 1);
//
// return this.Map[yf * this.Size + xf];
}
}
}