Ocean RNG to perlin noise + scanForQuads scan whole set.

1) specify that ocean RNG is perlin noise (nether biomes will use double-perlin & simplex)
2) scanForQuads now scans a whole set of lower bits
This commit is contained in:
Cubitect 2021-01-25 20:01:37 +01:00
parent c8af11082a
commit dd7e61999b
6 changed files with 65 additions and 42 deletions

View File

@ -672,13 +672,14 @@ L_ERR:
return err; return err;
} }
static inline
int scanForQuads(const StructureConfig sconf, int64_t s48, int64_t low20, int scanForQuadBits(const StructureConfig sconf, int radius, int64_t s48,
int x, int z, int w, int h, Pos *qplist, int n) int64_t lbit, int lbitn, int64_t invB, int x, int z, int w, int h,
Pos *qplist, int n)
{ {
const int m = (1LL << 20); const int m = (1LL << lbitn);
const int64_t A = 341873128712LL; const int64_t A = 341873128712LL;
const int64_t invB = 132477LL; // = mulInv(132897987541LL, m); // for lbitn=20: invB = 132477LL;
if (n < 1) if (n < 1)
return 0; return 0;
@ -687,13 +688,13 @@ int scanForQuads(const StructureConfig sconf, int64_t s48, int64_t low20,
for (i = x; i <= x+w; i++) for (i = x; i <= x+w; i++)
{ {
int64_t sx = s48 + A * i; int64_t sx = s48 + A * i;
j = (z & ~(m-1)) | ((low20 - sx) * invB & (m-1)); j = (z & ~(m-1)) | ((lbit - sx) * invB & (m-1));
if (j < z) if (j < z)
j += m; j += m;
for (; j <= z+h; j += m) for (; j <= z+h; j += m)
{ {
int64_t sp = moveStructure(s48, -i, -j); int64_t sp = moveStructure(s48, -i, -j);
if (isQuadBase(sconf, sp - sconf.salt, 128)) if (isQuadBase(sconf, sp - sconf.salt, radius))
{ {
qplist[cnt].x = i; qplist[cnt].x = i;
qplist[cnt].z = j; qplist[cnt].z = j;
@ -707,6 +708,26 @@ int scanForQuads(const StructureConfig sconf, int64_t s48, int64_t low20,
return cnt; return cnt;
} }
int scanForQuads(
const StructureConfig sconf, int radius, int64_t s48,
const int64_t *lowBits, int lowBitCnt, int lowBitN,
int x, int z, int w, int h, Pos *qplist, int n)
{
int i, cnt = 0;
const int64_t invB = mulInv(132897987541LL, (1LL << lowBitN));
for (i = 0; i < lowBitCnt; i++)
{
cnt += scanForQuadBits(sconf, radius, s48, lowBits[i], lowBitN, invB,
x, z, w, h, qplist+cnt, n-cnt);
if (cnt >= n)
break;
}
return cnt;
}
//============================================================================== //==============================================================================
// Checking Biomes & Biome Helper Functions // Checking Biomes & Biome Helper Functions

View File

@ -415,20 +415,25 @@ int searchAll48(
Pos getOptimalAfk(Pos p[4], int ax, int ay, int az, int *spcnt); Pos getOptimalAfk(Pos p[4], int ax, int ay, int az, int *spcnt);
/* Scans the seed 's48' for quad-structures in the given area of region /* Scans the seed 's48' for quad-structures in the given area of region
* coordiantes. The search is performed for only a specific lower 20-bits of * coordiantes. The search is performed for only a specific set of lower bits
* the transformed bases (i.e. each call looks for only one constellation of * of the transformed bases (each constellation of quad-structures is
* quad-structure). * considered separately).
* *
* @sconf : structure config (SWAMP_HUT_CONFIG or FEATURE_CONFIG) * @sconf : structure config
* @radius : radius for isQuadBase (use 128 for quad-huts)
* @s48 : 48-bit seed to scan * @s48 : 48-bit seed to scan
* @low20 : only consider transformations that yield these lower bits * @lowBits : consider transformations that yield one of these lower bits
* @lowBitCnt : length of lower bit subset
* @lowBitN : number of bits in the subset values (0 < lowBitN <= 48)
* @x,z,w,h : area to scan in region coordinates (inclusive) * @x,z,w,h : area to scan in region coordinates (inclusive)
* @qplist : output region coordinates for the descovered quad-structures * @qplist : output region coordinates for the descovered quad-structures
* @n : maximum number of quad-structures to look for * @n : maximum number of quad-structures to look for
* *
* Returns the number of quad-structures found (up to 'n'). * Returns the number of quad-structures found (up to 'n').
*/ */
int scanForQuads(const StructureConfig sconf, int64_t s48, int64_t low20, int scanForQuads(
const StructureConfig sconf, int radius, int64_t s48,
const int64_t *lowBits, int lowBitCnt, int lowBitN,
int x, int z, int w, int h, Pos *qplist, int n); int x, int z, int w, int h, Pos *qplist, int n);
//============================================================================== //==============================================================================
@ -442,7 +447,7 @@ int getBiomeAtPos(const LayerStack *g, const Pos pos);
/* Get the shadow seed. /* Get the shadow seed.
*/ */
inline int64_t getShadow(int64_t seed) static inline int64_t getShadow(int64_t seed)
{ {
return -7379792620528906219LL - seed; return -7379792620528906219LL - seed;
} }
@ -1040,11 +1045,9 @@ static inline __attribute__((always_inline, const))
float isQuadBaseLarge(const StructureConfig sconf, int64_t seed, float isQuadBaseLarge(const StructureConfig sconf, int64_t seed,
int ax, int ay, int az, int radius) int ax, int ay, int az, int radius)
{ {
// Good quad-monument bases are very rare indeed. There are only two seeds // Good quad-monument bases are very rare indeed and the search takes much
// for a radius below 148 blocks, between seed-bases 0 and 1e13: // longer since it cannot be abbreviated by the low-20-bit method. For a
// 775379617447 : radius=143.30 (400,384);(384,528);(528,384);(528,528) // complete list of bases see the implementation of cubiomes-viewer.
// 3752024106001 : radius=145.07 (400,384);(400,560);(544,416);(528,512)
const int64_t M = (1ULL << 48) - 1; const int64_t M = (1ULL << 48) - 1;
const int64_t K = 0x5deece66dLL; const int64_t K = 0x5deece66dLL;

View File

@ -17,7 +17,7 @@ void setupLayer(Layer *l, Layer *p, int s, mapfunc_t getMap)
l->scale = 0; l->scale = 0;
l->edge = 0; l->edge = 0;
l->getMap = getMap; l->getMap = getMap;
l->oceanRnd = NULL; l->noise = NULL;
l->data = NULL; l->data = NULL;
} }
@ -172,7 +172,7 @@ static void setupGeneratorImpl(LayerStack *g, int mcversion, int largeBiomes)
{ {
// ocean variants // ocean variants
setupLayer(&l[L13_OCEAN_TEMP_256], NULL, 2, mapOceanTemp); setupLayer(&l[L13_OCEAN_TEMP_256], NULL, 2, mapOceanTemp);
l[L13_OCEAN_TEMP_256].oceanRnd = &g->oceanRnd; l[L13_OCEAN_TEMP_256].noise = &g->oceanRnd;
setupLayer(&l[L13_ZOOM_128], &l[L13_OCEAN_TEMP_256], 2001, mapZoom); setupLayer(&l[L13_ZOOM_128], &l[L13_OCEAN_TEMP_256], 2001, mapZoom);
setupLayer(&l[L13_ZOOM_64], &l[L13_ZOOM_128], 2002, mapZoom); setupLayer(&l[L13_ZOOM_64], &l[L13_ZOOM_128], 2002, mapZoom);
setupLayer(&l[L13_ZOOM_32], &l[L13_ZOOM_64], 2003, mapZoom); setupLayer(&l[L13_ZOOM_32], &l[L13_ZOOM_64], 2003, mapZoom);

View File

@ -85,7 +85,7 @@ STRUCT(LayerStack)
Layer layers[L_NUM]; Layer layers[L_NUM];
Layer *entry_1; // entry layer, scale (1:1) [L_VORONOI_ZOOM_1] Layer *entry_1; // entry layer, scale (1:1) [L_VORONOI_ZOOM_1]
Layer *entry_4; // entry layer, scale (1:4) [L_RIVER_MIX_4|L13_OCEAN_MIX_4] Layer *entry_4; // entry layer, scale (1:4) [L_RIVER_MIX_4|L13_OCEAN_MIX_4]
OceanRnd oceanRnd; PerlinNoise oceanRnd;
}; };
typedef int (*mapfunc_t)(const Layer *, int *, int, int, int, int); typedef int (*mapfunc_t)(const Layer *, int *, int, int, int, int);

View File

@ -4,8 +4,6 @@
#include <stdio.h> #include <stdio.h>
static void oceanRndInit(OceanRnd *rnd, int64_t seed);
void initAddBiome(int id, int tempCat, int biometype, float temp, float height) void initAddBiome(int id, int tempCat, int biometype, float temp, float height)
{ {
@ -137,8 +135,8 @@ void setWorldSeed(Layer *layer, int64_t worldSeed)
if (layer->p != NULL) if (layer->p != NULL)
setWorldSeed(layer->p, worldSeed); setWorldSeed(layer->p, worldSeed);
if (layer->oceanRnd != NULL) if (layer->noise != NULL)
oceanRndInit(layer->oceanRnd, worldSeed); perlinInit((PerlinNoise*)layer->noise, worldSeed);
int64_t ls = layer->layerSeed; int64_t ls = layer->layerSeed;
if (ls != 0) // Pre 1.13 the Hills branch stays zero-initialized if (ls != 0) // Pre 1.13 the Hills branch stays zero-initialized
@ -1616,11 +1614,7 @@ int mapRiverMix(const Layer * l, int * out, int x, int z, int w, int h)
} }
void perlinInit(PerlinNoise *rnd, int64_t seed)
/* Initialises data for the ocean temperature types using the world seed.
* This function is called when the world seed is applied in setWorldSeed().
*/
static void oceanRndInit(OceanRnd *rnd, int64_t seed)
{ {
int i = 0; int i = 0;
memset(rnd, 0, sizeof(*rnd)); memset(rnd, 0, sizeof(*rnd));
@ -1643,7 +1637,7 @@ static void oceanRndInit(OceanRnd *rnd, int64_t seed)
} }
} }
static double lerp(const double part, const double from, const double to) static double lerp(double part, double from, double to)
{ {
return from + part * (to - from); return from + part * (to - from);
} }
@ -1653,14 +1647,14 @@ const double cEdgeX[] = {1.0,-1.0, 1.0,-1.0, 1.0,-1.0, 1.0,-1.0, 0.0, 0.0, 0.0,
const double cEdgeY[] = {1.0, 1.0,-1.0,-1.0, 0.0, 0.0, 0.0, 0.0, 1.0,-1.0, 1.0,-1.0, 1.0,-1.0, 1.0,-1.0}; const double cEdgeY[] = {1.0, 1.0,-1.0,-1.0, 0.0, 0.0, 0.0, 0.0, 1.0,-1.0, 1.0,-1.0, 1.0,-1.0, 1.0,-1.0};
const double cEdgeZ[] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0,-1.0,-1.0, 1.0, 1.0,-1.0,-1.0, 0.0, 1.0, 0.0,-1.0}; const double cEdgeZ[] = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0,-1.0,-1.0, 1.0, 1.0,-1.0,-1.0, 0.0, 1.0, 0.0,-1.0};
static double indexedLerp(int idx, const double d1, const double d2, const double d3) static double indexedLerp(int idx, double d1, double d2, double d3)
{ {
idx &= 0xf; idx &= 0xf;
return cEdgeX[idx] * d1 + cEdgeY[idx] * d2 + cEdgeZ[idx] * d3; return cEdgeX[idx] * d1 + cEdgeY[idx] * d2 + cEdgeZ[idx] * d3;
} }
static double getOceanTemp(const OceanRnd *rnd, double d1, double d2, double d3) double samplePerlin(const PerlinNoise *rnd, double d1, double d2, double d3)
{ {
d1 += rnd->a; d1 += rnd->a;
d2 += rnd->b; d2 += rnd->b;
@ -1709,13 +1703,13 @@ static double getOceanTemp(const OceanRnd *rnd, double d1, double d2, double d3)
int mapOceanTemp(const Layer * l, int * out, int x, int z, int w, int h) int mapOceanTemp(const Layer * l, int * out, int x, int z, int w, int h)
{ {
int i, j; int i, j;
OceanRnd *rnd = l->oceanRnd; const PerlinNoise *rnd = (const PerlinNoise*) l->noise;
for (j = 0; j < h; j++) for (j = 0; j < h; j++)
{ {
for (i = 0; i < w; i++) for (i = 0; i < w; i++)
{ {
double tmp = getOceanTemp(rnd, (i + x) / 8.0, (j + z) / 8.0, 0); double tmp = samplePerlin(rnd, (i + x) / 8.0, (j + z) / 8.0, 0);
if (tmp > 0.4) if (tmp > 0.4)
out[i + j*w] = warm_ocean; out[i + j*w] = warm_ocean;

View File

@ -145,19 +145,21 @@ STRUCT(Biome)
int mutated; int mutated;
}; };
STRUCT(OceanRnd)
STRUCT(PerlinNoise)
{ {
int d[512]; int d[512];
double a, b, c; double a, b, c;
}; };
STRUCT(Layer) STRUCT(Layer)
{ {
int64_t layerSeed; // (depends only on layer salt) int64_t layerSeed; // (depends only on layer salt)
int64_t startSalt; // (world seed dependent) = worldGenSeed, used for RND beyond the first int64_t startSalt; // (world seed dependent) = worldGenSeed, used for RND beyond the first
int64_t startSeed; // (world seed dependent) starting point for chunk seeds int64_t startSeed; // (world seed dependent) starting point for chunk seeds
OceanRnd *oceanRnd; // world seed dependent data for ocean temperatures void *noise; // seed dependent data for noise maps
void *data; // generic data for custom layers void *data; // generic data for custom layers
int scale; // map scale of this layer (map entry = scale x scale blocks) int scale; // map scale of this layer (map entry = scale x scale blocks)
@ -187,6 +189,9 @@ void initBiomes();
void setWorldSeed(Layer *layer, int64_t worldSeed); void setWorldSeed(Layer *layer, int64_t worldSeed);
void perlinInit(PerlinNoise *rnd, int64_t seed);
double samplePerlin(const PerlinNoise *rnd, double d1, double d2, double d3);
//============================================================================== //==============================================================================
// Static Helpers // Static Helpers
//============================================================================== //==============================================================================