Commit Graph

13 Commits

Author SHA1 Message Date
Cubitect
1163e4ec21 Smaller memory footprint of generator + small performance gain 2024-01-28 19:34:56 +01:00
Cubitect
df68a258d3 Fixed fortress generation finding incorrect end pieces (#103) 2023-10-11 18:27:10 +02:00
Cubitect
ddd19a14f6 Performance improvements to beta 1.7 biome gen. 2023-02-07 22:02:46 +01:00
Kai Sandstrom
e59c0d09e2 Beta 1.7 fixes and tweaks
(generator.c)
- getMinCacheSize():
    - Replaced integer mults/divs by powers of 2 with bit shifts.
    - Fixed a bug that made the cache buffer 2 SeaLevelColumnNoises too short.
          I'm kind of surprised this didn't cause segfaults.
- genBiomes():
    - Now copies cache values from y=0 to higher y values when sy > 1, to match
          behavior of b1.8 - 1.17.

(noise.c)
- removed sampleOctave2D().

(layers.c)
- genColumnNoise(): Now uses sampleOctaveAmp() for 2D Perlin samples.
- processColumnNoise(), sampleBlocks(), sampleBetaBiomeOneBlock(),
    genBetaBiomeNoiseScaled():
    - Replaced integer mults/divs and modulos by powers of 2 with left/right
        bit shifts and bitwise and, respectively.
2023-02-05 12:38:24 -05:00
Cubitect
7496e316a0 Octave specific biome noise initialization + use new IDs for beta + removed VLA 2023-02-04 18:09:05 +01:00
Kai Sandstrom
a42d97197c 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-01 19:00:03 -05:00
Kai Sandstrom
b9ab274afa 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-27 20:17:38 -05:00
Kai Sandstrom
6f790f4fa5 Add biome table, new funcs for beta climate maps
(biome_tree.c)
- Add lookup table for pre-B1.8 biomes
- Add getOldBetaBiome function to look up biome from climate noise values

(layers.h)
- Add header for getOldBetaBiome function defined in biome_tree.c
- Fix small error from previous commit (semicolons instead of commas)

(noise.c)
- Add new octaveInitOldBetaBiome function
- Add new sampleOctaveOldBetaBiome function

(noise.h)
- Add headers for two new functions defined in noise.c

This commit adds new functions required to generate Alpha 1.2 - Beta 1.7
climate maps, as well as a lookup table for biomes.

The pre- Beta 1.8 biome system uses three 2D simplex noise maps to determine
biomes -- two 4-octave maps for temperature and humidity, and an additional
2-octave map as a source of high-frequency noise that is applied to the raw
output of both climate maps as they are mapped to the range [-1, 1] before
being used to determine the biome at each coordinate sample.

Beta 1.7.3's NoiseGeneratorOctaves2 class defines the lacunarity and
amplitude of each octave of a map in a way that seems incompatible with the
existing octaveInit function. The lacunarity of each octave is the provided
starting value multiplied by a power of a provided modifier value, starting
at modifier^0 and ending at modifier^(octcnt-1). Amplitude works similarly, but
the starting value and modifier are hardcoded. As far as I can tell, there's no
way to get the correct results using octaveInit, so a new
octaveInitOldBetaBiome is used here to initialize the octaves correctly.

Given that Cubiomes has no pre-existing function for sampling simplex
OctaveNoise, I added sampleOctaveOldBetaBiome. It works the same as
sampleOctave, except that it calls sampleSimplex2D instead of samplePerlin,
and it adds the noisemap's random values 'a' and 'b' onto ax and az
respectively in order to match Minecraft b1.7's simplex sampling algorithm.
2023-01-19 20:02:29 -05:00
Cubitect
231ee62abe Performance improvements and separate climate min/max finders 2023-01-15 14:01:57 +01:00
Cubitect
c2442e0c94 Fix lookup table for large biome noise 2023-01-08 16:14:08 +01:00
Cubitect
a7df5c6916 Approxmate surface height + improved accuracy of getSpawn 2022-12-30 13:20:29 +01:00
Cubitect
5644cb1c22 Improved compatibility with non-GNU environments 2022-08-14 13:52:26 +02:00
Cubitect
9166974ccf Major redesign and 1.18 biome generation.
Different versions, dimensions and variations are now bundled into a single Generator structure.
Areas (x,z,w,h) are largely replaced with a Range structure that supports 3D cuboids with scaling.
The scale now acts as a generalization that replaces layer access. Direct layer access will
have to be version specific, using the LayerStack.
(I.e. this update will unfortunately break much of the API.)
2021-11-18 23:13:44 +01:00