cubiomes/biomenoise.h
Cubitect 89df24c3be Update spawn algorithm for 1.21.2 + cmake + more
* added basic support for cmake (#127)
* renamed Winter Drop version from MC_1_21_3 to MC_1_21_WD
* updated world spawn location for 1.21.2 (cubiomes-viewer #340)
* tweaked mc version to text conversion (#128)
* removed properties field in structure config and added dimension field instead
* moved biome tree selection back to biomenoise.c as it's slightly faster and avoids globals
2024-11-09 21:08:05 +01:00

317 lines
10 KiB
C

#ifndef BIOMENOISE_H_
#define BIOMENOISE_H_
#include "noise.h"
#include "layers.h"
STRUCT(Range)
{
// Defines an area or volume for the biome generation. It is given by a
// position, size and scaling in the horizontal axes, and an optional
// vertical range. The vertical scaling is equal to 1:1 iff scale == 1,
// and 1:4 (default biome scale) in all other cases!
//
// @scale: Horizontal scale factor, should be one of 1, 4, 16, 64, or 256
// additionally a value of zero bypasses scaling and expects a
// manual generation entry layer.
// @x,z: Horizontal position, i.e. coordinates of north-west corner.
// @sx,sz: Horizontal size (width and height for 2D), should be positive.
// @y Vertical position, 1:1 iff scale==1, 1:4 otherwise.
// @sy Vertical size. Values <= 0 are treated equivalent to 1.
//
// Volumes generated with a range are generally indexed as:
// out [ i_y*sx*sz + i_z*sx + i_x ]
// where i_x, i_y, i_z are indecies in their respective directions.
//
// EXAMPLES
// Area at normal biome scale (1:4):
// Range r_2d = {4, x,z, sx,sz};
// (C99 syntax allows ommission of the trailing zero-initialization.)
//
// Area at block scale (1:1) at sea level:
// Range r_surf = {1, x,z, sx,sz, 63};
// (Block level scale uses voronoi sampling with 1:1 vertical scaling.)
//
// Area at chunk scale (1:16) near sea level:
// Range r_surf16 = {16, x,z, sx,sz, 15};
// (Note that the vertical scaling is always 1:4 for non-voronoi scales.)
//
// Volume at scale (1:4):
// Range r_vol = {4, x,z, sx,sz, y,sy};
int scale;
int x, z, sx, sz;
int y, sy;
};
// Nether biome generator 1.16+
STRUCT(NetherNoise)
{ // altitude and wierdness don't affect nether biomes
// and the weight is a 5th noise parameter which is constant
DoublePerlinNoise temperature;
DoublePerlinNoise humidity;
PerlinNoise oct[8]; // buffer for octaves in double perlin noise
};
// End biome generator 1.9+
STRUCT(EndNoise)
{
PerlinNoise perlin;
int mc;
};
STRUCT(SurfaceNoise)
{
double xzScale, yScale;
double xzFactor, yFactor;
OctaveNoise octmin;
OctaveNoise octmax;
OctaveNoise octmain;
OctaveNoise octsurf;
OctaveNoise octdepth;
PerlinNoise oct[16+16+8+4+16];
};
STRUCT(SurfaceNoiseBeta)
{
OctaveNoise octmin;
OctaveNoise octmax;
OctaveNoise octmain;
OctaveNoise octcontA;
OctaveNoise octcontB;
PerlinNoise oct[16+16+8+10+16];
};
STRUCT(SeaLevelColumnNoiseBeta)
{
double contASample;
double contBSample;
double minSample[2];
double maxSample[2];
double mainSample[2];
};
STRUCT(Spline)
{
int len, typ;
float loc[12];
float der[12];
Spline *val[12];
};
STRUCT(FixSpline)
{
int len;
float val;
};
STRUCT(SplineStack)
{ // the stack size here is just sufficient for overworld generation
Spline stack[42];
FixSpline fstack[151];
int len, flen;
};
enum
{
NP_TEMPERATURE = 0,
NP_HUMIDITY = 1,
NP_CONTINENTALNESS = 2,
NP_EROSION = 3,
NP_SHIFT = 4, NP_DEPTH = NP_SHIFT, // not a real climate
NP_WEIRDNESS = 5,
NP_MAX
};
// Overworld biome generator for 1.18+
STRUCT(BiomeNoise)
{
DoublePerlinNoise climate[NP_MAX];
PerlinNoise oct[2*23]; // buffer for octaves in double perlin noise
Spline *sp;
SplineStack ss;
int nptype;
int mc;
};
// Overworld biome generator for pre-Beta 1.8
STRUCT(BiomeNoiseBeta)
{
OctaveNoise climate[3];
PerlinNoise oct[10];
int nptype;
int mc;
};
STRUCT(BiomeTree)
{
const uint32_t *steps;
const int32_t *param;
const uint64_t *nodes;
uint32_t order;
uint32_t len;
};
#ifdef __cplusplus
extern "C"
{
#endif
//==============================================================================
// Noise
//==============================================================================
void initSurfaceNoise(SurfaceNoise *sn, int dim, uint64_t seed);
void initSurfaceNoiseBeta(SurfaceNoiseBeta *snb, uint64_t seed);
double sampleSurfaceNoise(const SurfaceNoise *sn, int x, int y, int z);
double sampleSurfaceNoiseBetween(const SurfaceNoise *sn, int x, int y, int z,
double noiseMin, double noiseMax);
//==============================================================================
// End (1.9+), Nether (1.16+) and Overworld (1.18+) Biome Noise Generation
//==============================================================================
/**
* Nether biomes are 3D, and generated at scale 1:4. Use voronoiAccess3D() to
* convert coordinates at 1:1 scale to their 1:4 access. Biome checks for
* structures are generally done at y=0.
*
* The function getNetherBiome() determines the nether biome at a given
* coordinate at scale 1:4. The parameter 'ndel' is an output noise delta for
* optimization purposes and can be ignored (nullable).
*
* Use mapNether2D() to get a 2D area of nether biomes at y=0, scale 1:4.
*
* The mapNether3D() function attempts to optimize the generation of a volume
* at scale 1:4. The output is indexed as:
* out[i_y*(r.sx*r.sz) + i_z*r.sx + i_x].
* If the optimization parameter 'confidence' has a value less than 1.0, the
* generation will generally be faster, but can yield incorrect results in some
* circumstances.
*
* The output buffer for the map-functions need only be of sufficient size to
* hold the generated area (i.e. w*h or r.sx*r.sy*r.sz).
*/
void setNetherSeed(NetherNoise *nn, uint64_t seed);
int getNetherBiome(const NetherNoise *nn, int x, int y, int z, float *ndel);
int mapNether2D(const NetherNoise *nn, int *out, int x, int z, int w, int h);
int mapNether3D(const NetherNoise *nn, int *out, Range r, float confidence);
/**
* The scaled Nether generation supports scales 1, 4, 16, 64, and 256.
* It is similar to mapNether3D(), but applies voronoi zoom if necessary, and
* fills the output buffer with nether_wastes for versions older than 1.16.
*/
int genNetherScaled(const NetherNoise *nn, int *out, Range r, int mc, uint64_t sha);
/**
* End biome generation is based on simplex noise and varies only at a 1:16
* chunk scale which can be generated with mapEndBiome(). The function mapEnd()
* is a variation which also scales this up on a regular grid to 1:4. The final
* access at a 1:1 scale uses voronoi.
*/
void setEndSeed(EndNoise *en, int mc, uint64_t seed);
int mapEndBiome(const EndNoise *en, int *out, int x, int z, int w, int h);
int mapEnd(const EndNoise *en, int *out, int x, int z, int w, int h);
int getEndSurfaceHeight(int mc, uint64_t seed, int x, int z);
int mapEndSurfaceHeight(float *y, const EndNoise *en, const SurfaceNoise *sn,
int x, int z, int w, int h, int scale, int ymin);
/**
* The scaled End generation supports scales 1, 4, 16, and 64.
* The End biomes are usually 2D, but in 1.15+ there is 3D voronoi noise, which
* is controlled by the 'sha' hash of the seed. For scales higher than 1:1, and
* versions up to 1.14, 'sha' is ignored.
*/
int genEndScaled(const EndNoise *en, int *out, Range r, int mc, uint64_t sha);
/**
* In 1.18 the Overworld uses a new noise map system for the biome generation.
* The random number generation also has updated to a Xiroshiro128 algorithm.
* The scale is 1:4, and is sampled at each point individually as there is
* currently not much benefit from generating a volume as a whole.
*
* The 1.18 End generation remains similar to 1.17 and does NOT use the
* biome noise.
*/
enum {
SAMPLE_NO_SHIFT = 0x1, // skip local distortions
SAMPLE_NO_DEPTH = 0x2, // skip depth sampling for vertical biomes
SAMPLE_NO_BIOME = 0x4, // do not apply climate noise to biome mapping
};
void initBiomeNoise(BiomeNoise *bn, int mc);
void setBiomeSeed(BiomeNoise *bn, uint64_t seed, int large);
void setBetaBiomeSeed(BiomeNoiseBeta *bnb, uint64_t seed);
int sampleBiomeNoise(const BiomeNoise *bn, int64_t *np, int x, int y, int z,
uint64_t *dat, uint32_t sample_flags);
int sampleBiomeNoiseBeta(const BiomeNoiseBeta *bnb, int64_t *np, double *nv,
int x, int z);
double approxSurfaceBeta(const BiomeNoiseBeta *bnb, const SurfaceNoiseBeta *snb,
int x, int z); // doesn't really work yet
/**
* (Alpha 1.2 - Beta 1.7)
* Temperature and humidity values to biome.
*/
int getOldBetaBiome(float t, float h);
/**
* Uses the global biome tree definitions (see tables/btreeXX.h)
* to map a noise point (i.e. climate) to the corresponding overworld biome.
*/
int climateToBiome(int mc, const uint64_t np[6], uint64_t *dat);
/**
* Initialize BiomeNoise for only a single climate parameter.
* If nptype == NP_DEPTH, the value is sampled at y=0. Note that this value
* changes linearly with the height (i.e. -= y/128).
* A maximum of nmax octaves is set, initializing only the most contributing
* octaves up to that point. Use -1 for a full initialization.
*/
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);
/**
* Currently, in 1.18, we have to generate biomes one chunk at a time to get an
* accurate mapping of the biomes in the level storage, as there is no longer a
* unique mapping from noise points to biomes (MC-241546). Note that the results
* from this are not suitable for chunk population/structure generation.
* The output is in the form out[x][y][z] for the 64 biome points in the chunk
* section. The coordinates {cx,cy,cz} are all at scale 1:16 and the 'dat'
* argument should be the previous noise sampling and can be left NULL.
*/
void genBiomeNoiseChunkSection(const BiomeNoise *bn, int out[4][4][4],
int cx, int cy, int cz, uint64_t *dat);
/**
* The scaled biome noise generation applies for the Overworld version 1.18+.
* The 'sha' hash of the seed is only required for voronoi at scale 1:1.
* A scale of zero is interpreted as the default 1:4 scale.
*/
int genBiomeNoiseScaled(const BiomeNoise *bn, int *out, Range r, uint64_t sha);
/**
* Generates the biomes for Beta 1.7, the surface noise is optional and enables
* ocean mapping in areas that fall below the sea level.
*/
int genBiomeNoiseBetaScaled(const BiomeNoiseBeta *bnb, const SurfaceNoiseBeta *snb,
int *out, Range r);
int getBiomeDepthAndScale(int id, double *depth, double *scale, int *grass);
// Gets the range in the parent/source layer which may be accessed by voronoi.
Range getVoronoiSrcRange(Range r);
#ifdef __cplusplus
}
#endif
#endif /* BIOMENOISE_H_ */