mirror of
https://github.com/Cubitect/cubiomes.git
synced 2025-01-07 03:06:38 +08:00
89df24c3be
* 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
317 lines
10 KiB
C
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_ */
|
|
|
|
|
|
|