8 #include "../IniFile.h"
9 #include "../LinearInterpolation.h"
10 #include "../LinearUpscale.h"
65 static class cInterpolNoiseSpeedTest
68 cInterpolNoiseSpeedTest(
void)
72 printf(
"InterpolNoise speed comparison finished.\n");
77 void TestSpeed3D(
void)
79 printf(
"Evaluating 3D noise performance...\n");
80 static const int SIZE_X = 128;
81 static const int SIZE_Y = 128;
82 static const int SIZE_Z = 128;
84 std::unique_ptr<NOISE_DATATYPE[]> arr(
new NOISE_DATATYPE[SIZE_X * SIZE_Y * SIZE_Z]);
89 long long start = timer.GetNowTime();
90 for (
int i = 0; i < 30; i++)
92 interpNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, MUL * i, MUL * i + MUL, 0, MUL, 0, MUL);
94 long long end = timer.GetNowTime();
95 printf(
"InterpolNoise took %.02f sec\n",
static_cast<float>(end - start) / 1000);
99 start = timer.GetNowTime();
100 for (
int i = 0; i < 30; i++)
102 cubicNoise.Generate3D(arr.get(), SIZE_X, SIZE_Y, SIZE_Z, MUL * i, MUL * i + MUL, 0, MUL, 0, MUL);
104 end = timer.GetNowTime();
105 printf(
"CubicNoise took %.02f sec\n",
static_cast<float>(end - start) / 1000);
106 printf(
"3D noise performance comparison finished.\n");
111 void TestSpeed2D(
void)
113 printf(
"Evaluating 2D noise performance...\n");
114 static const int SIZE_X = 128;
115 static const int SIZE_Y = 128;
117 std::unique_ptr<NOISE_DATATYPE[]> arr(
new NOISE_DATATYPE[SIZE_X * SIZE_Y]);
122 long long start = timer.GetNowTime();
123 for (
int i = 0; i < 500; i++)
125 interpNoise.Generate2D(arr.get(), SIZE_X, SIZE_Y, MUL * i, MUL * i + MUL, 0, MUL);
127 long long end = timer.GetNowTime();
128 printf(
"InterpolNoise took %.02f sec\n",
static_cast<float>(end - start) / 1000);
132 start = timer.GetNowTime();
133 for (
int i = 0; i < 500; i++)
135 cubicNoise.Generate2D(arr.get(), SIZE_X, SIZE_Y, MUL * i, MUL * i + MUL, 0, MUL);
137 end = timer.GetNowTime();
138 printf(
"CubicNoise took %.02f sec\n",
static_cast<float>(end - start) / 1000);
139 printf(
"2D noise performance comparison finished.\n");
141 } g_InterpolNoiseSpeedTest;
201 for (
size_t i = 0; i <
ARRAYCOUNT(a_BiomeMap); i++)
221 int idx = z * 17 * 257 + y * 17;
260 m_Perlin.Generate3D(NoiseO,
DIM_X,
DIM_Y,
DIM_Z, StartX, EndX, StartY, EndY, StartZ, EndZ, NoiseW);
264 m_Cubic.Generate2D(Height,
DIM_X,
DIM_Z, StartX / 5, EndX / 5, StartZ / 5, EndZ / 5);
265 for (
size_t i = 0; i <
ARRAYCOUNT(Height); i++)
271 for (
int y = 0; y <
DIM_Y; y++)
275 for (
int z = 0; z <
DIM_Z; z++)
278 for (
int x = 0; x <
DIM_X; x++)
280 CurRow[x] += AddHeight + Height[x +
DIM_X * z];
303 int LastAir = a_ChunkDesc.
GetHeight(x, z) + 1;
304 bool HasHadWater =
false;
305 for (
int y = LastAir - 1; y > 0; y--)
351 m_ChoiceNoise(a_Seed),
352 m_DensityNoiseA(a_Seed + 1),
353 m_DensityNoiseB(a_Seed + 2),
354 m_BaseNoise(a_Seed + 3),
355 m_HeightAmplification(0.0),
360 m_BaseFrequencyX(0.0),
361 m_BaseFrequencyZ(0.0),
362 m_ChoiceFrequencyX(0.0),
363 m_ChoiceFrequencyY(0.0),
364 m_ChoiceFrequencyZ(0.0),
366 m_LastChunkCoords(0x7fffffff, 0x7fffffff)
389 int NumChoiceOctaves = a_IniFile.
GetValueSetI(
"Generator",
"Noise3DNumChoiceOctaves", 4);
390 int NumDensityOctaves = a_IniFile.
GetValueSetI(
"Generator",
"Noise3DNumDensityOctaves", 6);
391 int NumBaseOctaves = a_IniFile.
GetValueSetI(
"Generator",
"Noise3DNumBaseOctaves", 6);
396 for (
int i = 0; i < NumChoiceOctaves; i++)
404 wavlen = 1; ampl = 1;
405 for (
int i = 0; i < NumDensityOctaves; i++)
414 wavlen = 1; ampl = BaseNoiseAmplitude;
415 for (
int i = 0; i < NumBaseOctaves; i++)
445 m_ChoiceNoise.
Generate3D (ChoiceNoise, 33, 5, 5, 0, 257 /
m_ChoiceFrequencyY, BlockX /
m_ChoiceFrequencyX, (BlockX + 17) /
m_ChoiceFrequencyX, BlockZ /
m_ChoiceFrequencyZ, (BlockZ + 17) /
m_ChoiceFrequencyZ, Workspace);
446 m_DensityNoiseA.
Generate3D(DensityNoiseA, 33, 5, 5, 0, 257 /
m_FrequencyY, BlockX /
m_FrequencyX, (BlockX + 17) /
m_FrequencyX, BlockZ /
m_FrequencyZ, (BlockZ + 17) /
m_FrequencyZ, Workspace);
447 m_DensityNoiseB.
Generate3D(DensityNoiseB, 33, 5, 5, 0, 257 /
m_FrequencyY, BlockX /
m_FrequencyX, (BlockX + 17) /
m_FrequencyX, BlockZ /
m_FrequencyZ, (BlockZ + 17) /
m_FrequencyZ, Workspace);
451 for (
int z = 0; z < 5; z++)
453 for (
int x = 0; x < 5; x++)
456 for (
int y = 0; y < 33; y++)
473 int idx = 33 * x + 33 * 5 * z + y;
474 Workspace[idx] =
ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise;
478 LinearUpscale3DArray<NOISE_DATATYPE>(Workspace, 33, 5, 5,
m_NoiseArray, 8, 4, 4);
510 m_ChoiceNoise(a_Seed),
511 m_DensityNoiseA(a_Seed + 1),
512 m_DensityNoiseB(a_Seed + 2),
513 m_BaseNoise(a_Seed + 3),
514 m_BiomeGen(a_BiomeGen),
515 m_LastChunkCoords(0x7fffffff, 0x7fffffff)
547 int NumChoiceOctaves = a_IniFile.
GetValueSetI(
"Generator",
"BiomalNoise3DNumChoiceOctaves", 4);
548 int NumDensityOctaves = a_IniFile.
GetValueSetI(
"Generator",
"BiomalNoise3DNumDensityOctaves", 6);
549 int NumBaseOctaves = a_IniFile.
GetValueSetI(
"Generator",
"BiomalNoise3DNumBaseOctaves", 6);
554 for (
int i = 0; i < NumChoiceOctaves; i++)
562 wavlen = 1; ampl = 1;
563 for (
int i = 0; i < NumDensityOctaves; i++)
572 wavlen = 1; ampl = BaseNoiseAmplitude;
573 for (
int i = 0; i < NumBaseOctaves; i++)
608 m_ChoiceNoise.
Generate3D (ChoiceNoise, 33, 5, 5, 0, 257 /
m_ChoiceFrequencyY, BlockX /
m_ChoiceFrequencyX, (BlockX + 17) /
m_ChoiceFrequencyX, BlockZ /
m_ChoiceFrequencyZ, (BlockZ + 17) /
m_ChoiceFrequencyZ, Workspace);
609 m_DensityNoiseA.
Generate3D(DensityNoiseA, 33, 5, 5, 0, 257 /
m_FrequencyY, BlockX /
m_FrequencyX, (BlockX + 17) /
m_FrequencyX, BlockZ /
m_FrequencyZ, (BlockZ + 17) /
m_FrequencyZ, Workspace);
610 m_DensityNoiseB.
Generate3D(DensityNoiseB, 33, 5, 5, 0, 257 /
m_FrequencyY, BlockX /
m_FrequencyX, (BlockX + 17) /
m_FrequencyX, BlockZ /
m_FrequencyZ, (BlockZ + 17) /
m_FrequencyZ, Workspace);
614 for (
int z = 0; z < 5; z++)
616 for (
int x = 0; x < 5; x++)
621 for (
int y = 0; y < 33; y++)
637 int idx = 33 * x + y + 33 * 5 * z;
638 Workspace[idx] =
ClampedLerp(DensityNoiseA[idx], DensityNoiseB[idx], 8 * (ChoiceNoise[idx] + 0.5f)) + AddHeight + curBaseNoise;
642 LinearUpscale3DArray<NOISE_DATATYPE>(Workspace, 33, 5, 5,
m_NoiseArray, 8, 4, 4);
653 for (
int z = 0; z < 3; z++)
655 for (
int x = 0; x < 3; x++)
662 for (
int z = 0; z < 5; z++)
664 for (
int x = 0; x < 5; x++)
672 int neicellz = colz / 16;
673 int neirelz = colz % 16;
677 int neicellx = colx / 16;
678 int neirelx = colx % 16;
682 totalHeightAmp += heightAmp *
m_Weight[relz][relx];
683 totalMidPoint += midPoint *
m_Weight[relz][relx];
686 a_HeightAmp[x + 5 * z] = totalHeightAmp /
m_WeightSum;
687 a_MidPoint[x + 5 * z] = totalMidPoint /
m_WeightSum;
700 case biBeach: a_HeightAmp = 0.2f; a_MidPoint = 60;
break;
701 case biBirchForest: a_HeightAmp = 0.1f; a_MidPoint = 64;
break;
705 case biColdBeach: a_HeightAmp = 0.3f; a_MidPoint = 62;
break;
706 case biColdTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64;
break;
707 case biColdTaigaM: a_HeightAmp = 0.1f; a_MidPoint = 64;
break;
709 case biDesertHills: a_HeightAmp = 0.075f; a_MidPoint = 68;
break;
710 case biDeepOcean: a_HeightAmp = 0.17f; a_MidPoint = 35;
break;
711 case biDesert: a_HeightAmp = 0.29f; a_MidPoint = 62;
break;
712 case biDesertM: a_HeightAmp = 0.29f; a_MidPoint = 62;
break;
713 case biEnd: a_HeightAmp = 0.15f; a_MidPoint = 64;
break;
714 case biExtremeHills: a_HeightAmp = 0.045f; a_MidPoint = 75;
break;
720 case biForest: a_HeightAmp = 0.1f; a_MidPoint = 64;
break;
721 case biForestHills: a_HeightAmp = 0.075f; a_MidPoint = 68;
break;
722 case biFrozenRiver: a_HeightAmp = 0.4f; a_MidPoint = 54;
break;
723 case biFrozenOcean: a_HeightAmp = 0.12f; a_MidPoint = 45;
break;
724 case biIceMountains: a_HeightAmp = 0.075f; a_MidPoint = 68;
break;
725 case biIcePlains: a_HeightAmp = 0.3f; a_MidPoint = 62;
break;
727 case biJungle: a_HeightAmp = 0.1f; a_MidPoint = 63;
break;
728 case biJungleEdge: a_HeightAmp = 0.15f; a_MidPoint = 62;
break;
729 case biJungleEdgeM: a_HeightAmp = 0.15f; a_MidPoint = 62;
break;
730 case biJungleHills: a_HeightAmp = 0.075f; a_MidPoint = 68;
break;
731 case biJungleM: a_HeightAmp = 0.1f; a_MidPoint = 63;
break;
734 case biMegaTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64;
break;
736 case biMesa: a_HeightAmp = 0.09f; a_MidPoint = 61;
break;
737 case biMesaBryce: a_HeightAmp = 0.15f; a_MidPoint = 61;
break;
738 case biMesaPlateau: a_HeightAmp = 0.25f; a_MidPoint = 86;
break;
744 case biNether: a_HeightAmp = 0.01f; a_MidPoint = 64;
break;
745 case biOcean: a_HeightAmp = 0.12f; a_MidPoint = 45;
break;
746 case biPlains: a_HeightAmp = 0.3f; a_MidPoint = 62;
break;
747 case biRiver: a_HeightAmp = 0.4f; a_MidPoint = 54;
break;
750 case biSavanna: a_HeightAmp = 0.3f; a_MidPoint = 62;
break;
751 case biSavannaM: a_HeightAmp = 0.3f; a_MidPoint = 62;
break;
754 case biStoneBeach: a_HeightAmp = 0.075f; a_MidPoint = 60;
break;
756 case biSwampland: a_HeightAmp = 0.25f; a_MidPoint = 59;
break;
757 case biSwamplandM: a_HeightAmp = 0.11f; a_MidPoint = 59;
break;
758 case biTaiga: a_HeightAmp = 0.1f; a_MidPoint = 64;
break;
759 case biTaigaM: a_HeightAmp = 0.1f; a_MidPoint = 70;
break;
760 case biTaigaHills: a_HeightAmp = 0.075f; a_MidPoint = 68;
break;
767 a_HeightAmp = 0.001f;
EMCSBiome
Biome IDs The first batch corresponds to the clientside biomes, used by MineCraft.
@ E_BLOCK_STATIONARY_WATER
unsigned char BLOCKTYPE
The datatype used by blockdata.
#define ARRAYCOUNT(X)
Evaluates to the number of elements in an array (compile-time!)
void LinearUpscale3DArray(TYPE *a_Src, int a_SrcSizeX, int a_SrcSizeY, int a_SrcSizeZ, TYPE *a_Dst, int a_UpscaleX, int a_UpscaleY, int a_UpscaleZ)
Linearly interpolates values in the array between the equidistant anchor points (upscales).
NOISE_DATATYPE ClampedLerp(NOISE_DATATYPE a_Val1, NOISE_DATATYPE a_Val2, NOISE_DATATYPE a_Ratio)
Linearly interpolates between two values, clamping the ratio to [0, 1] first.
float NOISE_DATATYPE
The datatype used by all the noise generators.
Wraps the chunk coords into a single structure.
static EMCSBiome GetBiome(const BiomeMap &a_BiomeMap, int a_X, int a_Z)
EMCSBiome BiomeMap[Width *Width]
The type used for any biomemap operations and storage inside Cuberite, using Cuberite biomes (need no...
HEIGHTTYPE GetHeight(int a_RelX, int a_RelZ) const
void SetBlockType(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType)
Byte Shape[256 *16 *16]
The datatype used to represent the entire chunk worth of shape.
BLOCKTYPE GetBlockType(int a_RelX, int a_RelY, int a_RelZ) const
cChunkCoords GetChunkCoords() const
void UpdateHeightmap(void)
Updates the heightmap to match the current contents.
The interface that all chunk generators must implement to provide the generated chunks.
The interface that a biome generator must implement A biome generator takes chunk coords on input and...
virtual void GenBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap &a_BiomeMap)=0
Generates biomes for the given chunk.
cOctavedNoise< cInterp5DegNoise > m_Perlin
The base 3D noise source for the actual composition.
void ComposeTerrain(cChunkDesc &a_ChunkDesc)
Composes terrain - adds dirt, grass and sand.
NOISE_DATATYPE m_FrequencyZ
void GenerateNoiseArray(cChunkCoords a_ChunkCoords, NOISE_DATATYPE *a_Noise)
Generates the 3D noise array used for terrain generation into a_Noise; a_Noise is of ChunkData-size.
cOctavedNoise< cInterp5DegNoise > m_Cubic
The noise used for heightmap directing.
NOISE_DATATYPE m_FrequencyY
virtual void Initialize(cIniFile &a_IniFile) override
Called to initialize the generator on server startup.
virtual void Generate(cChunkDesc &a_ChunkDesc) override
Does the actual chunk generation.
NOISE_DATATYPE m_MidPoint
static const int UPSCALE_X
virtual void GenerateBiomes(cChunkCoords a_ChunkCoords, cChunkDef::BiomeMap &a_BiomeMap) override
Generates the biomes for the specified chunk.
NOISE_DATATYPE m_FrequencyX
virtual ~cNoise3DGenerator() override
NOISE_DATATYPE m_AirThreshold
NOISE_DATATYPE m_HeightAmplification
static const int UPSCALE_Z
static const int UPSCALE_Y
NOISE_DATATYPE m_ChoiceFrequencyX
NOISE_DATATYPE m_FrequencyY
NOISE_DATATYPE m_ChoiceFrequencyY
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_DensityNoiseA
Density 3D noise, variant A.
NOISE_DATATYPE m_FrequencyZ
NOISE_DATATYPE m_BaseFrequencyX
virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape &a_Shape) override
Generates the shape for the given chunk.
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_BaseNoise
Heightmap-like noise used to provide variance for low-amplitude biomes.
NOISE_DATATYPE m_MidPoint
Where the vertical "center" of the noise should be, as block height.
NOISE_DATATYPE m_NoiseArray[17 *17 *257]
cChunkCoords m_LastChunkCoords
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_DensityNoiseB
Density 3D noise, variant B.
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_ChoiceNoise
The 3D noise that is used to choose between density noise A and B.
NOISE_DATATYPE m_FrequencyX
NOISE_DATATYPE m_HeightAmplification
The main parameter of the generator, specifies the slope of the vertical linear gradient.
NOISE_DATATYPE m_BaseFrequencyZ
NOISE_DATATYPE m_AirThreshold
NOISE_DATATYPE m_ChoiceFrequencyZ
cNoise3DComposable(int a_Seed)
void GenerateNoiseArrayIfNeeded(cChunkCoords a_ChunkCoords)
Generates the 3D noise array used for terrain generation (m_NoiseArray), unless the LastChunk coords ...
void Initialize(cIniFile &a_IniFile)
NOISE_DATATYPE m_ChoiceFrequencyY
NOISE_DATATYPE m_ChoiceFrequencyZ
NOISE_DATATYPE m_Weight[AVERAGING_SIZE *2+1][AVERAGING_SIZE *2+1]
Weights for summing up neighboring biomes.
NOISE_DATATYPE m_NoiseArray[17 *17 *257]
void CalcBiomeParamArrays(cChunkCoords a_ChunkCoords, ChunkParam &a_HeightAmp, ChunkParam &a_MidPoint)
Calculates the biome-related parameters for the chunk.
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_BaseNoise
Heightmap-like noise used to provide variance for low-amplitude biomes.
NOISE_DATATYPE m_WeightSum
The sum of m_Weight[].
void GenerateNoiseArrayIfNeeded(cChunkCoords a_ChunkCoords)
Generates the 3D noise array used for terrain generation (m_NoiseArray), unless the LastChunk coords ...
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_ChoiceNoise
The noise that is used to choose between density noise A and B.
cBiomeGen & m_BiomeGen
The underlying biome generator.
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_DensityNoiseA
Density 3D noise, variant A.
NOISE_DATATYPE m_FrequencyY
NOISE_DATATYPE m_FrequencyX
void Initialize(cIniFile &a_IniFile)
cBiomalNoise3DComposable(int a_Seed, cBiomeGen &a_BiomeGen)
int m_SeaLevel
Block height of the sealevel, used for composing the terrain.
NOISE_DATATYPE m_ChoiceFrequencyX
NOISE_DATATYPE m_AirThreshold
static const int AVERAGING_SIZE
Number of columns around the pixel to query for biomes for averaging.
cChunkCoords m_LastChunkCoords
NOISE_DATATYPE ChunkParam[5 *5]
Type used for a single parameter across the entire (downscaled) chunk.
void GetBiomeParams(EMCSBiome a_Biome, NOISE_DATATYPE &a_HeightAmp, NOISE_DATATYPE &a_MidPoint)
Returns the parameters for the specified biome.
cOctavedNoise< cInterpolNoise< Interp5Deg > > m_DensityNoiseB
Density 3D noise, variant B.
NOISE_DATATYPE m_BaseFrequencyZ
virtual void GenShape(cChunkCoords a_ChunkCoords, cChunkDesc::Shape &a_Shape) override
Generates the shape for the given chunk.
NOISE_DATATYPE m_FrequencyZ
NOISE_DATATYPE m_BaseFrequencyX
int GetValueSetI(const AString &keyname, const AString &valuename, const int defValue=0) override
double GetValueSetF(const AString &keyname, const AString &valuename, const double defValue=0.0)
void Generate3D(NOISE_DATATYPE *a_Array, int a_SizeX, int a_SizeY, int a_SizeZ, NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, NOISE_DATATYPE a_StartZ, NOISE_DATATYPE a_EndZ, NOISE_DATATYPE *a_Workspace=nullptr) const
Fills a 3D array with the values of the noise.
void AddOctave(NOISE_DATATYPE a_Frequency, NOISE_DATATYPE a_Amplitude)
Adds a new octave to the list of octaves that compose this noise.
void Generate2D(NOISE_DATATYPE *a_Array, int a_SizeX, int a_SizeY, NOISE_DATATYPE a_StartX, NOISE_DATATYPE a_EndX, NOISE_DATATYPE a_StartY, NOISE_DATATYPE a_EndY, NOISE_DATATYPE *a_Workspace=nullptr) const
Fills a 2D array with the values of the noise.