summaryrefslogtreecommitdiffstats
path: root/src/VoronoiMap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VoronoiMap.cpp')
-rw-r--r--src/VoronoiMap.cpp126
1 files changed, 105 insertions, 21 deletions
diff --git a/src/VoronoiMap.cpp b/src/VoronoiMap.cpp
index 5efd09c01..5ad634fe4 100644
--- a/src/VoronoiMap.cpp
+++ b/src/VoronoiMap.cpp
@@ -10,11 +10,13 @@
-cVoronoiMap::cVoronoiMap(int a_Seed, int a_CellSize) :
+cVoronoiMap::cVoronoiMap(int a_Seed, int a_CellSize, int a_JitterSize) :
m_Noise1(a_Seed + 1),
m_Noise2(a_Seed + 2),
m_Noise3(a_Seed + 3),
- m_CellSize(a_CellSize),
+ m_CellSize(std::max(a_CellSize, 2)),
+ m_JitterSize(Clamp(a_JitterSize, 1, a_CellSize)),
+ m_OddRowOffset(0),
m_CurrentCellX(9999999), // Cell coords that are definitely out of the range for normal generator, so that the first query will overwrite them
m_CurrentCellZ(9999999)
{
@@ -26,7 +28,29 @@ cVoronoiMap::cVoronoiMap(int a_Seed, int a_CellSize) :
void cVoronoiMap::SetCellSize(int a_CellSize)
{
+ a_CellSize = std::max(a_CellSize, 2); // Cell size must be at least 2
m_CellSize = a_CellSize;
+
+ // For compatibility with previous version, which didn't have the jitter, we set jitter here as well.
+ m_JitterSize = a_CellSize;
+}
+
+
+
+
+
+void cVoronoiMap::SetJitterSize(int a_JitterSize)
+{
+ m_JitterSize = Clamp(a_JitterSize, 1, m_CellSize);
+}
+
+
+
+
+
+void cVoronoiMap::SetOddRowOffset(int a_OddRowOffset)
+{
+ m_OddRowOffset = Clamp(a_OddRowOffset, -m_CellSize, m_CellSize);
}
@@ -35,8 +59,8 @@ void cVoronoiMap::SetCellSize(int a_CellSize)
int cVoronoiMap::GetValueAt(int a_X, int a_Y)
{
- int MinDist1, MinDist2;
- return GetValueAt(a_X, a_Y, MinDist1, MinDist2);
+ int SeedX, SeedY, MinDist2;
+ return GetValueAt(a_X, a_Y, SeedX, SeedY, MinDist2);
}
@@ -45,41 +69,47 @@ int cVoronoiMap::GetValueAt(int a_X, int a_Y)
int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist)
{
- int MinDist2;
- return GetValueAt(a_X, a_Y, a_MinDist, MinDist2);
+ int SeedX, SeedY, MinDist2;
+ int res = GetValueAt(a_X, a_Y, SeedX, SeedY, MinDist2);
+ a_MinDist = (a_X - SeedX) * (a_X - SeedX) + (a_Y - SeedY) * (a_Y - SeedY);
+ return res;
}
-int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist1, int & a_MinDist2)
+int cVoronoiMap::GetValueAt(
+ int a_X, int a_Y, // Coords to query
+ int & a_NearestSeedX, int & a_NearestSeedY, // Coords of the closest cell
+ int & a_MinDist2 // Distance to the second closest cell
+)
{
- // Note that due to historical reasons, the algorithm uses XZ coords, while the input uses XY coords.
- // This is because the algorithm was first implemented directly in the biome generators which use MC coords.
-
int CellX = a_X / m_CellSize;
- int CellZ = a_Y / m_CellSize;
+ int CellY = a_Y / m_CellSize;
- UpdateCell(CellX, CellZ);
+ UpdateCell(CellX, CellY);
// Get 5x5 neighboring cell seeds, compare distance to each. Return the value in the minumim-distance cell
+ int NearestSeedX = 0, NearestSeedY = 0;
int MinDist = m_CellSize * m_CellSize * 16; // There has to be a cell closer than this
int MinDist2 = MinDist;
int res = 0; // Will be overriden
for (int x = 0; x < 5; x++)
{
- for (int z = 0; z < 5; z++)
+ for (int y = 0; y < 5; y++)
{
- int SeedX = m_SeedX[x][z];
- int SeedZ = m_SeedZ[x][z];
+ int SeedX = m_SeedX[x][y];
+ int SeedY = m_SeedZ[x][y];
- int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedZ - a_Y) * (SeedZ - a_Y);
+ int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedY - a_Y) * (SeedY - a_Y);
if (Dist < MinDist)
{
+ NearestSeedX = SeedX;
+ NearestSeedY = SeedY;
MinDist2 = MinDist;
MinDist = Dist;
- res = m_Noise3.IntNoise2DInt(x + CellX - 2, z + CellZ - 2);
+ res = m_Noise3.IntNoise2DInt(x + CellX - 2, y + CellY - 2);
}
else if (Dist < MinDist2)
{
@@ -88,7 +118,8 @@ int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist1, int & a_MinDist2
} // for z
} // for x
- a_MinDist1 = MinDist;
+ a_NearestSeedX = NearestSeedX;
+ a_NearestSeedY = NearestSeedY;
a_MinDist2 = MinDist2;
return res;
}
@@ -97,6 +128,58 @@ int cVoronoiMap::GetValueAt(int a_X, int a_Y, int & a_MinDist1, int & a_MinDist2
+void cVoronoiMap::FindNearestSeeds(
+ int a_X, int a_Y,
+ int & a_NearestSeedX, int & a_NearestSeedY,
+ int & a_SecondNearestSeedX, int & a_SecondNearestSeedY
+)
+{
+ int CellX = a_X / m_CellSize;
+ int CellY = a_Y / m_CellSize;
+
+ UpdateCell(CellX, CellY);
+
+ // Get 5x5 neighboring cell seeds, compare distance to each. Return the value in the minumim-distance cell
+ int NearestSeedX = 0, NearestSeedY = 0;
+ int SecondNearestSeedX = 0, SecondNearestSeedY = 0;
+ int MinDist = m_CellSize * m_CellSize * 16; // There has to be a cell closer than this
+ int MinDist2 = MinDist;
+ for (int x = 0; x < 5; x++)
+ {
+ for (int y = 0; y < 5; y++)
+ {
+ int SeedX = m_SeedX[x][y];
+ int SeedY = m_SeedZ[x][y];
+
+ int Dist = (SeedX - a_X) * (SeedX - a_X) + (SeedY - a_Y) * (SeedY - a_Y);
+ if (Dist < MinDist)
+ {
+ SecondNearestSeedX = NearestSeedX;
+ SecondNearestSeedY = NearestSeedY;
+ MinDist2 = MinDist;
+ NearestSeedX = SeedX;
+ NearestSeedY = SeedY;
+ MinDist = Dist;
+ }
+ else if (Dist < MinDist2)
+ {
+ SecondNearestSeedX = SeedX;
+ SecondNearestSeedY = SeedY;
+ MinDist2 = Dist;
+ }
+ } // for z
+ } // for x
+
+ a_NearestSeedX = NearestSeedX;
+ a_NearestSeedY = NearestSeedY;
+ a_SecondNearestSeedX = SecondNearestSeedX;
+ a_SecondNearestSeedY = SecondNearestSeedY;
+}
+
+
+
+
+
void cVoronoiMap::UpdateCell(int a_CellX, int a_CellZ)
{
// If the specified cell is currently cached, bail out:
@@ -111,12 +194,13 @@ void cVoronoiMap::UpdateCell(int a_CellX, int a_CellZ)
for (int x = 0; x < 5; x++)
{
int BaseX = (NoiseBaseX + x) * m_CellSize;
+ int OddRowOffset = ((NoiseBaseX + x) & 0x01) * m_OddRowOffset;
for (int z = 0; z < 5; z++)
{
- int OffsetX = (m_Noise1.IntNoise2DInt(NoiseBaseX + x, NoiseBaseZ + z) / 8) % m_CellSize;
- int OffsetZ = (m_Noise2.IntNoise2DInt(NoiseBaseX + x, NoiseBaseZ + z) / 8) % m_CellSize;
+ int OffsetX = (m_Noise1.IntNoise2DInt(NoiseBaseX + x, NoiseBaseZ + z) / 8) % m_JitterSize;
+ int OffsetZ = (m_Noise2.IntNoise2DInt(NoiseBaseX + x, NoiseBaseZ + z) / 8) % m_JitterSize;
m_SeedX[x][z] = BaseX + OffsetX;
- m_SeedZ[x][z] = (NoiseBaseZ + z) * m_CellSize + OffsetZ;
+ m_SeedZ[x][z] = (NoiseBaseZ + z) * m_CellSize + OddRowOffset + OffsetZ;
} // for z
} // for x
m_CurrentCellX = a_CellX;