Cuberite
A lightweight, fast and extensible game server for Minecraft
VoronoiMap.cpp
Go to the documentation of this file.
1 
2 // VoronoiMap.cpp
3 
4 // Implements the cVoronoiMap class that implements a Voronoi algorithm over a noise to produce a map
5 
6 #include "Globals.h"
7 #include "VoronoiMap.h"
8 
9 
10 
11 
12 
13 cVoronoiMap::cVoronoiMap(int a_Seed, int a_CellSize, int a_JitterSize) :
14  m_Noise1(a_Seed + 1),
15  m_Noise2(a_Seed + 2),
16  m_Noise3(a_Seed + 3),
17  m_CellSize(std::max(a_CellSize, 2)),
18  m_JitterSize(Clamp(a_JitterSize, 1, a_CellSize)),
19  m_OddRowOffset(0),
20  m_CurrentCellX(9999999), // Cell coords that are definitely out of the range for normal generator, so that the first query will overwrite them
21  m_CurrentCellZ(9999999)
22 {
23 }
24 
25 
26 
27 
28 
29 void cVoronoiMap::SetCellSize(int a_CellSize)
30 {
31  a_CellSize = std::max(a_CellSize, 2); // Cell size must be at least 2
32  m_CellSize = a_CellSize;
33 
34  // For compatibility with previous version, which didn't have the jitter, we set jitter here as well.
35  m_JitterSize = a_CellSize;
36 }
37 
38 
39 
40 
41 
42 void cVoronoiMap::SetJitterSize(int a_JitterSize)
43 {
44  m_JitterSize = Clamp(a_JitterSize, 1, m_CellSize);
45 }
46 
47 
48 
49 
50 
51 void cVoronoiMap::SetOddRowOffset(int a_OddRowOffset)
52 {
53  m_OddRowOffset = Clamp(a_OddRowOffset, -m_CellSize, m_CellSize);
54 }
55 
56 
57 
58 
59 
60 int cVoronoiMap::GetValueAt(int a_X, int a_Y)
61 {
62  int SeedX, SeedY, MinDist2;
63  return GetValueAt(a_X, a_Y, SeedX, SeedY, MinDist2);
64 }
65 
66 
67 
68 
69 
70 int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist)
71 {
72  int SeedX, SeedY, MinDist2;
73  int res = GetValueAt(a_X, a_Y, SeedX, SeedY, MinDist2);
74  a_MinDist = (a_X - SeedX) * (a_X - SeedX) + (a_Y - SeedY) * (a_Y - SeedY);
75  return res;
76 }
77 
78 
79 
80 
81 
83  int a_X, int a_Y, // Coords to query
84  int & a_NearestSeedX, int & a_NearestSeedY, // Coords of the closest cell
85  int & a_MinDist2 // Distance to the second closest cell
86 )
87 {
88  int CellX = a_X / m_CellSize;
89  int CellY = a_Y / m_CellSize;
90 
91  UpdateCell(CellX, CellY);
92 
93  // Get 5x5 neighboring cell seeds, compare distance to each. Return the value in the minumim-distance cell
94  int NearestSeedX = 0, NearestSeedY = 0;
95  int MinDist = m_CellSize * m_CellSize * 16; // There has to be a cell closer than this
96  int MinDist2 = MinDist;
97  int res = 0; // Will be overriden
98  for (int x = 0; x < 5; x++)
99  {
100  for (int y = 0; y < 5; y++)
101  {
102  int SeedX = m_SeedX[x][y];
103  int SeedY = m_SeedZ[x][y];
104 
105  int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedY - a_Y) * (SeedY - a_Y);
106  if (Dist < MinDist)
107  {
108  NearestSeedX = SeedX;
109  NearestSeedY = SeedY;
110  MinDist2 = MinDist;
111  MinDist = Dist;
112  res = m_Noise3.IntNoise2DInt(x + CellX - 2, y + CellY - 2);
113  }
114  else if (Dist < MinDist2)
115  {
116  MinDist2 = Dist;
117  }
118  } // for z
119  } // for x
120 
121  a_NearestSeedX = NearestSeedX;
122  a_NearestSeedY = NearestSeedY;
123  a_MinDist2 = MinDist2;
124  return res;
125 }
126 
127 
128 
129 
130 
132  int a_X, int a_Y,
133  int & a_NearestSeedX, int & a_NearestSeedY,
134  int & a_SecondNearestSeedX, int & a_SecondNearestSeedY
135 )
136 {
137  int CellX = a_X / m_CellSize;
138  int CellY = a_Y / m_CellSize;
139 
140  UpdateCell(CellX, CellY);
141 
142  // Get 5x5 neighboring cell seeds, compare distance to each. Return the value in the minumim-distance cell
143  int NearestSeedX = 0, NearestSeedY = 0;
144  int SecondNearestSeedX = 0, SecondNearestSeedY = 0;
145  int MinDist = m_CellSize * m_CellSize * 16; // There has to be a cell closer than this
146  int MinDist2 = MinDist;
147  for (int x = 0; x < 5; x++)
148  {
149  for (int y = 0; y < 5; y++)
150  {
151  int SeedX = m_SeedX[x][y];
152  int SeedY = m_SeedZ[x][y];
153 
154  int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedY - a_Y) * (SeedY - a_Y);
155  if (Dist < MinDist)
156  {
157  SecondNearestSeedX = NearestSeedX;
158  SecondNearestSeedY = NearestSeedY;
159  MinDist2 = MinDist;
160  NearestSeedX = SeedX;
161  NearestSeedY = SeedY;
162  MinDist = Dist;
163  }
164  else if (Dist < MinDist2)
165  {
166  SecondNearestSeedX = SeedX;
167  SecondNearestSeedY = SeedY;
168  MinDist2 = Dist;
169  }
170  } // for z
171  } // for x
172 
173  a_NearestSeedX = NearestSeedX;
174  a_NearestSeedY = NearestSeedY;
175  a_SecondNearestSeedX = SecondNearestSeedX;
176  a_SecondNearestSeedY = SecondNearestSeedY;
177 }
178 
179 
180 
181 
182 
183 void cVoronoiMap::UpdateCell(int a_CellX, int a_CellZ)
184 {
185  // If the specified cell is currently cached, bail out:
186  if ((a_CellX == m_CurrentCellX) && (a_CellZ == m_CurrentCellZ))
187  {
188  return;
189  }
190 
191  // Update the cell cache for the new cell position:
192  int NoiseBaseX = a_CellX - 2;
193  int NoiseBaseZ = a_CellZ - 2;
194  for (int x = 0; x < 5; x++)
195  {
196  int BaseX = (NoiseBaseX + x) * m_CellSize;
197  int OddRowOffset = ((NoiseBaseX + x) & 0x01) * m_OddRowOffset;
198  for (int z = 0; z < 5; z++)
199  {
200  int OffsetX = (m_Noise1.IntNoise2DInt(NoiseBaseX + x, NoiseBaseZ + z) / 8) % m_JitterSize;
201  int OffsetZ = (m_Noise2.IntNoise2DInt(NoiseBaseX + x, NoiseBaseZ + z) / 8) % m_JitterSize;
202  m_SeedX[x][z] = BaseX + OffsetX;
203  m_SeedZ[x][z] = (NoiseBaseZ + z) * m_CellSize + OddRowOffset + OffsetZ;
204  } // for z
205  } // for x
206  m_CurrentCellX = a_CellX;
207  m_CurrentCellZ = a_CellZ;
208 }
209 
210 
211 
212 
T Clamp(T a_Value, T a_Min, T a_Max)
Clamp X to the specified range.
Definition: Globals.h:336
Definition: FastNBT.h:132
int IntNoise2DInt(int a_X, int a_Y) const
Definition: Noise.h:243
int m_CurrentCellZ
The Z coordinate of the currently cached cell neighborhood.
Definition: VoronoiMap.h:78
int m_SeedX[5][5]
The seeds of cells around m_CurrentCellX, m_CurrentCellZ, X-coords.
Definition: VoronoiMap.h:81
void SetCellSize(int a_CellSize)
Sets both the cell size and jitter size used for generating the Voronoi seeds.
Definition: VoronoiMap.cpp:29
int m_CellSize
Size of the Voronoi cells (avg X / Y distance between the seeds).
Definition: VoronoiMap.h:63
int m_JitterSize
The amount that the cell seeds may be offset from the grid.
Definition: VoronoiMap.h:67
void FindNearestSeeds(int a_X, int a_Y, int &a_NearestSeedX, int &a_NearestSeedY, int &a_SecondNearestSeedX, int &a_SecondNearestSeedY)
Finds the nearest and second nearest seeds, returns their coords.
Definition: VoronoiMap.cpp:131
cVoronoiMap(int a_Seed, int a_CellSize=128, int a_JitterSize=128)
Definition: VoronoiMap.cpp:13
void SetJitterSize(int a_JitterSize)
Sets the jitter size.
Definition: VoronoiMap.cpp:42
int m_CurrentCellX
The X coordinate of the currently cached cell neighborhood.
Definition: VoronoiMap.h:75
int m_SeedZ[5][5]
The seeds of cells around m_CurrentCellX, m_CurrentCellZ, X-coords.
Definition: VoronoiMap.h:84
void UpdateCell(int a_CellX, int a_CellZ)
Updates the cached cell seeds to match the specified cell.
Definition: VoronoiMap.cpp:183
void SetOddRowOffset(int a_OddRowOffset)
Sets the offset that is added to each odd row of cells.
Definition: VoronoiMap.cpp:51
cNoise m_Noise2
Definition: VoronoiMap.h:59
int m_OddRowOffset
The constant amount that the cell seeds of every odd row will be offset from the grid.
Definition: VoronoiMap.h:72
cNoise m_Noise3
Definition: VoronoiMap.h:60
cNoise m_Noise1
The noise used for generating Voronoi seeds.
Definition: VoronoiMap.h:58
int GetValueAt(int a_X, int a_Y)
Returns the value in the cell into which the specified point lies.
Definition: VoronoiMap.cpp:60