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;
}
int scanForQuads(const StructureConfig sconf, int64_t s48, int64_t low20,
int x, int z, int w, int h, Pos *qplist, int n)
static inline
int scanForQuadBits(const StructureConfig sconf, int radius, int64_t s48,
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 invB = 132477LL; // = mulInv(132897987541LL, m);
// for lbitn=20: invB = 132477LL;
if (n < 1)
return 0;
@ -687,13 +688,13 @@ int scanForQuads(const StructureConfig sconf, int64_t s48, int64_t low20,
for (i = x; i <= x+w; 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)
j += m;
for (; j <= z+h; j += m)
{
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].z = j;
@ -707,6 +708,26 @@ int scanForQuads(const StructureConfig sconf, int64_t s48, int64_t low20,
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

View File

@ -415,20 +415,25 @@ int searchAll48(
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
* coordiantes. The search is performed for only a specific lower 20-bits of
* the transformed bases (i.e. each call looks for only one constellation of
* quad-structure).
* coordiantes. The search is performed for only a specific set of lower bits
* of the transformed bases (each constellation of quad-structures is
* considered separately).
*
* @sconf : structure config (SWAMP_HUT_CONFIG or FEATURE_CONFIG)
* @s48 : 48-bit seed to scan
* @low20 : only consider transformations that yield these lower bits
* @x,z,w,h : area to scan in region coordinates (inclusive)
* @qplist : output region coordinates for the descovered quad-structures
* @n : maximum number of quad-structures to look for
* @sconf : structure config
* @radius : radius for isQuadBase (use 128 for quad-huts)
* @s48 : 48-bit seed to scan
* @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)
* @qplist : output region coordinates for the descovered quad-structures
* @n : maximum number of quad-structures to look for
*
* 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);
//==============================================================================
@ -442,7 +447,7 @@ int getBiomeAtPos(const LayerStack *g, const Pos pos);
/* Get the shadow seed.
*/
inline int64_t getShadow(int64_t seed)
static inline int64_t getShadow(int64_t seed)
{
return -7379792620528906219LL - seed;
}
@ -1040,11 +1045,9 @@ static inline __attribute__((always_inline, const))
float isQuadBaseLarge(const StructureConfig sconf, int64_t seed,
int ax, int ay, int az, int radius)
{
// Good quad-monument bases are very rare indeed. There are only two seeds
// for a radius below 148 blocks, between seed-bases 0 and 1e13:
// 775379617447 : radius=143.30 (400,384);(384,528);(528,384);(528,528)
// 3752024106001 : radius=145.07 (400,384);(400,560);(544,416);(528,512)
// Good quad-monument bases are very rare indeed and the search takes much
// longer since it cannot be abbreviated by the low-20-bit method. For a
// complete list of bases see the implementation of cubiomes-viewer.
const int64_t M = (1ULL << 48) - 1;
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->edge = 0;
l->getMap = getMap;
l->oceanRnd = NULL;
l->noise = NULL;
l->data = NULL;
}
@ -172,7 +172,7 @@ static void setupGeneratorImpl(LayerStack *g, int mcversion, int largeBiomes)
{
// ocean variants
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_64], &l[L13_ZOOM_128], 2002, 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 *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]
OceanRnd oceanRnd;
PerlinNoise oceanRnd;
};
typedef int (*mapfunc_t)(const Layer *, int *, int, int, int, int);

View File

@ -4,8 +4,6 @@
#include <stdio.h>
static void oceanRndInit(OceanRnd *rnd, int64_t seed);
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)
setWorldSeed(layer->p, worldSeed);
if (layer->oceanRnd != NULL)
oceanRndInit(layer->oceanRnd, worldSeed);
if (layer->noise != NULL)
perlinInit((PerlinNoise*)layer->noise, worldSeed);
int64_t ls = layer->layerSeed;
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)
}
/* 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)
void perlinInit(PerlinNoise *rnd, int64_t seed)
{
int i = 0;
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);
}
@ -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 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;
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;
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 i, j;
OceanRnd *rnd = l->oceanRnd;
const PerlinNoise *rnd = (const PerlinNoise*) l->noise;
for (j = 0; j < h; j++)
{
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)
out[i + j*w] = warm_ocean;

View File

@ -145,19 +145,21 @@ STRUCT(Biome)
int mutated;
};
STRUCT(OceanRnd)
STRUCT(PerlinNoise)
{
int d[512];
double a, b, c;
};
STRUCT(Layer)
{
int64_t layerSeed; // (depends only on layer salt)
int64_t startSalt; // (world seed dependent) = worldGenSeed, used for RND beyond the first
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
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 perlinInit(PerlinNoise *rnd, int64_t seed);
double samplePerlin(const PerlinNoise *rnd, double d1, double d2, double d3);
//==============================================================================
// Static Helpers
//==============================================================================