cubiomes/generator.c

774 lines
27 KiB
C
Raw Permalink Normal View History

2018-03-06 05:20:54 +08:00
#include "generator.h"
#include "layers.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
2018-03-06 05:20:54 +08:00
int mapOceanMixMod(const Layer * l, int * out, int x, int z, int w, int h)
{
int *otyp;
int64_t i, j;
l->p2->getMap(l->p2, out, x, z, w, h);
otyp = (int *) malloc(w*h*sizeof(int));
memcpy(otyp, out, w*h*sizeof(int));
l->p->getMap(l->p, out, x, z, w, h);
for (j = 0; j < h; j++)
{
for (i = 0; i < w; i++)
{
int landID, oceanID;
landID = out[j*w + i];
if (!isOceanic(landID))
continue;
oceanID = otyp[j*w + i];
if (landID == deep_ocean)
{
switch (oceanID)
{
case lukewarm_ocean:
oceanID = deep_lukewarm_ocean;
break;
case ocean:
oceanID = deep_ocean;
break;
case cold_ocean:
oceanID = deep_cold_ocean;
break;
case frozen_ocean:
oceanID = deep_frozen_ocean;
break;
}
}
out[j*w + i] = oceanID;
}
}
free(otyp);
return 0;
}
void setupGenerator(Generator *g, int mc, uint32_t flags)
{
g->mc = mc;
2022-08-15 00:00:23 +08:00
g->dim = DIM_UNDEF;
g->flags = flags;
g->seed = 0;
g->sha = 0;
Added Beta climate biome generation (no ocean gen yet) (biome_tree.c) - getOldBetaBiome: removed isWater argument. (finders.c) - getStructureConfig: now returns 0 for mineshafts and villages before B1.8. (layers.h) - Added SurfaceNoiseBeta struct: Very similar to SurfaceNoise. Since SurfaceNoiseBeta will only ever be used for the Overworld, the double values saved in SurfaceNoise will be hardcoded into the SurfaceNoiseBeta sampling function. octSurf and octDepth in surfaceNoise are replaced with new octA and octB OctaveNoises, used for precise terrain generation. These names are subject to change if I come up with more meaningful names in the future. The oct array contains six additional PerlinNoise structs compared to SurfaceNoise, as the 4-octave octSurf is replaced with the 10-octave octA. - Added BiomeNoiseBeta struct: Mostly a cut-down version of BiomeNoise. The climate array contains three OctaveNoise structs, corresponding to the 4-octave temperature and humidity noise generators, as well as an additional 2-octave generator that I'm calling "fuzz". The fuzz noise is high-frequency and low-amplitude, and is used as a factor applied to the raw output of both the temperature and humidity generators before these values are used. The PerlinNoise array oct contains 10 octaves -- 4 for temperature, 4 for humidity, and 2 for fuzz. nptype and mc are carried over from BiomeNoise. mc currently has no purpose, but I've heard of a bug in some early beta versions causing chunk biomes to generate rotated, so storing the version may eventually prove useful. - Added headers for 5 new functions in layers.c. - Changed header for getOldBetaBiome (defined in biome_tree.c) to reflect new signature. (layers.c) - Added initSurfaceNoiseBeta function: No-op placeholder for now. - Added setBetaBiomeSeed function: Initializes the three climate simplex noise generators and sets bnb->nptype to -1 by default. - Added sampleBiomeNoiseBeta function: sampleBiomeNoiseBeta samples climate noise at the given x and z coordinates (1:1 scale) and returns a biome ID corresponding to the biome at the generated temperature and humidity noise values. The behavior of zeroing out the array np when it is passed is copied from sampleBiomeNoise. I'm not sure about its function, so if it's not applicable, this argument and associated behavior can be removed. If bnb->nptype is set to NP_TEMPERATURE or NP_HUMIDITY, only that noise value is generated and the other is ignored. The noise value is multiplied by 10000 and returned as a signed long to match the behavior of sampleBiomeNoise. Note that Beta climate values range from 0 to 1, not -1 to 1, so the resulting ints will all be nonnegative. The argument nv (noise values) is a pointer to a 2-element array of doubles. If it is present, the noise values are placed in the array before the biome is determined. - Added genBetaBiomeNoiseScaled function: At 1:1 scale, every block in Range r is sampled and the return value of sampleBiomeNoiseBeta is placed in the cache. At higher scales, midpoints are sampled. When ocean support is added, this function will likely behave differently when NO_BETA_OCEAN is clear in order to maximize time and memory efficiency. (generator.h) - Flags enum: Bit 1 (0x2) is now the NO_BETA_OCEAN flag. - Generator struct: New union member for pre-B1.8: Includes BiomeNoiseBeta and SurfaceNoiseBeta structs now defined in layers.h (generator.c) - setupGenearator: New version so pre-B1.8 versions behave correctly. For mc <= MC_B1_7, setupGenerator simply sets g->bnb.mc, as all other setup for pre-B1.8 biome generation requires the seed to be known. - applySeed: When mc <= MC_B1_7, the new setBetaBiomeSeed function defined in layers.c is called. If the NO_BETA_OCEAN flag is not set, initSurfaceNoiseBeta is also called. initSurfaceNoiseBeta is currently just a no-op placeholder. - getMinCacheSize: New version check. Returns default size when mc <= MC_B1_7. Will likely be modified when ocean-finding functionality is added. - genBiomes: Calls genBetaBiomeNoiseScaled when mc <= MC_B1_7 Note: Compiling libcubiomes.a will will currently cause several warnings due to unused parameters related to not-yet-implemented ocean finding.
2023-01-24 05:51:54 +08:00
if (mc >= MC_B1_8 && mc <= MC_1_17)
{
setupLayerStack(&g->ls, mc, flags & LARGE_BIOMES);
g->entry = NULL;
if (flags & FORCE_OCEAN_VARIANTS && mc >= MC_1_13)
{
g->ls.entry_16 = setupLayer(
g->xlayer+2, &mapOceanMixMod, mc, 1, 0, 0,
g->ls.entry_16, &g->ls.layers[L_ZOOM_16_OCEAN]);
g->ls.entry_64 = setupLayer(
g->xlayer+3, &mapOceanMixMod, mc, 1, 0, 0,
g->ls.entry_64, &g->ls.layers[L_ZOOM_64_OCEAN]);
g->ls.entry_256 = setupLayer(
g->xlayer+4, &mapOceanMixMod, mc, 1, 0, 0,
g->ls.entry_256, &g->ls.layers[L_OCEAN_TEMP_256]);
}
}
Added Beta climate biome generation (no ocean gen yet) (biome_tree.c) - getOldBetaBiome: removed isWater argument. (finders.c) - getStructureConfig: now returns 0 for mineshafts and villages before B1.8. (layers.h) - Added SurfaceNoiseBeta struct: Very similar to SurfaceNoise. Since SurfaceNoiseBeta will only ever be used for the Overworld, the double values saved in SurfaceNoise will be hardcoded into the SurfaceNoiseBeta sampling function. octSurf and octDepth in surfaceNoise are replaced with new octA and octB OctaveNoises, used for precise terrain generation. These names are subject to change if I come up with more meaningful names in the future. The oct array contains six additional PerlinNoise structs compared to SurfaceNoise, as the 4-octave octSurf is replaced with the 10-octave octA. - Added BiomeNoiseBeta struct: Mostly a cut-down version of BiomeNoise. The climate array contains three OctaveNoise structs, corresponding to the 4-octave temperature and humidity noise generators, as well as an additional 2-octave generator that I'm calling "fuzz". The fuzz noise is high-frequency and low-amplitude, and is used as a factor applied to the raw output of both the temperature and humidity generators before these values are used. The PerlinNoise array oct contains 10 octaves -- 4 for temperature, 4 for humidity, and 2 for fuzz. nptype and mc are carried over from BiomeNoise. mc currently has no purpose, but I've heard of a bug in some early beta versions causing chunk biomes to generate rotated, so storing the version may eventually prove useful. - Added headers for 5 new functions in layers.c. - Changed header for getOldBetaBiome (defined in biome_tree.c) to reflect new signature. (layers.c) - Added initSurfaceNoiseBeta function: No-op placeholder for now. - Added setBetaBiomeSeed function: Initializes the three climate simplex noise generators and sets bnb->nptype to -1 by default. - Added sampleBiomeNoiseBeta function: sampleBiomeNoiseBeta samples climate noise at the given x and z coordinates (1:1 scale) and returns a biome ID corresponding to the biome at the generated temperature and humidity noise values. The behavior of zeroing out the array np when it is passed is copied from sampleBiomeNoise. I'm not sure about its function, so if it's not applicable, this argument and associated behavior can be removed. If bnb->nptype is set to NP_TEMPERATURE or NP_HUMIDITY, only that noise value is generated and the other is ignored. The noise value is multiplied by 10000 and returned as a signed long to match the behavior of sampleBiomeNoise. Note that Beta climate values range from 0 to 1, not -1 to 1, so the resulting ints will all be nonnegative. The argument nv (noise values) is a pointer to a 2-element array of doubles. If it is present, the noise values are placed in the array before the biome is determined. - Added genBetaBiomeNoiseScaled function: At 1:1 scale, every block in Range r is sampled and the return value of sampleBiomeNoiseBeta is placed in the cache. At higher scales, midpoints are sampled. When ocean support is added, this function will likely behave differently when NO_BETA_OCEAN is clear in order to maximize time and memory efficiency. (generator.h) - Flags enum: Bit 1 (0x2) is now the NO_BETA_OCEAN flag. - Generator struct: New union member for pre-B1.8: Includes BiomeNoiseBeta and SurfaceNoiseBeta structs now defined in layers.h (generator.c) - setupGenearator: New version so pre-B1.8 versions behave correctly. For mc <= MC_B1_7, setupGenerator simply sets g->bnb.mc, as all other setup for pre-B1.8 biome generation requires the seed to be known. - applySeed: When mc <= MC_B1_7, the new setBetaBiomeSeed function defined in layers.c is called. If the NO_BETA_OCEAN flag is not set, initSurfaceNoiseBeta is also called. initSurfaceNoiseBeta is currently just a no-op placeholder. - getMinCacheSize: New version check. Returns default size when mc <= MC_B1_7. Will likely be modified when ocean-finding functionality is added. - genBiomes: Calls genBetaBiomeNoiseScaled when mc <= MC_B1_7 Note: Compiling libcubiomes.a will will currently cause several warnings due to unused parameters related to not-yet-implemented ocean finding.
2023-01-24 05:51:54 +08:00
else if (mc >= MC_1_18)
{
initBiomeNoise(&g->bn, mc);
}
Added Beta climate biome generation (no ocean gen yet) (biome_tree.c) - getOldBetaBiome: removed isWater argument. (finders.c) - getStructureConfig: now returns 0 for mineshafts and villages before B1.8. (layers.h) - Added SurfaceNoiseBeta struct: Very similar to SurfaceNoise. Since SurfaceNoiseBeta will only ever be used for the Overworld, the double values saved in SurfaceNoise will be hardcoded into the SurfaceNoiseBeta sampling function. octSurf and octDepth in surfaceNoise are replaced with new octA and octB OctaveNoises, used for precise terrain generation. These names are subject to change if I come up with more meaningful names in the future. The oct array contains six additional PerlinNoise structs compared to SurfaceNoise, as the 4-octave octSurf is replaced with the 10-octave octA. - Added BiomeNoiseBeta struct: Mostly a cut-down version of BiomeNoise. The climate array contains three OctaveNoise structs, corresponding to the 4-octave temperature and humidity noise generators, as well as an additional 2-octave generator that I'm calling "fuzz". The fuzz noise is high-frequency and low-amplitude, and is used as a factor applied to the raw output of both the temperature and humidity generators before these values are used. The PerlinNoise array oct contains 10 octaves -- 4 for temperature, 4 for humidity, and 2 for fuzz. nptype and mc are carried over from BiomeNoise. mc currently has no purpose, but I've heard of a bug in some early beta versions causing chunk biomes to generate rotated, so storing the version may eventually prove useful. - Added headers for 5 new functions in layers.c. - Changed header for getOldBetaBiome (defined in biome_tree.c) to reflect new signature. (layers.c) - Added initSurfaceNoiseBeta function: No-op placeholder for now. - Added setBetaBiomeSeed function: Initializes the three climate simplex noise generators and sets bnb->nptype to -1 by default. - Added sampleBiomeNoiseBeta function: sampleBiomeNoiseBeta samples climate noise at the given x and z coordinates (1:1 scale) and returns a biome ID corresponding to the biome at the generated temperature and humidity noise values. The behavior of zeroing out the array np when it is passed is copied from sampleBiomeNoise. I'm not sure about its function, so if it's not applicable, this argument and associated behavior can be removed. If bnb->nptype is set to NP_TEMPERATURE or NP_HUMIDITY, only that noise value is generated and the other is ignored. The noise value is multiplied by 10000 and returned as a signed long to match the behavior of sampleBiomeNoise. Note that Beta climate values range from 0 to 1, not -1 to 1, so the resulting ints will all be nonnegative. The argument nv (noise values) is a pointer to a 2-element array of doubles. If it is present, the noise values are placed in the array before the biome is determined. - Added genBetaBiomeNoiseScaled function: At 1:1 scale, every block in Range r is sampled and the return value of sampleBiomeNoiseBeta is placed in the cache. At higher scales, midpoints are sampled. When ocean support is added, this function will likely behave differently when NO_BETA_OCEAN is clear in order to maximize time and memory efficiency. (generator.h) - Flags enum: Bit 1 (0x2) is now the NO_BETA_OCEAN flag. - Generator struct: New union member for pre-B1.8: Includes BiomeNoiseBeta and SurfaceNoiseBeta structs now defined in layers.h (generator.c) - setupGenearator: New version so pre-B1.8 versions behave correctly. For mc <= MC_B1_7, setupGenerator simply sets g->bnb.mc, as all other setup for pre-B1.8 biome generation requires the seed to be known. - applySeed: When mc <= MC_B1_7, the new setBetaBiomeSeed function defined in layers.c is called. If the NO_BETA_OCEAN flag is not set, initSurfaceNoiseBeta is also called. initSurfaceNoiseBeta is currently just a no-op placeholder. - getMinCacheSize: New version check. Returns default size when mc <= MC_B1_7. Will likely be modified when ocean-finding functionality is added. - genBiomes: Calls genBetaBiomeNoiseScaled when mc <= MC_B1_7 Note: Compiling libcubiomes.a will will currently cause several warnings due to unused parameters related to not-yet-implemented ocean finding.
2023-01-24 05:51:54 +08:00
else
{
g->bnb.mc = mc;
}
}
void applySeed(Generator *g, int dim, uint64_t seed)
{
g->dim = dim;
g->seed = seed;
g->sha = 0;
2022-08-15 00:00:23 +08:00
if (dim == DIM_OVERWORLD)
{
if (g->mc <= MC_B1_7)
{
setBetaBiomeSeed(&g->bnb, seed);
//initSurfaceNoiseBeta(&g->snb, g->seed);
}
else if (g->mc <= MC_1_17)
{
setLayerSeed(g->entry ? g->entry : g->ls.entry_1, seed);
}
else // if (g->mc >= MC_1_18)
{
setBiomeSeed(&g->bn, seed, g->flags & LARGE_BIOMES);
}
}
else if (dim == DIM_NETHER && g->mc >= MC_1_16_1)
{
setNetherSeed(&g->nn, seed);
}
2022-08-15 00:00:23 +08:00
else if (dim == DIM_END && g->mc >= MC_1_9)
{
setEndSeed(&g->en, g->mc, seed);
}
if (g->mc >= MC_1_15)
{
2022-08-15 00:00:23 +08:00
if (g->mc <= MC_1_17 && dim == DIM_OVERWORLD && !g->entry)
g->sha = g->ls.entry_1->startSalt;
else
g->sha = getVoronoiSHA(seed);
}
}
size_t getMinCacheSize(const Generator *g, int scale, int sx, int sy, int sz)
{
if (sy == 0)
sy = 1;
size_t len = (size_t)sx * sz * sy;
if (g->mc <= MC_B1_7 && scale <= 4 && !(g->flags & NO_BETA_OCEAN))
Added ocean detection for Beta 1.7 (generator.c) - getMinCacheSize(): Allocate extra cache for Beta ocean column noise buffer (noise.c) - samplePerlin(): Reverted previous change, as the attempted optimization had unintended side-effects for 1.18+ generation and had no measurable performance improvement. (layers.h) - Renamed two OctaveNoise members of struct SurfaceNoiseBeta - Added new struct SeaLevelColumnNoiseBeta - Added headers for four new functions defined in layers.c (layers.c) - initSurfaceNoiseBeta(): Reflect changes to names in layers.h - sampleBiomeNoiseBeta(): When nptype == 1, returned humidity value is now multiplied by temperature to reflect the behavior seen in biome gen - Added new function genColumnNoise(): Generates values used to calculate terrain noise columns and places them in a SeaLevelColumnNoiseBeta struct pointed to by the provided pointer. - Added new function processColumnNoise(): Generates a partial noise column for finding the block at sea level using data pointed to by the provided SeaLevelColumnNoiseBeta pointer - Added new function sampleBlocks(): Using adjacent noise columns, determine whether the blocks at y=64 are solid and place results in array pointed to by provided pointer - Added new function sampleBetaBiomeOneBlock(): Generates new noise columns for each sampled block and skips the diagonal traversal with cache buffer, as no noise columns data can be re-used when scale >= 8. - genBetaBiomeNoiseScaled(): Previous "no ocean" code is now locked behind (noOcean || scale >= 8) condition. Calls sampleBiomeNoiseBeta() when noOcean is true, and calls sampleBetaBiomeOneBlock() otherwise. Else, the generated region is traversed in 4x4 block sections corresponding to terrain noise columns. Columns are saved for re-use in future passes in order to minimize unnecessary Perlin generation, and region traversal is done in diagonal stripes in order to minimize extra cache size needed (on average) for the saved noise sample buffer. My original plan for the diagonal traversal was to store SeaLevelColumnNoise *pointers* in the extra cache space, which would be dynamically allocated when generated, but since extra cache space will only exceed the original cache space when the generated area is so small that memory concerns are trivial, this plan was abandoned in favor of storing the structs directly in the cache. This approach also eliminates the risk of memory leaks. Currently, with oceans, this code takes about 20 seconds to generate the biomes for a 4096 x 4096 block region. Since this approach to ocean-finding deals in 4x4 noise columns, scales 2-4 are still quite slow for the same scaled region -- about 13 seconds at 1:4 scale. At higher scales, the diagonal approach is abandoned and four new noise columns are generated for every midpoint block that is sampled. I made a quick test build of Cubiomes Viewer, and while the ocean-finding code works, the regions are very slow to show up in the view window, and changing the zoom level can cause regions to reset when zooming in both directions. Perhaps some optimizations can be made in Cubiomes Viewer in terms of handling cache and displaying generated biomes at different scales, but I'm not familiar enough with that project to suggest anything specific. I tried to cut out as much unnecessary processing as possible in my implementation of the inherently cpu-intensive ocean-finding algorithm, but it's certainly possible optimizations can be made in the generation code itself.
2023-02-02 08:00:03 +08:00
{
int cellwidth = scale >> 1;
int smin = (sx < sz ? sx : sz);
int slen = ((smin >> (2 >> cellwidth)) + 1) * 2 + 1;
len += slen * sizeof(SeaLevelColumnNoiseBeta);
Added ocean detection for Beta 1.7 (generator.c) - getMinCacheSize(): Allocate extra cache for Beta ocean column noise buffer (noise.c) - samplePerlin(): Reverted previous change, as the attempted optimization had unintended side-effects for 1.18+ generation and had no measurable performance improvement. (layers.h) - Renamed two OctaveNoise members of struct SurfaceNoiseBeta - Added new struct SeaLevelColumnNoiseBeta - Added headers for four new functions defined in layers.c (layers.c) - initSurfaceNoiseBeta(): Reflect changes to names in layers.h - sampleBiomeNoiseBeta(): When nptype == 1, returned humidity value is now multiplied by temperature to reflect the behavior seen in biome gen - Added new function genColumnNoise(): Generates values used to calculate terrain noise columns and places them in a SeaLevelColumnNoiseBeta struct pointed to by the provided pointer. - Added new function processColumnNoise(): Generates a partial noise column for finding the block at sea level using data pointed to by the provided SeaLevelColumnNoiseBeta pointer - Added new function sampleBlocks(): Using adjacent noise columns, determine whether the blocks at y=64 are solid and place results in array pointed to by provided pointer - Added new function sampleBetaBiomeOneBlock(): Generates new noise columns for each sampled block and skips the diagonal traversal with cache buffer, as no noise columns data can be re-used when scale >= 8. - genBetaBiomeNoiseScaled(): Previous "no ocean" code is now locked behind (noOcean || scale >= 8) condition. Calls sampleBiomeNoiseBeta() when noOcean is true, and calls sampleBetaBiomeOneBlock() otherwise. Else, the generated region is traversed in 4x4 block sections corresponding to terrain noise columns. Columns are saved for re-use in future passes in order to minimize unnecessary Perlin generation, and region traversal is done in diagonal stripes in order to minimize extra cache size needed (on average) for the saved noise sample buffer. My original plan for the diagonal traversal was to store SeaLevelColumnNoise *pointers* in the extra cache space, which would be dynamically allocated when generated, but since extra cache space will only exceed the original cache space when the generated area is so small that memory concerns are trivial, this plan was abandoned in favor of storing the structs directly in the cache. This approach also eliminates the risk of memory leaks. Currently, with oceans, this code takes about 20 seconds to generate the biomes for a 4096 x 4096 block region. Since this approach to ocean-finding deals in 4x4 noise columns, scales 2-4 are still quite slow for the same scaled region -- about 13 seconds at 1:4 scale. At higher scales, the diagonal approach is abandoned and four new noise columns are generated for every midpoint block that is sampled. I made a quick test build of Cubiomes Viewer, and while the ocean-finding code works, the regions are very slow to show up in the view window, and changing the zoom level can cause regions to reset when zooming in both directions. Perhaps some optimizations can be made in Cubiomes Viewer in terms of handling cache and displaying generated biomes at different scales, but I'm not familiar enough with that project to suggest anything specific. I tried to cut out as much unnecessary processing as possible in my implementation of the inherently cpu-intensive ocean-finding algorithm, but it's certainly possible optimizations can be made in the generation code itself.
2023-02-02 08:00:03 +08:00
}
else if (g->mc >= MC_B1_8 && g->mc <= MC_1_17 && g->dim == DIM_OVERWORLD)
{ // recursively check the layer stack for the max buffer
const Layer *entry = getLayerForScale(g, scale);
if (!entry) {
printf("getMinCacheSize(): failed to determine scaled entry\n");
return 0;
}
size_t len2d = getMinLayerCacheSize(entry, sx, sz);
len += len2d - sx*sz;
}
else if ((g->mc >= MC_1_18 || g->dim != DIM_OVERWORLD) && scale <= 1)
{ // allocate space for temporary copy of voronoi source
sx = ((sx+3) >> 2) + 2;
sy = ((sy+3) >> 2) + 2;
sz = ((sz+3) >> 2) + 2;
len += sx * sy * sz;
}
return len;
}
int *allocCache(const Generator *g, Range r)
{
size_t len = getMinCacheSize(g, r.scale, r.sx, r.sy, r.sz);
if (len == 0)
return NULL;
return (int*) calloc(len, sizeof(int));
}
int genBiomes(const Generator *g, int *cache, Range r)
{
int err = 1;
int64_t i, k;
2022-08-15 00:00:23 +08:00
if (g->dim == DIM_OVERWORLD)
{
Added Beta climate biome generation (no ocean gen yet) (biome_tree.c) - getOldBetaBiome: removed isWater argument. (finders.c) - getStructureConfig: now returns 0 for mineshafts and villages before B1.8. (layers.h) - Added SurfaceNoiseBeta struct: Very similar to SurfaceNoise. Since SurfaceNoiseBeta will only ever be used for the Overworld, the double values saved in SurfaceNoise will be hardcoded into the SurfaceNoiseBeta sampling function. octSurf and octDepth in surfaceNoise are replaced with new octA and octB OctaveNoises, used for precise terrain generation. These names are subject to change if I come up with more meaningful names in the future. The oct array contains six additional PerlinNoise structs compared to SurfaceNoise, as the 4-octave octSurf is replaced with the 10-octave octA. - Added BiomeNoiseBeta struct: Mostly a cut-down version of BiomeNoise. The climate array contains three OctaveNoise structs, corresponding to the 4-octave temperature and humidity noise generators, as well as an additional 2-octave generator that I'm calling "fuzz". The fuzz noise is high-frequency and low-amplitude, and is used as a factor applied to the raw output of both the temperature and humidity generators before these values are used. The PerlinNoise array oct contains 10 octaves -- 4 for temperature, 4 for humidity, and 2 for fuzz. nptype and mc are carried over from BiomeNoise. mc currently has no purpose, but I've heard of a bug in some early beta versions causing chunk biomes to generate rotated, so storing the version may eventually prove useful. - Added headers for 5 new functions in layers.c. - Changed header for getOldBetaBiome (defined in biome_tree.c) to reflect new signature. (layers.c) - Added initSurfaceNoiseBeta function: No-op placeholder for now. - Added setBetaBiomeSeed function: Initializes the three climate simplex noise generators and sets bnb->nptype to -1 by default. - Added sampleBiomeNoiseBeta function: sampleBiomeNoiseBeta samples climate noise at the given x and z coordinates (1:1 scale) and returns a biome ID corresponding to the biome at the generated temperature and humidity noise values. The behavior of zeroing out the array np when it is passed is copied from sampleBiomeNoise. I'm not sure about its function, so if it's not applicable, this argument and associated behavior can be removed. If bnb->nptype is set to NP_TEMPERATURE or NP_HUMIDITY, only that noise value is generated and the other is ignored. The noise value is multiplied by 10000 and returned as a signed long to match the behavior of sampleBiomeNoise. Note that Beta climate values range from 0 to 1, not -1 to 1, so the resulting ints will all be nonnegative. The argument nv (noise values) is a pointer to a 2-element array of doubles. If it is present, the noise values are placed in the array before the biome is determined. - Added genBetaBiomeNoiseScaled function: At 1:1 scale, every block in Range r is sampled and the return value of sampleBiomeNoiseBeta is placed in the cache. At higher scales, midpoints are sampled. When ocean support is added, this function will likely behave differently when NO_BETA_OCEAN is clear in order to maximize time and memory efficiency. (generator.h) - Flags enum: Bit 1 (0x2) is now the NO_BETA_OCEAN flag. - Generator struct: New union member for pre-B1.8: Includes BiomeNoiseBeta and SurfaceNoiseBeta structs now defined in layers.h (generator.c) - setupGenearator: New version so pre-B1.8 versions behave correctly. For mc <= MC_B1_7, setupGenerator simply sets g->bnb.mc, as all other setup for pre-B1.8 biome generation requires the seed to be known. - applySeed: When mc <= MC_B1_7, the new setBetaBiomeSeed function defined in layers.c is called. If the NO_BETA_OCEAN flag is not set, initSurfaceNoiseBeta is also called. initSurfaceNoiseBeta is currently just a no-op placeholder. - getMinCacheSize: New version check. Returns default size when mc <= MC_B1_7. Will likely be modified when ocean-finding functionality is added. - genBiomes: Calls genBetaBiomeNoiseScaled when mc <= MC_B1_7 Note: Compiling libcubiomes.a will will currently cause several warnings due to unused parameters related to not-yet-implemented ocean finding.
2023-01-24 05:51:54 +08:00
if (g->mc >= MC_B1_8 && g->mc <= MC_1_17)
{
const Layer *entry = getLayerForScale(g, r.scale);
if (!entry) return -1;
err = genArea(entry, cache, r.x, r.z, r.sx, r.sz);
if (err) return err;
for (k = 1; k < r.sy; k++)
{ // overworld has no vertical noise: expanding 2D into 3D
for (i = 0; i < r.sx*r.sz; i++)
cache[k*r.sx*r.sz + i] = cache[i];
}
return 0;
}
Added Beta climate biome generation (no ocean gen yet) (biome_tree.c) - getOldBetaBiome: removed isWater argument. (finders.c) - getStructureConfig: now returns 0 for mineshafts and villages before B1.8. (layers.h) - Added SurfaceNoiseBeta struct: Very similar to SurfaceNoise. Since SurfaceNoiseBeta will only ever be used for the Overworld, the double values saved in SurfaceNoise will be hardcoded into the SurfaceNoiseBeta sampling function. octSurf and octDepth in surfaceNoise are replaced with new octA and octB OctaveNoises, used for precise terrain generation. These names are subject to change if I come up with more meaningful names in the future. The oct array contains six additional PerlinNoise structs compared to SurfaceNoise, as the 4-octave octSurf is replaced with the 10-octave octA. - Added BiomeNoiseBeta struct: Mostly a cut-down version of BiomeNoise. The climate array contains three OctaveNoise structs, corresponding to the 4-octave temperature and humidity noise generators, as well as an additional 2-octave generator that I'm calling "fuzz". The fuzz noise is high-frequency and low-amplitude, and is used as a factor applied to the raw output of both the temperature and humidity generators before these values are used. The PerlinNoise array oct contains 10 octaves -- 4 for temperature, 4 for humidity, and 2 for fuzz. nptype and mc are carried over from BiomeNoise. mc currently has no purpose, but I've heard of a bug in some early beta versions causing chunk biomes to generate rotated, so storing the version may eventually prove useful. - Added headers for 5 new functions in layers.c. - Changed header for getOldBetaBiome (defined in biome_tree.c) to reflect new signature. (layers.c) - Added initSurfaceNoiseBeta function: No-op placeholder for now. - Added setBetaBiomeSeed function: Initializes the three climate simplex noise generators and sets bnb->nptype to -1 by default. - Added sampleBiomeNoiseBeta function: sampleBiomeNoiseBeta samples climate noise at the given x and z coordinates (1:1 scale) and returns a biome ID corresponding to the biome at the generated temperature and humidity noise values. The behavior of zeroing out the array np when it is passed is copied from sampleBiomeNoise. I'm not sure about its function, so if it's not applicable, this argument and associated behavior can be removed. If bnb->nptype is set to NP_TEMPERATURE or NP_HUMIDITY, only that noise value is generated and the other is ignored. The noise value is multiplied by 10000 and returned as a signed long to match the behavior of sampleBiomeNoise. Note that Beta climate values range from 0 to 1, not -1 to 1, so the resulting ints will all be nonnegative. The argument nv (noise values) is a pointer to a 2-element array of doubles. If it is present, the noise values are placed in the array before the biome is determined. - Added genBetaBiomeNoiseScaled function: At 1:1 scale, every block in Range r is sampled and the return value of sampleBiomeNoiseBeta is placed in the cache. At higher scales, midpoints are sampled. When ocean support is added, this function will likely behave differently when NO_BETA_OCEAN is clear in order to maximize time and memory efficiency. (generator.h) - Flags enum: Bit 1 (0x2) is now the NO_BETA_OCEAN flag. - Generator struct: New union member for pre-B1.8: Includes BiomeNoiseBeta and SurfaceNoiseBeta structs now defined in layers.h (generator.c) - setupGenearator: New version so pre-B1.8 versions behave correctly. For mc <= MC_B1_7, setupGenerator simply sets g->bnb.mc, as all other setup for pre-B1.8 biome generation requires the seed to be known. - applySeed: When mc <= MC_B1_7, the new setBetaBiomeSeed function defined in layers.c is called. If the NO_BETA_OCEAN flag is not set, initSurfaceNoiseBeta is also called. initSurfaceNoiseBeta is currently just a no-op placeholder. - getMinCacheSize: New version check. Returns default size when mc <= MC_B1_7. Will likely be modified when ocean-finding functionality is added. - genBiomes: Calls genBetaBiomeNoiseScaled when mc <= MC_B1_7 Note: Compiling libcubiomes.a will will currently cause several warnings due to unused parameters related to not-yet-implemented ocean finding.
2023-01-24 05:51:54 +08:00
else if (g->mc >= MC_1_18)
{
return genBiomeNoiseScaled(&g->bn, cache, r, g->sha);
}
Added Beta climate biome generation (no ocean gen yet) (biome_tree.c) - getOldBetaBiome: removed isWater argument. (finders.c) - getStructureConfig: now returns 0 for mineshafts and villages before B1.8. (layers.h) - Added SurfaceNoiseBeta struct: Very similar to SurfaceNoise. Since SurfaceNoiseBeta will only ever be used for the Overworld, the double values saved in SurfaceNoise will be hardcoded into the SurfaceNoiseBeta sampling function. octSurf and octDepth in surfaceNoise are replaced with new octA and octB OctaveNoises, used for precise terrain generation. These names are subject to change if I come up with more meaningful names in the future. The oct array contains six additional PerlinNoise structs compared to SurfaceNoise, as the 4-octave octSurf is replaced with the 10-octave octA. - Added BiomeNoiseBeta struct: Mostly a cut-down version of BiomeNoise. The climate array contains three OctaveNoise structs, corresponding to the 4-octave temperature and humidity noise generators, as well as an additional 2-octave generator that I'm calling "fuzz". The fuzz noise is high-frequency and low-amplitude, and is used as a factor applied to the raw output of both the temperature and humidity generators before these values are used. The PerlinNoise array oct contains 10 octaves -- 4 for temperature, 4 for humidity, and 2 for fuzz. nptype and mc are carried over from BiomeNoise. mc currently has no purpose, but I've heard of a bug in some early beta versions causing chunk biomes to generate rotated, so storing the version may eventually prove useful. - Added headers for 5 new functions in layers.c. - Changed header for getOldBetaBiome (defined in biome_tree.c) to reflect new signature. (layers.c) - Added initSurfaceNoiseBeta function: No-op placeholder for now. - Added setBetaBiomeSeed function: Initializes the three climate simplex noise generators and sets bnb->nptype to -1 by default. - Added sampleBiomeNoiseBeta function: sampleBiomeNoiseBeta samples climate noise at the given x and z coordinates (1:1 scale) and returns a biome ID corresponding to the biome at the generated temperature and humidity noise values. The behavior of zeroing out the array np when it is passed is copied from sampleBiomeNoise. I'm not sure about its function, so if it's not applicable, this argument and associated behavior can be removed. If bnb->nptype is set to NP_TEMPERATURE or NP_HUMIDITY, only that noise value is generated and the other is ignored. The noise value is multiplied by 10000 and returned as a signed long to match the behavior of sampleBiomeNoise. Note that Beta climate values range from 0 to 1, not -1 to 1, so the resulting ints will all be nonnegative. The argument nv (noise values) is a pointer to a 2-element array of doubles. If it is present, the noise values are placed in the array before the biome is determined. - Added genBetaBiomeNoiseScaled function: At 1:1 scale, every block in Range r is sampled and the return value of sampleBiomeNoiseBeta is placed in the cache. At higher scales, midpoints are sampled. When ocean support is added, this function will likely behave differently when NO_BETA_OCEAN is clear in order to maximize time and memory efficiency. (generator.h) - Flags enum: Bit 1 (0x2) is now the NO_BETA_OCEAN flag. - Generator struct: New union member for pre-B1.8: Includes BiomeNoiseBeta and SurfaceNoiseBeta structs now defined in layers.h (generator.c) - setupGenearator: New version so pre-B1.8 versions behave correctly. For mc <= MC_B1_7, setupGenerator simply sets g->bnb.mc, as all other setup for pre-B1.8 biome generation requires the seed to be known. - applySeed: When mc <= MC_B1_7, the new setBetaBiomeSeed function defined in layers.c is called. If the NO_BETA_OCEAN flag is not set, initSurfaceNoiseBeta is also called. initSurfaceNoiseBeta is currently just a no-op placeholder. - getMinCacheSize: New version check. Returns default size when mc <= MC_B1_7. Will likely be modified when ocean-finding functionality is added. - genBiomes: Calls genBetaBiomeNoiseScaled when mc <= MC_B1_7 Note: Compiling libcubiomes.a will will currently cause several warnings due to unused parameters related to not-yet-implemented ocean finding.
2023-01-24 05:51:54 +08:00
else // g->mc <= MC_B1_7
{
if (g->flags & NO_BETA_OCEAN)
{
err = genBiomeNoiseBetaScaled(&g->bnb, NULL, cache, r);
}
else
Added noise generation functions for Beta 1.7 terrain (biome_tree.c) - Moved a curly brace to maintain style consistent with repo (generator.h) - Removed SurfaceNoiseBeta struct from Generator (generator.c) - applySeed(): Removed initSurfaceNoiseBeta() call - genBiomes(): Now declares and initializes SurfaceNoiseBeta when mc <= MC_B1_7 Returns err when g->dim == DIM_END and mc < MC_1_0 (layers.c) - biomeExists(): Added new checks for mc <= B1_7 - initSurfaceNoiseBeta(): Implemented - New comment added to sampleBiomeNoiseBeta() (noise.h) - Added headers for four new functions defined in noise.c (noise.c) - samplePerlin(): Placed all lerps used for 3D noise but not used for 2D noise behind a (d2 != 0) condition. I'm anticipating needing every bit of optimization I can find to make ocean-finding practically efficient. - added new samplePerlinOldBetaTerrain3D() function: used to generate the octmin, octmax, and octmain noise near sea level for the given noise column x and z. The necessity for this function will be explained more in-depth below. - added new initOctaveOldBetaTerrain() function: Used to initialize the five Perlin OctaveNoise structs in SurfaceNoiseBeta. Unlike climate noise, these are Perlin noise maps instead of Simplex, but the existing octaveInit() cannot be used because the starting lacunarity values are not integer powers of 2. - added new sampleOctave2D() function: Nearly identical to sampleOctave(), except that ay is set to -(p->b), forcing samplePerlin()'s d2 variable to be 0, resulting in a 2D noise sample. - added new sampleOctaveOldBetaTerrain3D() function: Used to sample the three 3D noisemaps in SurfaceNoiseBeta. The function is passed a 2-element array of doubles, which is passed to samplePerlinOldBetaTerrain3D() where the different octaves' values are added. The only samples made are the ones necessary to determine the blocks at sea level. samplePerlinOldBetaTerrain3D() is necessary because when generating these versions' overworld octmin, octmax, and octmain noise, lower levels affect higher levels based on whether the lower 8 bits of i2 are equal to the lower 8 bits of i2 from the previous iteration. Each level is only affected by the immediately previous level where (i2 & 255 !- previ2), so I was able to make an optimization -- the first several y-level iterations are split into a separate for loop that only looks at i2, and finds the highest y-level that affects the final output at sea level. In my Java test program using Minecraft's code, this optimization brough the time needed to produce an image of a 4096 x 4096 region down to 1/3 of what it was before the optimization. The yLacFlag argument determines whether or not lacunarity is cut in half for the y dimension -- octmain uses lacunarity values for y that are half of the x/z lacunarity value. In a future commit, I may extend samplePerlinOldBetaTerrain3D() and sampleOctaveOldBetaTerrain3D() to generate partial noise columns between ymin and ymax bounds, in order to eventually implement 4x4 surface height finding.
2023-01-28 09:17:38 +08:00
{
SurfaceNoiseBeta snb;
initSurfaceNoiseBeta(&snb, g->seed);
err = genBiomeNoiseBetaScaled(&g->bnb, &snb, cache, r);
Added noise generation functions for Beta 1.7 terrain (biome_tree.c) - Moved a curly brace to maintain style consistent with repo (generator.h) - Removed SurfaceNoiseBeta struct from Generator (generator.c) - applySeed(): Removed initSurfaceNoiseBeta() call - genBiomes(): Now declares and initializes SurfaceNoiseBeta when mc <= MC_B1_7 Returns err when g->dim == DIM_END and mc < MC_1_0 (layers.c) - biomeExists(): Added new checks for mc <= B1_7 - initSurfaceNoiseBeta(): Implemented - New comment added to sampleBiomeNoiseBeta() (noise.h) - Added headers for four new functions defined in noise.c (noise.c) - samplePerlin(): Placed all lerps used for 3D noise but not used for 2D noise behind a (d2 != 0) condition. I'm anticipating needing every bit of optimization I can find to make ocean-finding practically efficient. - added new samplePerlinOldBetaTerrain3D() function: used to generate the octmin, octmax, and octmain noise near sea level for the given noise column x and z. The necessity for this function will be explained more in-depth below. - added new initOctaveOldBetaTerrain() function: Used to initialize the five Perlin OctaveNoise structs in SurfaceNoiseBeta. Unlike climate noise, these are Perlin noise maps instead of Simplex, but the existing octaveInit() cannot be used because the starting lacunarity values are not integer powers of 2. - added new sampleOctave2D() function: Nearly identical to sampleOctave(), except that ay is set to -(p->b), forcing samplePerlin()'s d2 variable to be 0, resulting in a 2D noise sample. - added new sampleOctaveOldBetaTerrain3D() function: Used to sample the three 3D noisemaps in SurfaceNoiseBeta. The function is passed a 2-element array of doubles, which is passed to samplePerlinOldBetaTerrain3D() where the different octaves' values are added. The only samples made are the ones necessary to determine the blocks at sea level. samplePerlinOldBetaTerrain3D() is necessary because when generating these versions' overworld octmin, octmax, and octmain noise, lower levels affect higher levels based on whether the lower 8 bits of i2 are equal to the lower 8 bits of i2 from the previous iteration. Each level is only affected by the immediately previous level where (i2 & 255 !- previ2), so I was able to make an optimization -- the first several y-level iterations are split into a separate for loop that only looks at i2, and finds the highest y-level that affects the final output at sea level. In my Java test program using Minecraft's code, this optimization brough the time needed to produce an image of a 4096 x 4096 region down to 1/3 of what it was before the optimization. The yLacFlag argument determines whether or not lacunarity is cut in half for the y dimension -- octmain uses lacunarity values for y that are half of the x/z lacunarity value. In a future commit, I may extend samplePerlinOldBetaTerrain3D() and sampleOctaveOldBetaTerrain3D() to generate partial noise columns between ymin and ymax bounds, in order to eventually implement 4x4 surface height finding.
2023-01-28 09:17:38 +08:00
}
if (err) return err;
for (k = 1; k < r.sy; k++)
{ // overworld has no vertical noise: expanding 2D into 3D
for (i = 0; i < r.sx*r.sz; i++)
cache[k*r.sx*r.sz + i] = cache[i];
}
return 0;
Added Beta climate biome generation (no ocean gen yet) (biome_tree.c) - getOldBetaBiome: removed isWater argument. (finders.c) - getStructureConfig: now returns 0 for mineshafts and villages before B1.8. (layers.h) - Added SurfaceNoiseBeta struct: Very similar to SurfaceNoise. Since SurfaceNoiseBeta will only ever be used for the Overworld, the double values saved in SurfaceNoise will be hardcoded into the SurfaceNoiseBeta sampling function. octSurf and octDepth in surfaceNoise are replaced with new octA and octB OctaveNoises, used for precise terrain generation. These names are subject to change if I come up with more meaningful names in the future. The oct array contains six additional PerlinNoise structs compared to SurfaceNoise, as the 4-octave octSurf is replaced with the 10-octave octA. - Added BiomeNoiseBeta struct: Mostly a cut-down version of BiomeNoise. The climate array contains three OctaveNoise structs, corresponding to the 4-octave temperature and humidity noise generators, as well as an additional 2-octave generator that I'm calling "fuzz". The fuzz noise is high-frequency and low-amplitude, and is used as a factor applied to the raw output of both the temperature and humidity generators before these values are used. The PerlinNoise array oct contains 10 octaves -- 4 for temperature, 4 for humidity, and 2 for fuzz. nptype and mc are carried over from BiomeNoise. mc currently has no purpose, but I've heard of a bug in some early beta versions causing chunk biomes to generate rotated, so storing the version may eventually prove useful. - Added headers for 5 new functions in layers.c. - Changed header for getOldBetaBiome (defined in biome_tree.c) to reflect new signature. (layers.c) - Added initSurfaceNoiseBeta function: No-op placeholder for now. - Added setBetaBiomeSeed function: Initializes the three climate simplex noise generators and sets bnb->nptype to -1 by default. - Added sampleBiomeNoiseBeta function: sampleBiomeNoiseBeta samples climate noise at the given x and z coordinates (1:1 scale) and returns a biome ID corresponding to the biome at the generated temperature and humidity noise values. The behavior of zeroing out the array np when it is passed is copied from sampleBiomeNoise. I'm not sure about its function, so if it's not applicable, this argument and associated behavior can be removed. If bnb->nptype is set to NP_TEMPERATURE or NP_HUMIDITY, only that noise value is generated and the other is ignored. The noise value is multiplied by 10000 and returned as a signed long to match the behavior of sampleBiomeNoise. Note that Beta climate values range from 0 to 1, not -1 to 1, so the resulting ints will all be nonnegative. The argument nv (noise values) is a pointer to a 2-element array of doubles. If it is present, the noise values are placed in the array before the biome is determined. - Added genBetaBiomeNoiseScaled function: At 1:1 scale, every block in Range r is sampled and the return value of sampleBiomeNoiseBeta is placed in the cache. At higher scales, midpoints are sampled. When ocean support is added, this function will likely behave differently when NO_BETA_OCEAN is clear in order to maximize time and memory efficiency. (generator.h) - Flags enum: Bit 1 (0x2) is now the NO_BETA_OCEAN flag. - Generator struct: New union member for pre-B1.8: Includes BiomeNoiseBeta and SurfaceNoiseBeta structs now defined in layers.h (generator.c) - setupGenearator: New version so pre-B1.8 versions behave correctly. For mc <= MC_B1_7, setupGenerator simply sets g->bnb.mc, as all other setup for pre-B1.8 biome generation requires the seed to be known. - applySeed: When mc <= MC_B1_7, the new setBetaBiomeSeed function defined in layers.c is called. If the NO_BETA_OCEAN flag is not set, initSurfaceNoiseBeta is also called. initSurfaceNoiseBeta is currently just a no-op placeholder. - getMinCacheSize: New version check. Returns default size when mc <= MC_B1_7. Will likely be modified when ocean-finding functionality is added. - genBiomes: Calls genBetaBiomeNoiseScaled when mc <= MC_B1_7 Note: Compiling libcubiomes.a will will currently cause several warnings due to unused parameters related to not-yet-implemented ocean finding.
2023-01-24 05:51:54 +08:00
}
}
2022-08-15 00:00:23 +08:00
else if (g->dim == DIM_NETHER)
{
return genNetherScaled(&g->nn, cache, r, g->mc, g->sha);
}
2022-08-15 00:00:23 +08:00
else if (g->dim == DIM_END)
{
return genEndScaled(&g->en, cache, r, g->mc, g->sha);
}
return err;
}
int getBiomeAt(const Generator *g, int scale, int x, int y, int z)
{
Range r = {scale, x, z, 1, 1, y, 1};
int *ids = allocCache(g, r);
int id = genBiomes(g, ids, r);
if (id == 0)
id = ids[0];
else
id = none;
free(ids);
return id;
}
const Layer *getLayerForScale(const Generator *g, int scale)
{
if (g->mc > MC_1_17)
return NULL;
switch (scale)
{
case 0: return g->entry;
case 1: return g->ls.entry_1;
case 4: return g->ls.entry_4;
case 16: return g->ls.entry_16;
case 64: return g->ls.entry_64;
case 256: return g->ls.entry_256;
default:
return NULL;
}
}
Layer *setupLayer(Layer *l, mapfunc_t *map, int mc,
int8_t zoom, int8_t edge, uint64_t saltbase, Layer *p, Layer *p2)
2018-03-06 05:20:54 +08:00
{
//Layer *l = g->layers + layerId;
l->getMap = map;
l->mc = mc;
l->zoom = zoom;
l->edge = edge;
l->scale = 0;
if (saltbase == 0 || saltbase == LAYER_INIT_SHA)
l->layerSalt = saltbase;
else
l->layerSalt = getLayerSalt(saltbase);
l->startSalt = 0;
l->startSeed = 0;
l->noise = NULL;
l->data = NULL;
l->p = p;
2018-03-06 05:20:54 +08:00
l->p2 = p2;
return l;
2018-03-06 05:20:54 +08:00
}
static void setupScale(Layer *l, int scale)
{
l->scale = scale;
if (l->p)
setupScale(l->p, scale * l->zoom);
if (l->p2)
setupScale(l->p2, scale * l->zoom);
}
2018-03-18 00:53:16 +08:00
void setupLayerStack(LayerStack *g, int mc, int largeBiomes)
2018-03-06 05:20:54 +08:00
{
2021-07-24 01:56:59 +08:00
if (mc < MC_1_3)
largeBiomes = 0;
memset(g, 0, sizeof(LayerStack));
Layer *p, *l = g->layers;
mapfunc_t *map_land = 0;
// L: layer
// M: mapping function
// V: minecraft version
// Z: zoom
// E: edge
// S: salt base
// P1: parent 1
// P2: parent 2
2023-01-09 07:42:42 +08:00
if (mc == MC_B1_8)
{ // L M V Z E S P1 P2
// NOTE: reusing slot for continent:4096, but scale is 1:8192
map_land = mapLandB18;
2023-01-09 07:42:42 +08:00
p = setupLayer(l+L_CONTINENT_4096, mapContinent, mc, 1, 0, 1, 0, 0);
p = setupLayer(l+L_ZOOM_4096, mapZoomFuzzy, mc, 2, 3, 2000, p, 0);
p = setupLayer(l+L_LAND_4096, map_land, mc, 1, 2, 1, p, 0);
2023-01-09 07:42:42 +08:00
p = setupLayer(l+L_ZOOM_2048, mapZoom, mc, 2, 3, 2001, p, 0);
p = setupLayer(l+L_LAND_2048, map_land, mc, 1, 2, 2, p, 0);
2023-01-09 07:42:42 +08:00
p = setupLayer(l+L_ZOOM_1024, mapZoom, mc, 2, 3, 2002, p, 0);
p = setupLayer(l+L_LAND_1024_A, map_land, mc, 1, 2, 3, p, 0);
2023-01-09 07:42:42 +08:00
p = setupLayer(l+L_ZOOM_512, mapZoom, mc, 2, 3, 2003, p, 0);
p = setupLayer(l+L_LAND_512, map_land, mc, 1, 2, 3, p, 0);
2023-01-09 07:42:42 +08:00
p = setupLayer(l+L_ZOOM_256, mapZoom, mc, 2, 3, 2004, p, 0);
p = setupLayer(l+L_LAND_256, map_land, mc, 1, 2, 3, p, 0);
p = setupLayer(l+L_BIOME_256, mapBiome, mc, 1, 0, 200, p, 0);
p = setupLayer(l+L_ZOOM_128, mapZoom, mc, 2, 3, 1000, p, 0);
p = setupLayer(l+L_ZOOM_64, mapZoom, mc, 2, 3, 1001, p, 0);
// river noise layer chain, also used to determine where hills generate
p = setupLayer(l+L_NOISE_256, mapNoise, mc, 1, 0, 100,
l+L_LAND_256, 0);
2023-01-09 07:42:42 +08:00
}
else if (mc <= MC_1_6)
2023-01-09 07:42:42 +08:00
{ // L M V Z E S P1 P2
map_land = mapLand16;
2023-01-09 07:42:42 +08:00
p = setupLayer(l+L_CONTINENT_4096, mapContinent, mc, 1, 0, 1, 0, 0);
p = setupLayer(l+L_ZOOM_2048, mapZoomFuzzy, mc, 2, 3, 2000, p, 0);
p = setupLayer(l+L_LAND_2048, map_land, mc, 1, 2, 1, p, 0);
2023-01-09 07:42:42 +08:00
p = setupLayer(l+L_ZOOM_1024, mapZoom, mc, 2, 3, 2001, p, 0);
p = setupLayer(l+L_LAND_1024_A, map_land, mc, 1, 2, 2, p, 0);
p = setupLayer(l+L_SNOW_1024, mapSnow16, mc, 1, 2, 2, p, 0);
p = setupLayer(l+L_ZOOM_512, mapZoom, mc, 2, 3, 2002, p, 0);
p = setupLayer(l+L_LAND_512, map_land, mc, 1, 2, 3, p, 0);
p = setupLayer(l+L_ZOOM_256, mapZoom, mc, 2, 3, 2003, p, 0);
p = setupLayer(l+L_LAND_256, map_land, mc, 1, 2, 4, p, 0);
p = setupLayer(l+L_MUSHROOM_256, mapMushroom, mc, 1, 2, 5, p, 0);
p = setupLayer(l+L_BIOME_256, mapBiome, mc, 1, 0, 200, p, 0);
p = setupLayer(l+L_ZOOM_128, mapZoom, mc, 2, 3, 1000, p, 0);
p = setupLayer(l+L_ZOOM_64, mapZoom, mc, 2, 3, 1001, p, 0);
// river noise layer chain, also used to determine where hills generate
p = setupLayer(l+L_NOISE_256, mapNoise, mc, 1, 0, 100,
l+L_MUSHROOM_256, 0);
2021-07-24 01:56:59 +08:00
}
else
{ // L M V Z E S P1 P2
map_land = mapLand;
p = setupLayer(l+L_CONTINENT_4096, mapContinent, mc, 1, 0, 1, 0, 0);
p = setupLayer(l+L_ZOOM_2048, mapZoomFuzzy, mc, 2, 3, 2000, p, 0);
p = setupLayer(l+L_LAND_2048, map_land, mc, 1, 2, 1, p, 0);
p = setupLayer(l+L_ZOOM_1024, mapZoom, mc, 2, 3, 2001, p, 0);
p = setupLayer(l+L_LAND_1024_A, map_land, mc, 1, 2, 2, p, 0);
p = setupLayer(l+L_LAND_1024_B, map_land, mc, 1, 2, 50, p, 0);
p = setupLayer(l+L_LAND_1024_C, map_land, mc, 1, 2, 70, p, 0);
p = setupLayer(l+L_ISLAND_1024, mapIsland, mc, 1, 2, 2, p, 0);
p = setupLayer(l+L_SNOW_1024, mapSnow, mc, 1, 2, 2, p, 0);
p = setupLayer(l+L_LAND_1024_D, map_land, mc, 1, 2, 3, p, 0);
p = setupLayer(l+L_COOL_1024, mapCool, mc, 1, 2, 2, p, 0);
p = setupLayer(l+L_HEAT_1024, mapHeat, mc, 1, 2, 2, p, 0);
p = setupLayer(l+L_SPECIAL_1024, mapSpecial, mc, 1, 2, 3, p, 0);
p = setupLayer(l+L_ZOOM_512, mapZoom, mc, 2, 3, 2002, p, 0);
p = setupLayer(l+L_ZOOM_256, mapZoom, mc, 2, 3, 2003, p, 0);
p = setupLayer(l+L_LAND_256, map_land, mc, 1, 2, 4, p, 0);
p = setupLayer(l+L_MUSHROOM_256, mapMushroom, mc, 1, 2, 5, p, 0);
p = setupLayer(l+L_DEEP_OCEAN_256, mapDeepOcean, mc, 1, 2, 4, p, 0);
p = setupLayer(l+L_BIOME_256, mapBiome, mc, 1, 0, 200, p, 0);
2021-07-24 01:56:59 +08:00
if (mc >= MC_1_14)
p = setupLayer(l+L_BAMBOO_256, mapBamboo, mc, 1, 0, 1001, p, 0);
p = setupLayer(l+L_ZOOM_128, mapZoom, mc, 2, 3, 1000, p, 0);
p = setupLayer(l+L_ZOOM_64, mapZoom, mc, 2, 3, 1001, p, 0);
p = setupLayer(l+L_BIOME_EDGE_64, mapBiomeEdge, mc, 1, 2, 1000, p, 0);
2021-07-24 01:56:59 +08:00
// river noise layer chain, also used to determine where hills generate
p = setupLayer(l+L_RIVER_INIT_256, mapNoise, mc, 1, 0, 100,
l+L_DEEP_OCEAN_256, 0);
2021-07-24 01:56:59 +08:00
}
if (mc <= MC_1_0) {}
else if (mc <= MC_1_12)
2021-07-24 01:56:59 +08:00
{
p = setupLayer(l+L_ZOOM_128_HILLS, mapZoom, mc, 2, 3, 0, p, 0);
p = setupLayer(l+L_ZOOM_64_HILLS, mapZoom, mc, 2, 3, 0, p, 0);
2021-07-24 01:56:59 +08:00
}
else // if (mc >= MC_1_13)
2021-07-24 01:56:59 +08:00
{
p = setupLayer(l+L_ZOOM_128_HILLS, mapZoom, mc, 2, 3, 1000, p, 0);
p = setupLayer(l+L_ZOOM_64_HILLS, mapZoom, mc, 2, 3, 1001, p, 0);
2021-07-24 01:56:59 +08:00
}
if (mc <= MC_1_0)
{ // L M V Z E S P1 P2
p = setupLayer(l+L_ZOOM_32, mapZoom, mc, 2, 3, 1000,
l+L_ZOOM_64, 0);
p = setupLayer(l+L_LAND_32, map_land, mc, 1, 2, 3, p, 0);
2021-07-24 01:56:59 +08:00
// NOTE: reusing slot for shore:16, but scale is 1:32
p = setupLayer(l+L_SHORE_16, mapShore, mc, 1, 2, 1000, p, 0);
p = setupLayer(l+L_ZOOM_16, mapZoom, mc, 2, 3, 1001, p, 0);
p = setupLayer(l+L_ZOOM_8, mapZoom, mc, 2, 3, 1002, p, 0);
p = setupLayer(l+L_ZOOM_4, mapZoom, mc, 2, 3, 1003, p, 0);
2021-07-24 01:56:59 +08:00
p = setupLayer(l+L_SMOOTH_4, mapSmooth, mc, 1, 2, 1000, p, 0);
2021-07-24 01:56:59 +08:00
// river layer chain
p = setupLayer(l+L_ZOOM_128_RIVER, mapZoom, mc, 2, 3, 1000,
l+L_NOISE_256, 0);
p = setupLayer(l+L_ZOOM_64_RIVER, mapZoom, mc, 2, 3, 1001, p, 0);
p = setupLayer(l+L_ZOOM_32_RIVER, mapZoom, mc, 2, 3, 1002, p, 0);
p = setupLayer(l+L_ZOOM_16_RIVER, mapZoom, mc, 2, 3, 1003, p, 0);
p = setupLayer(l+L_ZOOM_8_RIVER, mapZoom, mc, 2, 3, 1004, p, 0);
p = setupLayer(l+L_ZOOM_4_RIVER, mapZoom, mc, 2, 3, 1005, p, 0);
p = setupLayer(l+L_RIVER_4, mapRiver, mc, 1, 2, 1, p, 0);
p = setupLayer(l+L_SMOOTH_4_RIVER, mapSmooth, mc, 1, 2, 1000, p, 0);
2021-07-24 01:56:59 +08:00
}
else if (mc <= MC_1_6)
{ // L M V Z E S P1 P2
p = setupLayer(l+L_HILLS_64, mapHills, mc, 1, 2, 1000,
l+L_ZOOM_64, l+L_ZOOM_64_HILLS);
p = setupLayer(l+L_ZOOM_32, mapZoom, mc, 2, 3, 1000, p, 0);
p = setupLayer(l+L_LAND_32, map_land, mc, 1, 2, 3, p, 0);
p = setupLayer(l+L_ZOOM_16, mapZoom, mc, 2, 3, 1001, p, 0);
p = setupLayer(l+L_SHORE_16, mapShore, mc, 1, 2, 1000, p, 0);
p = setupLayer(l+L_SWAMP_RIVER_16, mapSwampRiver, mc, 1, 0, 1000, p, 0);
p = setupLayer(l+L_ZOOM_8, mapZoom, mc, 2, 3, 1002, p, 0);
p = setupLayer(l+L_ZOOM_4, mapZoom, mc, 2, 3, 1003, p, 0);
2021-07-20 00:11:36 +08:00
if (largeBiomes)
{
p = setupLayer(l+L_ZOOM_LARGE_A, mapZoom, mc, 2, 3, 1004, p, 0);
p = setupLayer(l+L_ZOOM_LARGE_B, mapZoom, mc, 2, 3, 1005, p, 0);
2021-07-20 00:11:36 +08:00
}
p = setupLayer(l+L_SMOOTH_4, mapSmooth, mc, 1, 2, 1000, p, 0);
// river layer chain
p = setupLayer(l+L_ZOOM_128_RIVER, mapZoom, mc, 2, 3, 1000,
l+L_NOISE_256, 0);
p = setupLayer(l+L_ZOOM_64_RIVER, mapZoom, mc, 2, 3, 1001, p, 0);
p = setupLayer(l+L_ZOOM_32_RIVER, mapZoom, mc, 2, 3, 1002, p, 0);
p = setupLayer(l+L_ZOOM_16_RIVER, mapZoom, mc, 2, 3, 1003, p, 0);
p = setupLayer(l+L_ZOOM_8_RIVER, mapZoom, mc, 2, 3, 1004, p, 0);
p = setupLayer(l+L_ZOOM_4_RIVER, mapZoom, mc, 2, 3, 1005, p, 0);
2021-07-20 00:11:36 +08:00
if (largeBiomes)
{
p = setupLayer(l+L_ZOOM_L_RIVER_A, mapZoom, mc, 2, 3, 1006, p, 0);
p = setupLayer(l+L_ZOOM_L_RIVER_B, mapZoom, mc, 2, 3, 1007, p, 0);
2021-07-20 00:11:36 +08:00
}
p = setupLayer(l+L_RIVER_4, mapRiver, mc, 1, 2, 1, p, 0);
p = setupLayer(l+L_SMOOTH_4_RIVER, mapSmooth, mc, 1, 2, 1000, p, 0);
2018-03-06 05:20:54 +08:00
}
else // if (mc >= MC_1_7)
{ // L M V Z E S P1 P2
p = setupLayer(l+L_HILLS_64, mapHills, mc, 1, 2, 1000,
l+L_BIOME_EDGE_64, l+L_ZOOM_64_HILLS);
p = setupLayer(l+L_SUNFLOWER_64, mapSunflower, mc, 1, 0, 1001, p, 0);
p = setupLayer(l+L_ZOOM_32, mapZoom, mc, 2, 3, 1000, p, 0);
p = setupLayer(l+L_LAND_32, map_land, mc, 1, 2, 3, p, 0);
p = setupLayer(l+L_ZOOM_16, mapZoom, mc, 2, 3, 1001, p, 0);
p = setupLayer(l+L_SHORE_16, mapShore, mc, 1, 2, 1000, p, 0);
p = setupLayer(l+L_ZOOM_8, mapZoom, mc, 2, 3, 1002, p, 0);
p = setupLayer(l+L_ZOOM_4, mapZoom, mc, 2, 3, 1003, p, 0);
if (largeBiomes)
{
p = setupLayer(l+L_ZOOM_LARGE_A, mapZoom, mc, 2, 3, 1004, p, 0);
p = setupLayer(l+L_ZOOM_LARGE_B, mapZoom, mc, 2, 3, 1005, p, 0);
}
p = setupLayer(l+L_SMOOTH_4, mapSmooth, mc, 1, 2, 1000, p, 0);
// river layer chain
p = setupLayer(l+L_ZOOM_128_RIVER, mapZoom, mc, 2, 3, 1000,
l+L_RIVER_INIT_256, 0);
p = setupLayer(l+L_ZOOM_64_RIVER, mapZoom, mc, 2, 3, 1001, p, 0);
p = setupLayer(l+L_ZOOM_32_RIVER, mapZoom, mc, 2, 3, 1000, p, 0);
p = setupLayer(l+L_ZOOM_16_RIVER, mapZoom, mc, 2, 3, 1001, p, 0);
p = setupLayer(l+L_ZOOM_8_RIVER, mapZoom, mc, 2, 3, 1002, p, 0);
p = setupLayer(l+L_ZOOM_4_RIVER, mapZoom, mc, 2, 3, 1003, p, 0);
2021-07-20 00:11:36 +08:00
if (largeBiomes && mc == MC_1_7)
{
p = setupLayer(l+L_ZOOM_L_RIVER_A, mapZoom, mc, 2, 3, 1004, p, 0);
p = setupLayer(l+L_ZOOM_L_RIVER_B, mapZoom, mc, 2, 3, 1005, p, 0);
}
p = setupLayer(l+L_RIVER_4, mapRiver, mc, 1, 2, 1, p, 0);
p = setupLayer(l+L_SMOOTH_4_RIVER, mapSmooth, mc, 1, 2, 1000, p, 0);
2020-05-05 17:32:35 +08:00
}
2018-03-11 05:45:57 +08:00
p = setupLayer(l+L_RIVER_MIX_4, mapRiverMix, mc, 1, 0, 100,
l+L_SMOOTH_4, l+L_SMOOTH_4_RIVER);
if (mc <= MC_1_12)
2018-11-29 12:32:12 +08:00
{
p = setupLayer(l+L_VORONOI_1, mapVoronoi114, mc, 4, 3, 10, p, 0);
}
else
{
// ocean variants
p = setupLayer(l+L_OCEAN_TEMP_256, mapOceanTemp, mc, 1, 0, 2, 0, 0);
p->noise = &g->oceanRnd;
p = setupLayer(l+L_ZOOM_128_OCEAN, mapZoom, mc, 2, 3, 2001, p, 0);
p = setupLayer(l+L_ZOOM_64_OCEAN, mapZoom, mc, 2, 3, 2002, p, 0);
p = setupLayer(l+L_ZOOM_32_OCEAN, mapZoom, mc, 2, 3, 2003, p, 0);
p = setupLayer(l+L_ZOOM_16_OCEAN, mapZoom, mc, 2, 3, 2004, p, 0);
p = setupLayer(l+L_ZOOM_8_OCEAN, mapZoom, mc, 2, 3, 2005, p, 0);
p = setupLayer(l+L_ZOOM_4_OCEAN, mapZoom, mc, 2, 3, 2006, p, 0);
p = setupLayer(l+L_OCEAN_MIX_4, mapOceanMix, mc, 1, 17, 100,
l+L_RIVER_MIX_4, l+L_ZOOM_4_OCEAN);
if (mc <= MC_1_14)
p = setupLayer(l+L_VORONOI_1, mapVoronoi114, mc, 4, 3, 10, p, 0);
else
p = setupLayer(l+L_VORONOI_1, mapVoronoi, mc, 4, 3, LAYER_INIT_SHA, p, 0);
2018-11-29 12:32:12 +08:00
}
g->entry_1 = p;
g->entry_4 = l + (mc <= MC_1_12 ? L_RIVER_MIX_4 : L_OCEAN_MIX_4);
if (largeBiomes)
{
g->entry_16 = l + L_ZOOM_4;
g->entry_64 = l + (mc <= MC_1_6 ? L_SWAMP_RIVER_16 : L_SHORE_16);
g->entry_256 = l + (mc <= MC_1_6 ? L_HILLS_64 : L_SUNFLOWER_64);
}
2021-07-24 01:56:59 +08:00
else if (mc >= MC_1_1)
{
g->entry_16 = l + (mc <= MC_1_6 ? L_SWAMP_RIVER_16 : L_SHORE_16);
g->entry_64 = l + (mc <= MC_1_6 ? L_HILLS_64 : L_SUNFLOWER_64);
g->entry_256 = l + (mc <= MC_1_14 ? L_BIOME_256 : L_BAMBOO_256);
}
2021-07-24 01:56:59 +08:00
else
{
g->entry_16 = l + L_ZOOM_16;
g->entry_64 = l + L_ZOOM_64;
g->entry_256 = l + L_BIOME_256;
2021-07-24 01:56:59 +08:00
}
setupScale(g->entry_1, 1);
2018-11-29 12:32:12 +08:00
}
2020-05-05 18:49:06 +08:00
2018-07-28 22:36:41 +08:00
/* Recursively calculates the minimum buffer size required to generate an area
* of the specified size from the current layer onwards.
*/
static void getMaxArea(
const Layer *layer, int areaX, int areaZ, int *maxX, int *maxZ, size_t *siz)
2018-03-06 05:20:54 +08:00
{
2018-07-28 22:36:41 +08:00
if (layer == NULL)
2018-03-11 05:45:57 +08:00
return;
2018-03-06 05:20:54 +08:00
areaX += layer->edge;
areaZ += layer->edge;
// multi-layers and zoom-layers use a temporary copy of their parent area
if (layer->p2 || layer->zoom != 1)
*siz += areaX * areaZ;
if (areaX > *maxX) *maxX = areaX;
if (areaZ > *maxZ) *maxZ = areaZ;
if (layer->zoom == 2)
2018-03-06 05:20:54 +08:00
{
areaX >>= 1;
areaZ >>= 1;
2018-03-11 05:45:57 +08:00
}
else if (layer->zoom == 4)
2018-03-11 05:45:57 +08:00
{
areaX >>= 2;
areaZ >>= 2;
2018-03-06 05:20:54 +08:00
}
getMaxArea(layer->p, areaX, areaZ, maxX, maxZ, siz);
if (layer->p2)
getMaxArea(layer->p2, areaX, areaZ, maxX, maxZ, siz);
2018-03-11 05:45:57 +08:00
}
size_t getMinLayerCacheSize(const Layer *layer, int sizeX, int sizeZ)
2018-03-11 05:45:57 +08:00
{
int maxX = sizeX, maxZ = sizeZ;
size_t bufsiz = 0;
getMaxArea(layer, sizeX, sizeZ, &maxX, &maxZ, &bufsiz);
return bufsiz + maxX * (size_t)maxZ;
2018-03-06 05:20:54 +08:00
}
int genArea(const Layer *layer, int *out, int areaX, int areaZ, int areaWidth, int areaHeight)
2018-03-06 05:20:54 +08:00
{
memset(out, 0, sizeof(*out)*areaWidth*areaHeight);
return layer->getMap(layer, out, areaX, areaZ, areaWidth, areaHeight);
2018-03-06 05:20:54 +08:00
}
int mapApproxHeight(float *y, int *ids, const Generator *g, const SurfaceNoise *sn,
int x, int z, int w, int h)
{
if (g->dim == DIM_NETHER)
return 127;
if (g->dim == DIM_END)
{
if (g->mc <= MC_1_8)
return 1;
return mapEndSurfaceHeight(y, &g->en, sn, x, z, w, h, 4, 0);
}
if (g->mc >= MC_1_18)
{
if (g->bn.nptype != -1 && g->bn.nptype != NP_DEPTH)
return 1;
int64_t i, j;
for (j = 0; j < h; j++)
{
for (i = 0; i < w; i++)
{
int flags = 0;//SAMPLE_NO_SHIFT;
int64_t np[6];
int id = sampleBiomeNoise(&g->bn, np, x+i, 0, z+j, 0, flags);
if (ids)
ids[j*w+i] = id;
y[j*w+i] = np[NP_DEPTH] / 76.0;
}
}
return 0;
}
else if (g->mc <= MC_B1_7)
{
SurfaceNoiseBeta snb; // TODO: merge SurfaceNoise and SurfaceNoiseBeta?
initSurfaceNoiseBeta(&snb, g->seed);
int64_t i, j;
for (j = 0; j < h; j++)
{
for (i = 0; i < w; i++)
{
int samplex = (x + i) * 4 + 2;
int samplez = (z + j) * 4 + 2;
// TODO: properly implement beta surface finder
y[j*w+i] = approxSurfaceBeta(&g->bnb, &snb, samplex, samplez);
}
}
return 0;
}
const float biome_kernel[25] = { // with 10 / (sqrt(i**2 + j**2) + 0.2)
3.302044127, 4.104975761, 4.545454545, 4.104975761, 3.302044127,
4.104975761, 6.194967155, 8.333333333, 6.194967155, 4.104975761,
4.545454545, 8.333333333, 50.00000000, 8.333333333, 4.545454545,
4.104975761, 6.194967155, 8.333333333, 6.194967155, 4.104975761,
3.302044127, 4.104975761, 4.545454545, 4.104975761, 3.302044127,
};
double *depth = (double*) malloc(sizeof(double) * 2 * w * h);
double *scale = depth + w * h;
int64_t i, j;
int ii, jj;
Range r = {4, x-2, z-2, w+5, h+5, 0, 1};
int *cache = allocCache(g, r);
genBiomes(g, cache, r);
for (j = 0; j < h; j++)
{
for (i = 0; i < w; i++)
{
double d0, s0;
double wt = 0, ws = 0, wd = 0;
int id0 = cache[(j+2)*r.sx + (i+2)];
getBiomeDepthAndScale(id0, &d0, &s0, 0);
for (jj = 0; jj < 5; jj++)
{
for (ii = 0; ii < 5; ii++)
{
double d, s;
int id = cache[(j+jj)*r.sx + (i+ii)];
getBiomeDepthAndScale(id, &d, &s, 0);
float weight = biome_kernel[jj*5+ii] / (d + 2);
if (d > d0)
weight *= 0.5;
ws += s * weight;
wd += d * weight;
wt += weight;
}
}
ws /= wt;
wd /= wt;
ws = ws * 0.9 + 0.1;
wd = (wd * 4.0 - 1) / 8;
ws = 96 / ws;
wd = wd * 17./64;
depth[j*w+i] = wd;
scale[j*w+i] = ws;
if (ids)
ids[j*w+i] = id0;
}
}
free(cache);
for (j = 0; j < h; j++)
{
for (i = 0; i < w; i++)
{
int px = x+i, pz = z+j;
double off = sampleOctaveAmp(&sn->octdepth, px*200, 10, pz*200, 1, 0, 1);
off *= 65535./8000;
if (off < 0) off = -0.3 * off;
off = off * 3 - 2;
if (off > 1) off = 1;
off *= 17./64;
if (off < 0) off *= 1./28;
else off *= 1./40;
double vmin = 0, vmax = 0;
int ytest = 8, ymin = 0, ymax = 32;
do
{
double v[2];
int k;
for (k = 0; k < 2; k++)
{
int py = ytest + k;
double n0 = sampleSurfaceNoise(sn, px, py, pz);
double fall = 1 - 2 * py / 32.0 + off - 0.46875;
fall = scale[j*w+i] * (fall + depth[j*w+i]);
n0 += (fall > 0 ? 4*fall : fall);
v[k] = n0;
if (n0 >= 0 && py > ymin)
{
ymin = py;
vmin = n0;
}
if (n0 < 0 && py < ymax)
{
ymax = py;
vmax = n0;
}
}
double dy = v[0] / (v[0] - v[1]);
dy = (dy <= 0 ? floor(dy) : ceil(dy)); // round away from zero
ytest += (int) dy;
if (ytest <= ymin) ytest = ymin+1;
if (ytest >= ymax) ytest = ymax-1;
}
while (ymax - ymin > 1);
y[j*w+i] = 8 * (vmin / (double)(vmin - vmax) + ymin);
}
}
free(depth);
return 0;
}
2018-03-06 05:20:54 +08:00