2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
// IntGen.h
|
|
|
|
|
|
|
|
// Declares the cIntGen class and descendants for generating and filtering various 2D arrays of ints
|
|
|
|
|
|
|
|
/*
|
|
|
|
The integers generated may be interpreted in several ways:
|
|
|
|
- land/see designators
|
|
|
|
- 0 = ocean
|
|
|
|
- >0 = land
|
|
|
|
- biome group designators
|
|
|
|
- 0 = ocean
|
|
|
|
- 1 = desert biomes
|
|
|
|
- 2 = temperate biomes
|
|
|
|
- 3 = mountains (hills and forests)
|
|
|
|
- 4 = jungle
|
|
|
|
- 5 = ice biomes
|
|
|
|
- biome IDs
|
|
|
|
The interpretation depends on the generator used and on the position in the chain.
|
|
|
|
|
|
|
|
The generators can be chained together - one produces data that another one consumes.
|
|
|
|
Some of such chain connections require changing the data dimensions between the two, which is handled automatically
|
|
|
|
by using templates.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "../BiomeDef.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Constants representing the biome group designators. */
|
2014-10-30 11:24:35 -04:00
|
|
|
const int bgOcean = 0;
|
|
|
|
const int bgDesert = 1;
|
|
|
|
const int bgTemperate = 2;
|
|
|
|
const int bgMountains = 3;
|
|
|
|
const int bgJungle = 4;
|
|
|
|
const int bgIce = 5;
|
|
|
|
const int bgLandOceanMax = 5; // Maximum biome group value generated in the landOcean generator
|
|
|
|
const int bgMesa = 6;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Interface that all the generator classes provide. */
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGen
|
|
|
|
{
|
|
|
|
public:
|
2014-10-27 04:48:57 -04:00
|
|
|
/** Force a virtual destructor in all descendants.
|
|
|
|
Descendants contain virtual functions and are referred to via pointer-to-base, so they need a virtual destructor. */
|
|
|
|
virtual ~cIntGen() {}
|
|
|
|
|
2014-10-26 14:58:16 -04:00
|
|
|
/** Holds the array of values generated by this class (descendant). */
|
|
|
|
typedef int Values[SizeX * SizeZ];
|
|
|
|
|
|
|
|
/** Generates the array of templated size into a_Values, based on given min coords. */
|
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, Values & a_Values) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Provides additional cNoise member and its helper functions. */
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenWithNoise :
|
|
|
|
public cIntGen<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGen<SizeX, SizeZ> super;
|
|
|
|
|
|
|
|
public:
|
|
|
|
cIntGenWithNoise(int a_Seed) :
|
|
|
|
m_Noise(a_Seed)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
cNoise m_Noise;
|
|
|
|
|
|
|
|
/** Chooses one of a_Val1 or a_Val2, based on m_Noise and the coordinates for querying the noise. */
|
|
|
|
int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2)
|
|
|
|
{
|
|
|
|
int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7;
|
|
|
|
return ((rnd & 1) == 0) ? a_Val1 : a_Val2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Chooses one of a_ValN, based on m_Noise and the coordinates for querying the noise. */
|
|
|
|
int ChooseRandomOne(int a_RndX, int a_RndZ, int a_Val1, int a_Val2, int a_Val3, int a_Val4)
|
|
|
|
{
|
|
|
|
int rnd = m_Noise.IntNoise2DInt(a_RndX, a_RndZ) / 7;
|
|
|
|
switch (rnd % 4)
|
|
|
|
{
|
|
|
|
case 0: return a_Val1;
|
|
|
|
case 1: return a_Val2;
|
|
|
|
case 2: return a_Val3;
|
|
|
|
default: return a_Val4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Generates a 2D array of random integers in the specified range [0 .. Range). */
|
|
|
|
template <int Range, int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenChoice :
|
|
|
|
public cIntGenWithNoise<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGenWithNoise<SizeX, SizeZ> super;
|
|
|
|
|
|
|
|
public:
|
|
|
|
cIntGenChoice(int a_Seed) :
|
|
|
|
super(a_Seed)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:56:02 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
int BaseZ = a_MinZ + z;
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
2014-10-26 17:59:59 -04:00
|
|
|
a_Values[x + SizeX * z] = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7) % Range;
|
2014-10-26 14:58:16 -04:00
|
|
|
}
|
|
|
|
} // for z
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Decides between the ocean and landmass biomes.
|
|
|
|
Has a threshold (in percent) of how much land, the larger the threshold, the more land.
|
|
|
|
Generates 0 for ocean, biome group ID for landmass. */
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
2014-10-26 17:56:02 -04:00
|
|
|
class cIntGenLandOcean :
|
2014-10-26 14:58:16 -04:00
|
|
|
public cIntGenWithNoise<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGenWithNoise<SizeX, SizeZ> super;
|
|
|
|
|
|
|
|
public:
|
2014-10-26 17:56:02 -04:00
|
|
|
cIntGenLandOcean(int a_Seed, int a_Threshold) :
|
2014-10-26 14:58:16 -04:00
|
|
|
super(a_Seed),
|
|
|
|
m_Threshold(a_Threshold)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
int BaseZ = a_MinZ + z;
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
2014-10-27 04:35:21 -04:00
|
|
|
int rnd = (super::m_Noise.IntNoise2DInt(a_MinX + x, BaseZ) / 7);
|
2014-10-30 11:24:35 -04:00
|
|
|
a_Values[x + SizeX * z] = ((rnd % 100) < m_Threshold) ? ((rnd / 128) % bgLandOceanMax + 1) : 0;
|
2014-10-26 14:58:16 -04:00
|
|
|
}
|
|
|
|
}
|
2014-10-26 17:56:02 -04:00
|
|
|
|
|
|
|
// If the centerpoint of the world is within the area, set it to bgTemperate, always:
|
|
|
|
if ((a_MinX <= 0) && (a_MinZ <= 0) && (a_MinX + SizeX > 0) && (a_MinZ + SizeZ > 0))
|
|
|
|
{
|
|
|
|
a_Values[-a_MinX - a_MinZ * SizeX] = bgTemperate;
|
|
|
|
}
|
2014-10-26 14:58:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
int m_Threshold;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenZoom :
|
|
|
|
public cIntGenWithNoise<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGenWithNoise<SizeX, SizeZ> super;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
static const int m_LowerSizeX = (SizeX / 2) + 2;
|
|
|
|
static const int m_LowerSizeZ = (SizeZ / 2) + 2;
|
|
|
|
|
|
|
|
public:
|
2014-10-27 04:35:21 -04:00
|
|
|
typedef std::shared_ptr<cIntGen<m_LowerSizeX, m_LowerSizeZ>> Underlying;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
cIntGenZoom(int a_Seed, Underlying a_UnderlyingGen) :
|
|
|
|
super(a_Seed),
|
|
|
|
m_UnderlyingGen(a_UnderlyingGen)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
// Generate the underlying data with half the resolution:
|
|
|
|
int lowerMinX = a_MinX >> 1;
|
|
|
|
int lowerMinZ = a_MinZ >> 1;
|
|
|
|
int Underlying[m_LowerSizeX * m_LowerSizeZ];
|
|
|
|
m_UnderlyingGen->GetInts(lowerMinX, lowerMinZ, Underlying);
|
|
|
|
const int lowStepX = (m_LowerSizeX - 1) * 2;
|
|
|
|
const int lowStepZ = (m_LowerSizeZ - 1) * 2;
|
|
|
|
int Cache[lowStepX * lowStepZ];
|
|
|
|
|
|
|
|
// Discreet-interpolate the values into twice the size:
|
|
|
|
for (int z = 0; z < m_LowerSizeZ - 1; ++z)
|
|
|
|
{
|
|
|
|
int idx = (z * 2) * lowStepX;
|
|
|
|
int PrevZ0 = Underlying[z * m_LowerSizeX];
|
|
|
|
int PrevZ1 = Underlying[(z + 1) * m_LowerSizeX];
|
|
|
|
|
|
|
|
for (int x = 0; x < m_LowerSizeX - 1; ++x)
|
|
|
|
{
|
|
|
|
int ValX1Z0 = Underlying[x + 1 + z * m_LowerSizeX];
|
|
|
|
int ValX1Z1 = Underlying[x + 1 + (z + 1) * m_LowerSizeX];
|
|
|
|
int RndX = (x + lowerMinX) * 2;
|
|
|
|
int RndZ = (z + lowerMinZ) * 2;
|
|
|
|
Cache[idx] = PrevZ0;
|
2014-10-27 04:35:21 -04:00
|
|
|
Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, PrevZ1);
|
2014-10-26 14:58:16 -04:00
|
|
|
idx++;
|
2014-10-27 04:35:21 -04:00
|
|
|
Cache[idx] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0);
|
|
|
|
Cache[idx + lowStepX] = super::ChooseRandomOne(RndX, RndZ, PrevZ0, ValX1Z0, PrevZ1, ValX1Z1);
|
2014-10-26 14:58:16 -04:00
|
|
|
idx++;
|
|
|
|
PrevZ0 = ValX1Z0;
|
|
|
|
PrevZ1 = ValX1Z1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy from Cache into a_Values; take into account the even/odd offsets in a_Min:
|
|
|
|
for (int z = 0; z < SizeZ; ++z)
|
|
|
|
{
|
|
|
|
memcpy(a_Values + z * SizeX, Cache + (z + (a_MinZ & 1)) * lowStepX + (a_MinX & 1), SizeX * sizeof(int));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Underlying m_UnderlyingGen;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenSmooth :
|
|
|
|
public cIntGenWithNoise<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGenWithNoise<SizeX, SizeZ> super;
|
2014-10-27 04:35:21 -04:00
|
|
|
static const int UnderlyingSizeX = SizeX + 2;
|
|
|
|
static const int UnderlyingSizeZ = SizeZ + 2;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
public:
|
2014-10-27 04:35:21 -04:00
|
|
|
typedef std::shared_ptr<cIntGen<UnderlyingSizeX, UnderlyingSizeZ>> Underlying;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
cIntGenSmooth(int a_Seed, Underlying a_Underlying) :
|
|
|
|
super(a_Seed),
|
|
|
|
m_Underlying(a_Underlying)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
// Generate the underlying values:
|
2014-10-27 04:35:21 -04:00
|
|
|
int Cache[UnderlyingSizeX * UnderlyingSizeZ];
|
2014-10-26 14:58:16 -04:00
|
|
|
m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache);
|
|
|
|
|
|
|
|
// Smooth - for each square check if the surroundings are the same, if so, expand them diagonally.
|
|
|
|
// Also get rid of single-pixel irregularities (A-B-A):
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
int NoiseZ = a_MinZ + z;
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
2014-10-27 04:35:21 -04:00
|
|
|
int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX];
|
|
|
|
int Above = Cache[x + 1 + z * UnderlyingSizeX];
|
|
|
|
int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX];
|
|
|
|
int Left = Cache[x + (z + 1) * UnderlyingSizeX];
|
|
|
|
int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX];
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
if ((Left == Right) && (Above == Below))
|
|
|
|
{
|
2014-10-27 04:35:21 -04:00
|
|
|
if (((super::m_Noise.IntNoise2DInt(a_MinX + x, NoiseZ) / 7) % 2) == 0)
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
val = Left;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
val = Above;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (Left == Right)
|
|
|
|
{
|
|
|
|
val = Left;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Above == Below)
|
|
|
|
{
|
|
|
|
val = Above;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
a_Values[x + z * SizeX] = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Underlying m_Underlying;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenBeaches :
|
|
|
|
public cIntGen<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGen<SizeX, SizeZ> super;
|
|
|
|
static const int m_UnderlyingSizeX = SizeX + 2;
|
|
|
|
static const int m_UnderlyingSizeZ = SizeZ + 2;
|
|
|
|
|
|
|
|
public:
|
2014-10-27 04:35:21 -04:00
|
|
|
typedef std::shared_ptr<cIntGen<m_UnderlyingSizeX, m_UnderlyingSizeZ>> Underlying;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
cIntGenBeaches(Underlying a_Underlying) :
|
|
|
|
m_Underlying(a_Underlying)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
// Map for biome -> its beach:
|
|
|
|
static const int ToBeach[] =
|
|
|
|
{
|
|
|
|
/* biOcean */ biOcean,
|
|
|
|
/* biPlains */ biBeach,
|
|
|
|
/* biDesert */ biBeach,
|
|
|
|
/* biExtremeHills */ biStoneBeach,
|
|
|
|
/* biForest */ biBeach,
|
|
|
|
/* biTaiga */ biColdBeach,
|
|
|
|
/* biSwampland */ biSwampland,
|
|
|
|
/* biRiver */ biRiver,
|
|
|
|
/* biNether */ biNether,
|
|
|
|
/* biEnd */ biEnd,
|
|
|
|
/* biFrozenOcean */ biColdBeach,
|
|
|
|
/* biFrozenRiver */ biColdBeach,
|
|
|
|
/* biIcePlains */ biColdBeach,
|
|
|
|
/* biIceMountains */ biColdBeach,
|
|
|
|
/* biMushroomIsland */ biMushroomShore,
|
|
|
|
/* biMushroomShore */ biMushroomShore,
|
|
|
|
/* biBeach */ biBeach,
|
|
|
|
/* biDesertHills */ biBeach,
|
|
|
|
/* biForestHills */ biBeach,
|
|
|
|
/* biTaigaHills */ biColdBeach,
|
|
|
|
/* biExtremeHillsEdge */ biStoneBeach,
|
|
|
|
/* biJungle */ biBeach,
|
|
|
|
/* biJungleHills */ biBeach,
|
|
|
|
/* biJungleEdge */ biBeach,
|
|
|
|
/* biDeepOcean */ biOcean,
|
|
|
|
/* biStoneBeach */ biStoneBeach,
|
|
|
|
/* biColdBeach */ biColdBeach,
|
|
|
|
/* biBirchForest */ biBeach,
|
|
|
|
/* biBirchForestHills */ biBeach,
|
|
|
|
/* biRoofedForest */ biBeach,
|
|
|
|
/* biColdTaiga */ biColdBeach,
|
|
|
|
/* biColdTaigaHills */ biColdBeach,
|
|
|
|
/* biMegaTaiga */ biStoneBeach,
|
|
|
|
/* biMegaTaigaHills */ biStoneBeach,
|
|
|
|
/* biExtremeHillsPlus */ biStoneBeach,
|
|
|
|
/* biSavanna */ biBeach,
|
|
|
|
/* biSavannaPlateau */ biBeach,
|
|
|
|
/* biMesa */ biMesa,
|
|
|
|
/* biMesaPlateauF */ biMesa,
|
|
|
|
/* biMesaPlateau */ biMesa,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Generate the underlying values:
|
|
|
|
int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ];
|
|
|
|
m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache);
|
|
|
|
|
|
|
|
// Add beaches between ocean and biomes:
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
|
|
|
int val = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX];
|
|
|
|
int Above = Cache[x + 1 + z * m_UnderlyingSizeX];
|
|
|
|
int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX];
|
|
|
|
int Left = Cache[x + (z + 1) * m_UnderlyingSizeX];
|
|
|
|
int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX];
|
|
|
|
if (!IsBiomeOcean(val))
|
|
|
|
{
|
|
|
|
if (IsBiomeOcean(Above) || IsBiomeOcean(Below) || IsBiomeOcean(Left) || IsBiomeOcean(Right))
|
|
|
|
{
|
|
|
|
val = ToBeach[(val % 128) % ARRAYCOUNT(ToBeach)];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
a_Values[x + z * SizeX] = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Underlying m_Underlying;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Generates the underlying numbers and then randomly changes some zeroes into nonzeroes. */
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenAddIslands :
|
|
|
|
public cIntGenWithNoise<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGenWithNoise<SizeX, SizeZ> super;
|
|
|
|
|
|
|
|
public:
|
2014-10-27 04:35:21 -04:00
|
|
|
typedef std::shared_ptr<cIntGen<SizeX, SizeZ>> Underlying;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
cIntGenAddIslands(int a_Seed, int a_Threshold, Underlying a_Underlying) :
|
|
|
|
super(a_Seed),
|
|
|
|
m_Threshold(a_Threshold),
|
|
|
|
m_Underlying(a_Underlying)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
m_Underlying->GetInts(a_MinX, a_MinZ, a_Values);
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
2014-10-26 17:56:02 -04:00
|
|
|
if (a_Values[x + z * SizeX] == bgOcean)
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
2014-10-27 04:35:21 -04:00
|
|
|
int rnd = super::m_Noise.IntNoise2DInt(a_MinX + x, a_MinZ + z) / 7;
|
2014-10-26 14:58:16 -04:00
|
|
|
if (rnd % 100 < m_Threshold)
|
|
|
|
{
|
2014-10-30 11:24:35 -04:00
|
|
|
a_Values[x + z * SizeX] = (rnd / 100) % bgLandOceanMax;
|
2014-10-26 14:58:16 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
int m_Threshold;
|
|
|
|
|
|
|
|
Underlying m_Underlying;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** A filter that adds an edge biome group between two biome groups that need an edge between them. */
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenBiomeGroupEdges :
|
|
|
|
public cIntGen<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGen<SizeX, SizeZ> super;
|
|
|
|
|
|
|
|
static const int m_UnderlyingSizeX = SizeX + 2;
|
|
|
|
static const int m_UnderlyingSizeZ = SizeZ + 2;
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
2014-10-27 04:35:21 -04:00
|
|
|
typedef std::shared_ptr<cIntGen<m_UnderlyingSizeX, m_UnderlyingSizeZ>> Underlying;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
cIntGenBiomeGroupEdges(Underlying a_Underlying) :
|
|
|
|
m_Underlying(a_Underlying)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values)
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
// Generate the underlying biome groups:
|
|
|
|
int Cache[m_UnderlyingSizeX * m_UnderlyingSizeZ];
|
|
|
|
m_Underlying->GetInts(a_MinX, a_MinZ, Cache);
|
|
|
|
|
|
|
|
// Change the biomes on incompatible edges into an edge biome:
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
|
|
|
int v = Cache[x + 1 + (z + 1) * m_UnderlyingSizeX];
|
|
|
|
int Above = Cache[x + 1 + z * m_UnderlyingSizeX];
|
|
|
|
int Below = Cache[x + 1 + (z + 2) * m_UnderlyingSizeX];
|
|
|
|
int Left = Cache[x + (z + 1) * m_UnderlyingSizeX];
|
|
|
|
int Right = Cache[x + 2 + (z + 1) * m_UnderlyingSizeX];
|
|
|
|
switch (v)
|
|
|
|
{
|
|
|
|
// Desert should neighbor only oceans, desert and temperates; change to temperate when another:
|
|
|
|
case bgDesert:
|
|
|
|
{
|
|
|
|
if (
|
2014-10-30 11:24:35 -04:00
|
|
|
!isDesertCompatible(Above) ||
|
|
|
|
!isDesertCompatible(Below) ||
|
|
|
|
!isDesertCompatible(Left) ||
|
|
|
|
!isDesertCompatible(Right)
|
2014-10-26 14:58:16 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
v = bgTemperate;
|
|
|
|
}
|
|
|
|
break;
|
2014-10-30 11:24:35 -04:00
|
|
|
} // case bgDesert
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
// Ice should not neighbor deserts; change to temperate:
|
|
|
|
case bgIce:
|
|
|
|
{
|
|
|
|
if (
|
|
|
|
(Above == bgDesert) ||
|
|
|
|
(Below == bgDesert) ||
|
|
|
|
(Left == bgDesert) ||
|
|
|
|
(Right == bgDesert)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
v = bgTemperate;
|
|
|
|
}
|
|
|
|
break;
|
2014-10-30 11:24:35 -04:00
|
|
|
} // case bgIce
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
// Jungle should not neighbor Desert or Ice; change to temperate:
|
|
|
|
case bgJungle:
|
|
|
|
{
|
|
|
|
if (
|
2014-10-30 11:24:35 -04:00
|
|
|
!isJungleCompatible(Above) ||
|
|
|
|
!isJungleCompatible(Below) ||
|
|
|
|
!isJungleCompatible(Left) ||
|
|
|
|
!isJungleCompatible(Right)
|
2014-10-26 14:58:16 -04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
v = bgTemperate;
|
|
|
|
}
|
2014-10-30 11:24:35 -04:00
|
|
|
} // case bgJungle
|
|
|
|
|
|
|
|
// Mesa should neighbor only oceans and deserts; change to desert when another:
|
|
|
|
case bgMesa:
|
|
|
|
{
|
|
|
|
if (
|
|
|
|
!isMesaCompatible(Above) ||
|
|
|
|
!isMesaCompatible(Below) ||
|
|
|
|
!isMesaCompatible(Left) ||
|
|
|
|
!isMesaCompatible(Right)
|
|
|
|
)
|
|
|
|
{
|
|
|
|
v = bgDesert;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
} // case bgDesert
|
2014-10-26 14:58:16 -04:00
|
|
|
}
|
|
|
|
a_Values[x + z * SizeX] = v;
|
|
|
|
} // for x
|
|
|
|
} // for z
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Underlying m_Underlying;
|
|
|
|
|
|
|
|
|
2014-10-30 11:24:35 -04:00
|
|
|
inline bool isDesertCompatible(int a_BiomeGroup)
|
|
|
|
{
|
|
|
|
switch (a_BiomeGroup)
|
|
|
|
{
|
|
|
|
case bgOcean:
|
|
|
|
case bgDesert:
|
|
|
|
case bgTemperate:
|
|
|
|
case bgMesa:
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool isJungleCompatible(int a_BiomeGroup)
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
2014-10-30 11:24:35 -04:00
|
|
|
return ((a_BiomeGroup != bgDesert) && (a_BiomeGroup != bgMesa) && (a_BiomeGroup != bgIce));
|
2014-10-26 14:58:16 -04:00
|
|
|
}
|
|
|
|
|
2014-10-30 11:24:35 -04:00
|
|
|
inline bool isMesaCompatible(int a_BiomeGroup)
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
2014-10-30 11:24:35 -04:00
|
|
|
return ((a_BiomeGroup == bgOcean) || (a_BiomeGroup == bgDesert));
|
2014-10-26 14:58:16 -04:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenBiomes :
|
|
|
|
public cIntGenWithNoise<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGenWithNoise<SizeX, SizeZ> super;
|
|
|
|
|
|
|
|
public:
|
2014-10-27 04:35:21 -04:00
|
|
|
typedef std::shared_ptr<cIntGen<SizeX, SizeZ>> Underlying;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
cIntGenBiomes(int a_Seed, Underlying a_Underlying) :
|
|
|
|
super(a_Seed),
|
|
|
|
m_Underlying(a_Underlying)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
// Define the per-biome-group biomes:
|
2014-10-30 11:24:35 -04:00
|
|
|
static const int oceanBiomes[] =
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
biOcean, // biDeepOcean,
|
|
|
|
};
|
|
|
|
|
2014-10-30 11:24:35 -04:00
|
|
|
static const int desertBiomes[] =
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
2014-10-30 11:24:35 -04:00
|
|
|
biDesert, biDesert, biDesert, biDesert, biDesert, biDesert, biSavanna, biSavanna, biPlains,
|
2014-10-26 14:58:16 -04:00
|
|
|
};
|
|
|
|
|
2014-10-30 11:24:35 -04:00
|
|
|
static const int temperateBiomes[] =
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
2014-10-30 11:24:35 -04:00
|
|
|
biForest, biForest, biRoofedForest, biExtremeHills, biPlains, biBirchForest, biSwampland,
|
2014-10-26 14:58:16 -04:00
|
|
|
};
|
|
|
|
|
2014-10-30 11:24:35 -04:00
|
|
|
static const int mountainBiomes[] =
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
biExtremeHills, biForest, biTaiga, biPlains,
|
|
|
|
};
|
|
|
|
|
2014-10-30 11:24:35 -04:00
|
|
|
static const int jungleBiomes[] =
|
|
|
|
{
|
|
|
|
biJungle, biJungle, biJungle, biForest,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const int iceBiomes[] =
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
2014-10-30 11:24:35 -04:00
|
|
|
biIcePlains, biIcePlains, biIcePlains, biIcePlains, biColdTaiga,
|
2014-10-26 14:58:16 -04:00
|
|
|
};
|
|
|
|
|
2014-10-30 11:24:35 -04:00
|
|
|
static const int mesaBiomes[] =
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
2014-10-30 11:24:35 -04:00
|
|
|
biMesa, biMesaPlateau,
|
2014-10-26 14:58:16 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
static const cBiomesInGroups BiomesInGroups[] =
|
|
|
|
{
|
2014-10-30 11:24:35 -04:00
|
|
|
/* bgOcean */ { static_cast<int>(ARRAYCOUNT(oceanBiomes)), oceanBiomes},
|
|
|
|
/* bgDesert */ { static_cast<int>(ARRAYCOUNT(desertBiomes)), desertBiomes},
|
|
|
|
/* bgTemperate */ { static_cast<int>(ARRAYCOUNT(temperateBiomes)), temperateBiomes},
|
|
|
|
/* bgMountains */ { static_cast<int>(ARRAYCOUNT(mountainBiomes)), mountainBiomes},
|
|
|
|
/* bgJungle */ { static_cast<int>(ARRAYCOUNT(jungleBiomes)), jungleBiomes},
|
|
|
|
/* bgIce */ { static_cast<int>(ARRAYCOUNT(iceBiomes)), iceBiomes},
|
|
|
|
/* bgMesa */ { static_cast<int>(ARRAYCOUNT(mesaBiomes)), mesaBiomes},
|
2014-10-26 14:58:16 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
// Generate the underlying values, representing biome groups:
|
|
|
|
m_Underlying->GetInts(a_MinX, a_MinZ, a_Values);
|
|
|
|
|
|
|
|
// Overwrite each biome group with a random biome from that group:
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
int IdxZ = z * SizeX;
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
|
|
|
int val = a_Values[x + IdxZ];
|
|
|
|
const cBiomesInGroups & Biomes = BiomesInGroups[val % ARRAYCOUNT(BiomesInGroups)];
|
2014-10-27 04:35:21 -04:00
|
|
|
int rnd = (super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7);
|
2014-10-26 14:58:16 -04:00
|
|
|
a_Values[x + IdxZ] = Biomes.Biomes[rnd % Biomes.Count];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
|
|
struct cBiomesInGroups
|
|
|
|
{
|
|
|
|
const int Count;
|
|
|
|
const int * Biomes;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/** The underlying int generator */
|
|
|
|
Underlying m_Underlying;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenReplaceRandomly :
|
|
|
|
public cIntGenWithNoise<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGenWithNoise<SizeX, SizeZ> super;
|
|
|
|
|
|
|
|
public:
|
2014-10-27 04:35:21 -04:00
|
|
|
typedef std::shared_ptr<cIntGen<SizeX, SizeZ>> Underlying;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
cIntGenReplaceRandomly(int a_From, int a_To, int a_Chance, int a_Seed, Underlying a_Underlying) :
|
|
|
|
super(a_Seed),
|
|
|
|
m_From(a_From),
|
|
|
|
m_To(a_To),
|
|
|
|
m_Chance(a_Chance),
|
|
|
|
m_Underlying(a_Underlying)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
// Generate the underlying values:
|
|
|
|
m_Underlying->GetInts(a_MinX, a_MinZ, a_Values);
|
|
|
|
|
|
|
|
// Replace some of the values:
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
int idxZ = z * SizeX;
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
|
|
|
int idx = x + idxZ;
|
|
|
|
if (a_Values[idx] == m_From)
|
|
|
|
{
|
2014-10-27 04:35:21 -04:00
|
|
|
int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7;
|
2014-10-26 14:58:16 -04:00
|
|
|
if (rnd % 100 < m_Chance)
|
|
|
|
{
|
|
|
|
a_Values[idx] = m_To;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // for z
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
int m_From;
|
|
|
|
int m_To;
|
|
|
|
int m_Chance;
|
|
|
|
Underlying m_Underlying;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Mixer that joins together finalized biomes and rivers.
|
|
|
|
It first checks for oceans; if there's no ocean, it checks for a river. */
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenMixRivers:
|
|
|
|
public cIntGen<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGen<SizeX, SizeZ> super;
|
|
|
|
|
|
|
|
public:
|
2014-10-27 04:35:21 -04:00
|
|
|
typedef std::shared_ptr<cIntGen<SizeX, SizeZ>> Underlying;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
cIntGenMixRivers(Underlying a_Biomes, Underlying a_Rivers):
|
|
|
|
m_Biomes(a_Biomes),
|
|
|
|
m_Rivers(a_Rivers)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
// Generate the underlying data:
|
|
|
|
m_Biomes->GetInts(a_MinX, a_MinZ, a_Values);
|
2014-10-26 17:59:59 -04:00
|
|
|
typename super::Values Rivers;
|
2014-10-26 14:58:16 -04:00
|
|
|
m_Rivers->GetInts(a_MinX, a_MinZ, Rivers);
|
|
|
|
|
|
|
|
// Mix the values:
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
int idxZ = z * SizeX;
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
|
|
|
int idx = x + idxZ;
|
|
|
|
if (IsBiomeOcean(a_Values[idx]))
|
|
|
|
{
|
|
|
|
// Oceans are kept without any changes
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (Rivers[idx] != biRiver)
|
|
|
|
{
|
|
|
|
// There's no river, keep the current value
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// There's a river, change the output to a river or a frozen river, based on the original biome:
|
|
|
|
if (IsBiomeVeryCold((EMCSBiome)a_Values[idx]))
|
|
|
|
{
|
|
|
|
a_Values[idx] = biFrozenRiver;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
a_Values[idx] = biRiver;
|
|
|
|
}
|
|
|
|
} // for x
|
|
|
|
} // for z
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Underlying m_Biomes;
|
|
|
|
Underlying m_Rivers;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Generates a river based on the underlying data.
|
|
|
|
This is basically an edge detector over the underlying data. The rivers are the edges where the underlying data
|
|
|
|
changes from one pixel to its neighbor. */
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenRiver:
|
|
|
|
public cIntGenWithNoise<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGenWithNoise<SizeX, SizeZ> super;
|
|
|
|
static const int UnderlyingSizeX = SizeX + 2;
|
|
|
|
static const int UnderlyingSizeZ = SizeZ + 2;
|
|
|
|
|
|
|
|
public:
|
2014-10-27 04:35:21 -04:00
|
|
|
typedef std::shared_ptr<cIntGen<UnderlyingSizeX, UnderlyingSizeZ>> Underlying;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
cIntGenRiver(int a_Seed, Underlying a_Underlying):
|
|
|
|
super(a_Seed),
|
|
|
|
m_Underlying(a_Underlying)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
// Generate the underlying data:
|
|
|
|
int Cache[UnderlyingSizeX * UnderlyingSizeZ];
|
|
|
|
m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache);
|
|
|
|
|
|
|
|
// Detect the edges:
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
|
|
|
int Above = Cache[x + 1 + z * UnderlyingSizeX];
|
|
|
|
int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX];
|
|
|
|
int Left = Cache[x + (z + 1) * UnderlyingSizeX];
|
|
|
|
int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX];
|
|
|
|
int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX];
|
|
|
|
|
|
|
|
if ((val == Above) && (val == Below) && (val == Left) && (val == Right))
|
|
|
|
{
|
|
|
|
val = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
val = biRiver;
|
|
|
|
}
|
|
|
|
a_Values[x + z * SizeX] = val;
|
|
|
|
} // for x
|
|
|
|
} // for z
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
Underlying m_Underlying;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Turns some of the oceans into the specified biome. Used for mushroom and deep ocean.
|
|
|
|
The biome is only placed if at least 3 of its neighbors are ocean and only with the specified chance. */
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenAddToOcean:
|
|
|
|
public cIntGenWithNoise<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGenWithNoise<SizeX, SizeZ> super;
|
|
|
|
static const int UnderlyingSizeX = SizeX + 2;
|
|
|
|
static const int UnderlyingSizeZ = SizeZ + 2;
|
|
|
|
|
|
|
|
public:
|
2014-10-27 04:35:21 -04:00
|
|
|
typedef std::shared_ptr<cIntGen<UnderlyingSizeX, UnderlyingSizeZ>> Underlying;
|
2014-10-26 14:58:16 -04:00
|
|
|
|
|
|
|
|
|
|
|
cIntGenAddToOcean(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying):
|
|
|
|
super(a_Seed),
|
|
|
|
m_Chance(a_Chance),
|
|
|
|
m_ToValue(a_ToValue),
|
|
|
|
m_Underlying(a_Underlying)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-10-26 17:59:59 -04:00
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
// Generate the underlying data:
|
|
|
|
int Cache[UnderlyingSizeX * UnderlyingSizeZ];
|
|
|
|
m_Underlying->GetInts(a_MinX - 1, a_MinZ - 1, Cache);
|
|
|
|
|
|
|
|
// Add the mushroom islands:
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
|
|
|
int val = Cache[x + 1 + (z + 1) * UnderlyingSizeX];
|
|
|
|
if (!IsBiomeOcean(val))
|
|
|
|
{
|
|
|
|
a_Values[x + z * SizeX] = val;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Count the ocean neighbors:
|
|
|
|
int Above = Cache[x + 1 + z * UnderlyingSizeX];
|
|
|
|
int Below = Cache[x + 1 + (z + 2) * UnderlyingSizeX];
|
|
|
|
int Left = Cache[x + (z + 1) * UnderlyingSizeX];
|
|
|
|
int Right = Cache[x + 2 + (z + 1) * UnderlyingSizeX];
|
|
|
|
int NumOceanNeighbors = 0;
|
|
|
|
if (IsBiomeOcean(Above))
|
|
|
|
{
|
|
|
|
NumOceanNeighbors += 1;
|
|
|
|
}
|
2014-10-26 16:35:24 -04:00
|
|
|
if (IsBiomeOcean(Below))
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
NumOceanNeighbors += 1;
|
|
|
|
}
|
2014-10-26 16:35:24 -04:00
|
|
|
if (IsBiomeOcean(Left))
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
NumOceanNeighbors += 1;
|
|
|
|
}
|
2014-10-26 16:35:24 -04:00
|
|
|
if (IsBiomeOcean(Right))
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
NumOceanNeighbors += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If at least 3 ocean neighbors and the chance is right, change:
|
2014-10-27 04:35:21 -04:00
|
|
|
if ((NumOceanNeighbors >= 3) && ((super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7) % 1000 < m_Chance))
|
2014-10-26 14:58:16 -04:00
|
|
|
{
|
|
|
|
a_Values[x + z * SizeX] = m_ToValue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
a_Values[x + z * SizeX] = val;
|
|
|
|
}
|
|
|
|
} // for x
|
|
|
|
} // for z
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** Chance, in permille, of changing the biome. */
|
|
|
|
int m_Chance;
|
|
|
|
|
|
|
|
/** The value to change the ocean into. */
|
|
|
|
int m_ToValue;
|
|
|
|
|
|
|
|
Underlying m_Underlying;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-10-30 11:24:35 -04:00
|
|
|
|
|
|
|
/** Changes random pixels of the underlying data to the specified value. */
|
|
|
|
template <int SizeX, int SizeZ = SizeX>
|
|
|
|
class cIntGenSetRandomly :
|
|
|
|
public cIntGenWithNoise<SizeX, SizeZ>
|
|
|
|
{
|
|
|
|
typedef cIntGenWithNoise<SizeX, SizeZ> super;
|
|
|
|
|
|
|
|
public:
|
|
|
|
typedef std::shared_ptr<cIntGen<SizeX, SizeZ>> Underlying;
|
|
|
|
|
|
|
|
cIntGenSetRandomly(int a_Seed, int a_Chance, int a_ToValue, Underlying a_Underlying) :
|
|
|
|
super(a_Seed),
|
|
|
|
m_Chance(a_Chance),
|
|
|
|
m_ToValue(a_ToValue),
|
|
|
|
m_Underlying(a_Underlying)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
virtual void GetInts(int a_MinX, int a_MinZ, typename super::Values & a_Values) override
|
|
|
|
{
|
|
|
|
// Generate the underlying data:
|
|
|
|
m_Underlying->GetInts(a_MinX, a_MinZ, a_Values);
|
|
|
|
|
|
|
|
// Change random pixels to bgOcean:
|
|
|
|
for (int z = 0; z < SizeZ; z++)
|
|
|
|
{
|
|
|
|
for (int x = 0; x < SizeX; x++)
|
|
|
|
{
|
|
|
|
int rnd = super::m_Noise.IntNoise2DInt(x + a_MinX, z + a_MinZ) / 7;
|
|
|
|
if (rnd % 1000 < m_Chance)
|
|
|
|
{
|
|
|
|
a_Values[x + z * SizeX] = m_ToValue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/** Chance, in permille, of changing each pixel. */
|
|
|
|
int m_Chance;
|
|
|
|
|
|
|
|
/** The value to which to set the pixel. */
|
|
|
|
int m_ToValue;
|
|
|
|
|
|
|
|
Underlying m_Underlying;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|