diff --git a/.gitignore b/.gitignore index 1d48335..80dad2a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ docs/LayerSummary.synctex.gz docs/LayerSummary.toc *.o *.a +a.out diff --git a/layers.c b/layers.c index 3f86070..373e4b0 100644 --- a/layers.c +++ b/layers.c @@ -1152,7 +1152,7 @@ int genEndScaled(const EndNoise *en, int *out, Range r, int mc, uint64_t sha) static int init_climate_seed( DoublePerlinNoise *dpn, PerlinNoise *oct, - uint64_t xlo, uint64_t xhi, int large, int nptype + uint64_t xlo, uint64_t xhi, int large, int nptype, int nmax ) { Xoroshiro pxr; @@ -1161,57 +1161,51 @@ static int init_climate_seed( switch (nptype) { case NP_SHIFT: { - double amp_s[] = {1, 1, 1, 0}; - int len = sizeof(amp_s)/sizeof(double); + static const double amp[] = {1, 1, 1, 0}; // md5 "minecraft:offset" pxr.lo = xlo ^ 0x080518cf6af25384; pxr.hi = xhi ^ 0x3f3dfb40a54febd5; - n += xDoublePerlinInit(dpn, &pxr, oct, amp_s, -3, len); + n += xDoublePerlinInit(dpn, &pxr, oct, amp, -3, 4, nmax); } break; case NP_TEMPERATURE: { - double amp_t[] = {1.5, 0, 1, 0, 0, 0}; - int len = sizeof(amp_t)/sizeof(double); + static const double amp[] = {1.5, 0, 1, 0, 0, 0}; // md5 "minecraft:temperature" or "minecraft:temperature_large" pxr.lo = xlo ^ (large ? 0x944b0073edf549db : 0x5c7e6b29735f0d7f); pxr.hi = xhi ^ (large ? 0x4ff44347e9d22b96 : 0xf7d86f1bbc734988); - n += xDoublePerlinInit(dpn, &pxr, oct, amp_t, large ? -12 : -10, len); + n += xDoublePerlinInit(dpn, &pxr, oct, amp, large ? -12 : -10, 6, nmax); } break; case NP_HUMIDITY: { - double amp_h[] = {1, 1, 0, 0, 0, 0}; - int len = sizeof(amp_h)/sizeof(double); + static const double amp[] = {1, 1, 0, 0, 0, 0}; // md5 "minecraft:vegetation" or "minecraft:vegetation_large" pxr.lo = xlo ^ (large ? 0x71b8ab943dbd5301 : 0x81bb4d22e8dc168e); pxr.hi = xhi ^ (large ? 0xbb63ddcf39ff7a2b : 0xf1c8b4bea16303cd); - n += xDoublePerlinInit(dpn, &pxr, oct, amp_h, large ? -10 : -8, len); + n += xDoublePerlinInit(dpn, &pxr, oct, amp, large ? -10 : -8, 6, nmax); } break; case NP_CONTINENTALNESS: { - double amp_c[] = {1, 1, 2, 2, 2, 1, 1, 1, 1}; - int len = sizeof(amp_c)/sizeof(double); + static const double amp[] = {1, 1, 2, 2, 2, 1, 1, 1, 1}; // md5 "minecraft:continentalness" or "minecraft:continentalness_large" pxr.lo = xlo ^ (large ? 0x9a3f51a113fce8dc : 0x83886c9d0ae3a662); pxr.hi = xhi ^ (large ? 0xee2dbd157e5dcdad : 0xafa638a61b42e8ad); - n += xDoublePerlinInit(dpn, &pxr, oct, amp_c, large ? -11 : -9, len); + n += xDoublePerlinInit(dpn, &pxr, oct, amp, large ? -11 : -9, 9, nmax); } break; case NP_EROSION: { - double amp_e[] = {1, 1, 0, 1, 1}; - int len = sizeof(amp_e)/sizeof(double); + static const double amp[] = {1, 1, 0, 1, 1}; // md5 "minecraft:erosion" or "minecraft:erosion_large" pxr.lo = xlo ^ (large ? 0x8c984b1f8702a951 : 0xd02491e6058f6fd8); pxr.hi = xhi ^ (large ? 0xead7b1f92bae535f : 0x4792512c94c17a80); - n += xDoublePerlinInit(dpn, &pxr, oct, amp_e, large ? -11 : -9, len); + n += xDoublePerlinInit(dpn, &pxr, oct, amp, large ? -11 : -9, 5, nmax); } break; case NP_WEIRDNESS: { - double amp_w[] = {1, 2, 1, 0, 0, 0}; - int len = sizeof(amp_w)/sizeof(double); + static const double amp[] = {1, 2, 1, 0, 0, 0}; // md5 "minecraft:ridge" pxr.lo = xlo ^ 0xefc8ef4d36102b34; pxr.hi = xhi ^ 0x1beeeb324a0f24ea; - n += xDoublePerlinInit(dpn, &pxr, oct, amp_w, -7, len); + n += xDoublePerlinInit(dpn, &pxr, oct, amp, -7, 6, nmax); } break; default: @@ -1230,7 +1224,7 @@ void setBiomeSeed(BiomeNoise *bn, uint64_t seed, int large) int n = 0, i = 0; for (; i < NP_MAX; i++) - n += init_climate_seed(&bn->climate[i], bn->oct+n, xlo, xhi, large, i); + n += init_climate_seed(&bn->climate[i], bn->oct+n, xlo, xhi, large, i, -1); if ((size_t)n > sizeof(bn->oct) / sizeof(*bn->oct)) { @@ -1505,8 +1499,6 @@ int sampleBiomeNoise(const BiomeNoise *bn, int64_t *np, int x, int y, int z, return id; } -// Note: When selecting Temperature and Humidity with bnb->nptype, noise -// varies from 0 to 10000, not -10000 to 10000. // Note: Climate noise exists at a 1:1 scale. 1:4 is obtained by sampling // midpoints. int sampleBiomeNoiseBeta(const BiomeNoiseBeta *bnb, int64_t *np, double *nv, @@ -1515,8 +1507,7 @@ int sampleBiomeNoiseBeta(const BiomeNoiseBeta *bnb, int64_t *np, double *nv, if (bnb->nptype >= 0 && np) memset(np, 0, 2*sizeof(*np)); - double t = 0; // prevent compiler warning - double h, f; + double t, h, f; f = sampleOctaveOldBetaBiome(&bnb->climate[2], x, z) * 1.1 + 0.5; t = (sampleOctaveOldBetaBiome(&bnb->climate[0], x, z) * @@ -1543,7 +1534,7 @@ int sampleBiomeNoiseBeta(const BiomeNoiseBeta *bnb, int64_t *np, double *nv, return getOldBetaBiome((float) t, (float) h); } -void setClimateParaSeed(BiomeNoise *bn, uint64_t seed, int large, int nptype) +void setClimateParaSeed(BiomeNoise *bn, uint64_t seed, int large, int nptype, int nmax) { Xoroshiro pxr; xSetSeed(&pxr, seed); @@ -1553,15 +1544,15 @@ void setClimateParaSeed(BiomeNoise *bn, uint64_t seed, int large, int nptype) { int n = 0; n += init_climate_seed(bn->climate + NP_CONTINENTALNESS, - bn->oct + n, xlo, xhi, large, NP_CONTINENTALNESS); + bn->oct + n, xlo, xhi, large, NP_CONTINENTALNESS, nmax); n += init_climate_seed(bn->climate + NP_EROSION, - bn->oct + n, xlo, xhi, large, NP_EROSION); + bn->oct + n, xlo, xhi, large, NP_EROSION, nmax); n += init_climate_seed(bn->climate + NP_WEIRDNESS, - bn->oct + n, xlo, xhi, large, NP_WEIRDNESS); + bn->oct + n, xlo, xhi, large, NP_WEIRDNESS, nmax); } else { - init_climate_seed(bn->climate + nptype, bn->oct, xlo, xhi, large, nptype); + init_climate_seed(bn->climate + nptype, bn->oct, xlo, xhi, large, nptype, nmax); } bn->nptype = nptype; } @@ -1884,7 +1875,7 @@ int genBetaBiomeNoiseScaled(const BiomeNoiseBeta *bnb, SeaLevelColumnNoiseBeta *buf = (SeaLevelColumnNoiseBeta*) (out + r.sx * r.sy * r.sz); SeaLevelColumnNoiseBeta *colNoise; double colsProcessed[8]; - uint8_t blockSamples[4/scale * 4/scale]; + uint8_t blockSamples[16]; // sufficient buffer for 4x4 at scale 1:1 // Diagonal traversal of range region, in order to minimize size of saved // column noise buffer diff --git a/layers.h b/layers.h index 4004fff..e4721b4 100644 --- a/layers.h +++ b/layers.h @@ -107,7 +107,11 @@ enum BiomeID deep_cold_ocean, coldDeepOcean = deep_cold_ocean, // 50 deep_frozen_ocean, frozenDeepOcean = deep_frozen_ocean, - BIOME_NUM, + // Alpha 1.2 - Beta 1.7 + seasonal_forest, + rainforest, + shrubland, + the_void = 127, @@ -165,10 +169,6 @@ enum BiomeID // 1.19 deep_dark = 183, mangrove_swamp = 184, - // Alpha 1.2 - Beta 1.7 - seasonal_forest = wooded_hills, - rainforest = jungle, - shrubland = windswept_savanna, }; @@ -541,7 +541,7 @@ int p2overworld(int mc, const uint64_t np[6], uint64_t *dat); * If nptype == NP_DEPTH, the value is sampled at y=0. Note that this value * changes linearly with the height (i.e. -= y/128). */ -void setClimateParaSeed(BiomeNoise *bn, uint64_t seed, int large, int nptype); +void setClimateParaSeed(BiomeNoise *bn, uint64_t seed, int large, int nptype, int nmax); double sampleClimatePara(const BiomeNoise *bn, int64_t *np, double x, double z); /** @@ -562,11 +562,7 @@ void genBiomeNoiseChunkSection(const BiomeNoise *bn, int out[4][4][4], * A scale of zero is interpreted as the default 1:4 scale. */ int genBiomeNoiseScaled(const BiomeNoise *bn, int *out, Range r, int mc, uint64_t sha); -void genColumnNoise(const SurfaceNoiseBeta *snb, SeaLevelColumnNoiseBeta *dest, - int cx, int cz); -void processColumnNoise(double *out, SeaLevelColumnNoiseBeta *src, - const BiomeNoiseBeta *bnb, int x, int z, int chunkBorderX, int chunkBorderZ); -void sampleBlocks(double *src, uint8_t *out, int scale); + int sampleBetaBiomeOneBlock(const BiomeNoiseBeta *bnb, const SurfaceNoiseBeta *snb, int x, int z); int genBetaBiomeNoiseScaled(const BiomeNoiseBeta *bnb, const SurfaceNoiseBeta *snb, diff --git a/noise.c b/noise.c index db875b1..503c73c 100644 --- a/noise.c +++ b/noise.c @@ -6,7 +6,7 @@ // grad() -/* +#if 0 static double indexedLerp(int idx, double d1, double d2, double d3) { const double cEdgeX[] = { 1.0,-1.0, 1.0,-1.0, 1.0,-1.0, 1.0,-1.0, @@ -19,8 +19,8 @@ static double indexedLerp(int idx, double d1, double d2, double d3) idx &= 0xf; return cEdgeX[idx] * d1 + cEdgeY[idx] * d2 + cEdgeZ[idx] * d3; } -*/ -ATTR(hot, const, always_inline, artificial) +#else +ATTR(hot, const) static inline double indexedLerp(int idx, double a, double b, double c) { switch (idx & 0xf) @@ -45,6 +45,7 @@ static inline double indexedLerp(int idx, double a, double b, double c) UNREACHABLE(); return 0; } +#endif void perlinInit(PerlinNoise *noise, uint64_t *seed) { @@ -355,9 +356,9 @@ void octaveInitOldBetaTerrain(OctaveNoise *noise, uint64_t *seed, } int xOctaveInit(OctaveNoise *noise, Xoroshiro *xr, PerlinNoise *octaves, - const double *amplitudes, int omin, int len) + const double *amplitudes, int omin, int len, int nmax) { - const uint64_t md5_octave_n[][2] = { + static const uint64_t md5_octave_n[][2] = { {0xb198de63a8012672, 0x7b84cad43ef7b5a8}, // md5 "octave_-12" {0x0fd787bfbc403ec3, 0x74a4a31ca21b48b8}, // md5 "octave_-11" {0x36d326eed40efeb2, 0x5be9ce18223c636a}, // md5 "octave_-10" @@ -372,11 +373,11 @@ int xOctaveInit(OctaveNoise *noise, Xoroshiro *xr, PerlinNoise *octaves, {0xdffa22b534c5f608, 0xb9b67517d3665ca9}, // md5 "octave_-1" {0xd50708086cef4d7c, 0x6e1651ecc7f43309}, // md5 "octave_0" }; - const double lacuna_ini[] = { // -omin = 3..12 + static const double lacuna_ini[] = { // -omin = 3..12 1, .5, .25, 1./8, 1./16, 1./32, 1./64, 1./128, 1./256, 1./512, 1./1024, 1./2048, 1./4096, }; - const double persist_ini[] = { // len = 4..9 + static const double persist_ini[] = { // len = 4..9 0, 1, 2./3, 4./7, 8./15, 16./31, 32./63, 64./127, 128./255, 256./511, }; #if DEBUG @@ -393,7 +394,7 @@ int xOctaveInit(OctaveNoise *noise, Xoroshiro *xr, PerlinNoise *octaves, uint64_t xhi = xNextLong(xr); int i = 0, n = 0; - for (; i < len; i++, lacuna *= 2.0, persist *= 0.5) + for (; i < len && n != nmax; i++, lacuna *= 2.0, persist *= 0.5) { if (amplitudes[i] == 0) continue; @@ -506,29 +507,37 @@ void doublePerlinInit(DoublePerlinNoise *noise, uint64_t *seed, } /** - * Sets up a DoublePerlinNoise generator (MC 1.18). + * Sets up a DoublePerlinNoise generator (MC 1.18+). * @noise: Object to be initialized * @xr: Xoroshiro random object - * @octaves: Octaves buffer, size has to be 2x (No. non-zeros in amplitudes) + * @octaves: Octaves buffer, size has to be 2x (# non-zeros in amplitudes) * @amplitudes: Octave amplitude, needs at least one non-zero * @omin: First octave * @len: Length of amplitudes array + * @nmax: Number of octaves available in buffer (can be <=0 to ignore) * @return Number of octaves used (see octaves buffer size). */ int xDoublePerlinInit(DoublePerlinNoise *noise, Xoroshiro *xr, - PerlinNoise *octaves, const double *amplitudes, - int omin, int len) + PerlinNoise *octaves, const double *amplitudes, int omin, int len, int nmax) { - int i, n = 0; - n += xOctaveInit(&noise->octA, xr, octaves+n, amplitudes, omin, len); - n += xOctaveInit(&noise->octB, xr, octaves+n, amplitudes, omin, len); + int i, n = 0, na = -1, nb = -1; + if (nmax > 0) + { + na = (nmax + 1) >> 1; + nb = nmax - na; + } + n += xOctaveInit(&noise->octA, xr, octaves+n, amplitudes, omin, len, na); + n += xOctaveInit(&noise->octB, xr, octaves+n, amplitudes, omin, len, nb); // trim amplitudes of zero for (i = len-1; i >= 0 && amplitudes[i] == 0.0; i--) len--; for (i = 0; amplitudes[i] == 0.0; i++) len--; - noise->amplitude = (10.0 / 6.0) * len / (len + 1); + static const double amp_ini[] = { // (5 ./ 3) * len / (len + 1), len = 2..9 + 0, 5./6, 10./9, 15./12, 20./15, 25./18, 30./21, 35./24, 40./27, 45./30, + }; + noise->amplitude = amp_ini[len]; return n; } diff --git a/noise.h b/noise.h index 6c6f030..8a11efc 100644 --- a/noise.h +++ b/noise.h @@ -59,7 +59,7 @@ void octaveInitOldBetaBiome(OctaveNoise *noise, uint64_t *seed, void octaveInitOldBetaTerrain(OctaveNoise *noise, uint64_t *seed, PerlinNoise *octaves, int octcnt, double lacBase); int xOctaveInit(OctaveNoise *noise, Xoroshiro *xr, PerlinNoise *octaves, - const double *amplitudes, int omin, int len); + const double *amplitudes, int omin, int len, int nmax); double sampleOctave(const OctaveNoise *noise, double x, double y, double z); double sampleOctaveAmp(const OctaveNoise *noise, double x, double y, double z, @@ -73,7 +73,7 @@ void sampleOctaveOldBetaTerrain3D(const OctaveNoise *noise, double *v, void doublePerlinInit(DoublePerlinNoise *noise, uint64_t *seed, PerlinNoise *octavesA, PerlinNoise *octavesB, int omin, int len); int xDoublePerlinInit(DoublePerlinNoise *noise, Xoroshiro *xr, - PerlinNoise *octaves, const double *amplitudes, int omin, int len); + PerlinNoise *octaves, const double *amplitudes, int omin, int len, int nmax); double sampleDoublePerlin(const DoublePerlinNoise *noise, double x, double y, double z); diff --git a/quadbase.h b/quadbase.h index 22c28f2..ade1a58 100644 --- a/quadbase.h +++ b/quadbase.h @@ -283,9 +283,10 @@ static inline float isQuadBase(const StructureConfig sconf, uint64_t seed, int r return isQuadBaseLarge(sconf, seed, 58, 23, 58, radius); //case Mansion: - //case Ocean_Ruin: - //case Shipwreck: - //case Ruined_Portal: + case Ocean_Ruin: + case Shipwreck: + case Ruined_Portal: + return isQuadBaseFeature(sconf, seed, 0, 0, 0, radius); default: fprintf(stderr, "isQuadBase: not implemented for structure type %d\n", diff --git a/tests.c b/tests.c index b725413..57d5ba9 100644 --- a/tests.c +++ b/tests.c @@ -136,14 +136,14 @@ uint32_t testAreas(int mc, int dim, int scale) double t = -now(); uint32_t hash = 0; uint64_t s; - for (s = 0; s < 100; s++) + for (s = 0; s < 1000; s++) { int d = 40000; int x = hash32(s << 5) % d - d/2; int y = ((int)(hash32(s << 7) % 384) - 64); int z = hash32(s << 9) % d - d/2; - int w = 1 + hash32(s << 11) % 128; w = 128; - int h = 1 + hash32(s << 13) % 128; h = 128; + int w = 1 + hash32(s << 11) % 128; + int h = 1 + hash32(s << 13) % 128; applySeed(&g, dim, s); Range r = {scale, x, z, w, h, y, 1}; @@ -466,8 +466,10 @@ void findStructures(int structureType, int mc, int dim, uint64_t seed, int main() { + //testAreas(MC_1_19, 0, 4); + testAreas(MC_B1_7, 0, 4); //testCanBiomesGenerate(); - testGeneration(); + //testGeneration(); //findBiomeParaBounds(); return 0; } diff --git a/util.c b/util.c index 4d1f032..a08e84d 100644 --- a/util.c +++ b/util.c @@ -127,19 +127,6 @@ const char *biome2str(int mc, int id) case wooded_badlands: return "wooded_badlands"; } } - if (mc <= MC_B1_7) - { - // ids and colors re-used for Alpha 1.2 - Beta 1.7 biomes: - // wooded_hills used for seasonal_forest - // windswept_savanna used for shrubland - // jungle used for rainforest - switch(id) - { - case wooded_hills: return "seasonal_forest"; - case windswept_savanna: return "shrubland"; - case jungle: return "rainforest"; - } - } switch (id) { @@ -199,6 +186,10 @@ const char *biome2str(int mc, int id) case deep_cold_ocean: return "deep_cold_ocean"; // 50 case deep_frozen_ocean: return "deep_frozen_ocean"; + // Alpha 1.2 - Beta 1.7 + case seasonal_forest: return "seasonal_forest"; + case shrubland: return "shrubland"; + case rainforest: return "rainforest"; case the_void: return "the_void"; @@ -327,6 +318,10 @@ void initBiomeColors(unsigned char biomeColors[256][3]) setBiomeColor(biomeColors, deep_cold_ocean, 32, 32, 56); setBiomeColor(biomeColors, deep_frozen_ocean, 64, 64, 144); + setBiomeColor(biomeColors, seasonal_forest, 49, 93, 25); + setBiomeColor(biomeColors, shrubland, 197, 193, 82); + setBiomeColor(biomeColors, rainforest, 71, 132, 14); + setBiomeColor(biomeColors, the_void, 0, 0, 0); setMutationColor(biomeColors, sunflower_plains, plains);