Class PerlinNoise
java.lang.Object
com.github.yellowstonegames.grid.PerlinNoise
- All Implemented Interfaces:
INoise, Externalizable, Serializable
"Classic" Perlin noise, written by Ken Perlin before he created
This variant also uses different
Simplex Noise, with minor
adjustments. This uses quintic interpolation throughout (which was an improvement found in Simplex Noise), and has a
single long seed. Perlin Noise can have significant grid-aligned and 45-degree-diagonal artifacts when too
few octaves are used, but sometimes this is irrelevant, such as when sampling 3D noise on the surface of a sphere.
This variant also uses different
gradient vectors than the
ones used in "Improved Perlin Noise." Here all the gradient vectors are unit vectors, like in the original Perlin
Noise, which makes some calculations regarding the range the functions can return easier... in theory. In practice,
the somewhat-flawed gradient vectors used in earlier iterations of this PerlinNoise permitted a very different range
calculation, and so this class uses a carefully-crafted sigmoid function to move around the most frequent values to
roughly match earlier Perlin Noise results, but without risking going out-of-range. You can adjust the sigmoid
function parameters for a given dimension using setEqualization(int, float); "add" parameters closer to 0
produce sharper results, and results closer to 1 produce results closer to un-adjusted noise. Each dimension
typically needs a different parameter, because of how Perlin noise works; here, the defaults are
(7-dim) * 0.2f / 1.75f for each dim between 2 and 6. Why these values work well enough isn't exactly clear;
dividing by 2 instead of 1.75 makes the noise too sharp in 6D, for instance. Using any value larger than 1 for "add"
is generally very similar to just using 1. Large values tend to produce "cloudier" or "blurrier" results.- See Also:
-
Nested Class Summary
Nested classes/interfaces inherited from interface INoise
INoise.Serializer -
Field Summary
Fields -
Constructor Summary
ConstructorsConstructorDescriptionPerlinNoise(long seed) PerlinNoise(long seed, float eq2, float eq3, float eq4, float eq5, float eq6) A constructor that allows specifying theequalization valuesfor all dimensions this supports (2 through 6 inclusive), as well as the seed.PerlinNoise(PerlinNoise other) -
Method Summary
Modifier and TypeMethodDescriptionstatic floatcalculateEqualizeAdjustment(float add) Gets the value to optimally use formulinequalize(float, float, float), given the value that will be used asaddthere.copy()Creates a copy of this PerlinNoise, which should be a deep copy for any mutable state but can be shallow for immutable types such as functions.static floatemphasizeSigned(float a) Given a floatafrom -1.0 to 1.0 (both inclusive), this gets a float that adjusts a to be closer to the end points of that range (if less than 0, it gets closer to -1.0, otherwise it gets closer to 1.0).static floatequalize(float x, float add, float mul) Given inputs asxin the range -1.0 to 1.0 that are too biased towards 0.0, this "squashes" the range softly to widen it and spread it away from 0.0 without increasing bias anywhere else.booleanfloatgetEqualization(int dimension) intGets the maximum dimension supported by this generator, which is 6.intGets the minimum dimension supported by this generator, which is 2.floatgetNoise(float x, float y) Gets 2D noise with a default or pre-set seed.floatgetNoise(float x, float y, float z) Gets 3D noise with a default or pre-set seed.floatgetNoise(float x, float y, float z, float w) Gets 4D noise with a default or pre-set seed.floatgetNoise(float x, float y, float z, float w, float u) Gets 5D noise with a default or pre-set seed.floatgetNoise(float x, float y, float z, float w, float u, float v) Gets 6D noise with a default or pre-set seed.floatgetNoiseWithSeed(float x, float y, float z, float w, float u, float v, long seed) Gets 6D noise with a specific seed.floatgetNoiseWithSeed(float x, float y, float z, float w, float u, long seed) Gets 5D noise with a specific seed.floatgetNoiseWithSeed(float x, float y, float z, float w, long seed) Gets 4D noise with a specific seed.floatgetNoiseWithSeed(float x, float y, float z, long seed) Gets 3D noise with a specific seed.floatgetNoiseWithSeed(float x, float y, long seed) Gets 2D noise with a specific seed.longgetSeed()Gets the current seed of the generator, as a long.getTag()Returns the constant String"PerN"that identifies this in serialized Strings.protected static floatgradCoord2D(long seed, int x, int y, float xd, float yd) protected static floatgradCoord3D(long seed, int x, int y, int z, float xd, float yd, float zd) protected static floatgradCoord4D(long seed, int x, int y, int z, int w, float xd, float yd, float zd, float wd) protected static floatgradCoord5D(long seed, int x, int y, int z, int w, int u, float xd, float yd, float zd, float wd, float ud) protected static floatgradCoord6D(long seed, int x, int y, int z, int w, int u, int v, float xd, float yd, float zd, float wd, float ud, float vd) booleanReturns true because this generator can be seeded withsetSeed(long)and retrieved withgetSeed().inthashCode()static PerlinNoiserecreateFromString(String data) voidsetEqualization(int dimension, float value) voidsetSeed(long seed) Sets the seed to the given long, if long seeds are supported, or(int)seedif only int seeds are supported.stringDeserialize(String data) Given a serialized String produced bystringSerialize(), reassigns this PerlinNoise to have the described state from the given String.Produces a String that describes everything needed to recreate this INoise in full.toString()static floattowardsZero(float x) Given a floatx, this returns the second-closest float to x in the direction of zero.Methods inherited from interface INoise
getNoise, getNoiseWithSeed, readExternal, writeExternal
-
Field Details
-
instance
-
SCALE2
public static final float SCALE2- See Also:
-
SCALE3
public static final float SCALE3- See Also:
-
SCALE4
public static final float SCALE4- See Also:
-
SCALE5
public static final float SCALE5- See Also:
-
SCALE6
public static final float SCALE6- See Also:
-
seed
public long seed
-
-
Constructor Details
-
PerlinNoise
public PerlinNoise() -
PerlinNoise
public PerlinNoise(long seed) -
PerlinNoise
public PerlinNoise(long seed, float eq2, float eq3, float eq4, float eq5, float eq6) A constructor that allows specifying theequalization valuesfor all dimensions this supports (2 through 6 inclusive), as well as the seed. Equalization values are typically less than 1.0 and get smaller as the dimension increases.- Parameters:
seed- any longeq2- defaults to1.0f/1.75feq3- defaults to0.8f/1.75feq4- defaults to0.6f/1.75feq5- defaults to0.4f/1.75feq6- defaults to0.2f/1.75f
-
PerlinNoise
-
-
Method Details
-
towardsZero
public static float towardsZero(float x) Given a floatx, this returns the second-closest float to x in the direction of zero. If x is0f,-0f,Float.MIN_VALUE,-Float.MIN_VALUE, orFloat.MIN_VALUE - Float.MIN_VALUE, this is undefined and will probably produce an incorrect result. This is very similar toMath.nextAfter(x, 0.0), but is defined on more platforms, and skips the closest number in the direction of zero.
This static method is likely to be moved toMathToolsat some point.- Parameters:
x- a non-zero float that must be finite and should not be extremely close to 0- Returns:
- a float closer to 0 than x
-
emphasizeSigned
public static float emphasizeSigned(float a) Given a floatafrom -1.0 to 1.0 (both inclusive), this gets a float that adjusts a to be closer to the end points of that range (if less than 0, it gets closer to -1.0, otherwise it gets closer to 1.0).
Used to increase the frequency of high and low results, which improves the behavior of ridged and billow noise.
The actual numbers here are just slightly off of normal "quintic" interpolation, because this tries to avoid returning any numbers that are just slightly out-of-bounds, and has to make tiny adjustments to do so.
This static method is likely to be moved toMathToolsat some point.- Parameters:
a- a float between -1.0f and 1.0f inclusive- Returns:
- a float between -1.0f and 1.0f inclusive that is more likely to be near the extremes
-
getMinDimension
public int getMinDimension()Gets the minimum dimension supported by this generator, which is 2.- Specified by:
getMinDimensionin interfaceINoise- Returns:
- the minimum supported dimension, 2
-
getMaxDimension
public int getMaxDimension()Gets the maximum dimension supported by this generator, which is 6.- Specified by:
getMaxDimensionin interfaceINoise- Returns:
- the maximum supported dimension, 6
-
hasEfficientSetSeed
public boolean hasEfficientSetSeed()Returns true because this generator can be seeded withsetSeed(long)and retrieved withgetSeed().- Specified by:
hasEfficientSetSeedin interfaceINoise- Returns:
- true
-
setSeed
public void setSeed(long seed) Sets the seed to the given long, if long seeds are supported, or(int)seedif only int seeds are supported. IfhasEfficientSetSeed()returns true, this must be implemented and must set the seed given a long input. If this generator cannot be seeded, this is permitted to either do nothing or throw anUnsupportedOperationException. If this operation allocates or is time-intensive, then that performance cost will be passed along togetNoiseWithSeed(float, float, long), since that calls this twice unless overridden. In the case where seeding is expensive to perform, setSeed() can still be implemented whilehasEfficientSetSeed()returns false. This makes thegetNoiseWithSeed(float, float, long)methods avoid reseeding, and instead move their inputs around in space. -
getSeed
-
getTag
-
stringSerialize
Produces a String that describes everything needed to recreate this INoise in full. This String can be read back in bystringDeserialize(String)to reassign the described state to another INoise.- Specified by:
stringSerializein interfaceINoise- Returns:
- a String that describes this PerlinNoise for serialization
-
stringDeserialize
Given a serialized String produced bystringSerialize(), reassigns this PerlinNoise to have the described state from the given String. The serialized String must have been produced by a PerlinNoise.- Specified by:
stringDeserializein interfaceINoise- Parameters:
data- a serialized String, typically produced bystringSerialize()- Returns:
- this PerlinNoise, after being modified (if possible)
-
recreateFromString
-
copy
Creates a copy of this PerlinNoise, which should be a deep copy for any mutable state but can be shallow for immutable types such as functions. This almost always just calls a copy constructor. -
gradCoord2D
protected static float gradCoord2D(long seed, int x, int y, float xd, float yd) -
gradCoord3D
protected static float gradCoord3D(long seed, int x, int y, int z, float xd, float yd, float zd) -
gradCoord4D
protected static float gradCoord4D(long seed, int x, int y, int z, int w, float xd, float yd, float zd, float wd) -
gradCoord5D
protected static float gradCoord5D(long seed, int x, int y, int z, int w, int u, float xd, float yd, float zd, float wd, float ud) -
gradCoord6D
protected static float gradCoord6D(long seed, int x, int y, int z, int w, int u, int v, float xd, float yd, float zd, float wd, float ud, float vd) -
getEqualization
public float getEqualization(int dimension) - Parameters:
dimension- between 2 and 6, inclusive- Returns:
- the
addvalue currently used to equalize noise
-
setEqualization
public void setEqualization(int dimension, float value) - Parameters:
dimension- between 2 and 6, inclusivevalue- theaddvalue to use when equalizing noise
-
equalize
public static float equalize(float x, float add, float mul) Given inputs asxin the range -1.0 to 1.0 that are too biased towards 0.0, this "squashes" the range softly to widen it and spread it away from 0.0 without increasing bias anywhere else.
This starts with a common sigmoid function,x / sqrt(add + x * x), but instead of approaching -1 and 1 but never reaching them, this multiplies the result so the line crosses -1 when x is -1, and crosses 1 when x is 1. It has a smooth derivative, if that matters to you.- Parameters:
x- a float between -1 and 1add- if greater than 1, this will have nearly no effect; the lower this goes below 1, the more this will separate results near the center of the range. This must be greater than or equal to 0.0mul- typically the result of callingcalculateEqualizeAdjustment(float)onadd- Returns:
- a float with a slightly different distribution from
x, but still between -1 and 1
-
calculateEqualizeAdjustment
public static float calculateEqualizeAdjustment(float add) Gets the value to optimally use formulinequalize(float, float, float), given the value that will be used asaddthere. If mul is calculated in some other way, inputs in the -1 to 1 range won't have outputs in the -1 to 1 range from equalize().
This is mathematically the same as using1f / equalize(1f, add, 1f), but has a faster implementation.- Parameters:
add- the value that will be used asaddin a call toequalize(float, float, float)- Returns:
- the value to use as
mulinequalize(float, float, float)
-
getNoise
public float getNoise(float x, float y) Description copied from interface:INoiseGets 2D noise with a default or pre-set seed. -
getNoiseWithSeed
public float getNoiseWithSeed(float x, float y, long seed) Description copied from interface:INoiseGets 2D noise with a specific seed. If the seed cannot be retrieved or changed per-call, then this falls back to changing the position instead of the seed; you can check if this will happen withINoise.hasEfficientSetSeed().- Specified by:
getNoiseWithSeedin interfaceINoise- Parameters:
x- x position; can be any finite floaty- y position; can be any finite floatseed- can be any long- Returns:
- a noise value between -1.0f and 1.0f, both inclusive
-
getNoise
public float getNoise(float x, float y, float z) Description copied from interface:INoiseGets 3D noise with a default or pre-set seed. -
getNoiseWithSeed
public float getNoiseWithSeed(float x, float y, float z, long seed) Description copied from interface:INoiseGets 3D noise with a specific seed. If the seed cannot be retrieved or changed per-call, then this falls back to changing the position instead of the seed; you can check if this will happen withINoise.hasEfficientSetSeed().- Specified by:
getNoiseWithSeedin interfaceINoise- Parameters:
x- x position; can be any finite floaty- y position; can be any finite floatz- z position; can be any finite floatseed- can be any long- Returns:
- a noise value between -1.0f and 1.0f, both inclusive
-
getNoise
public float getNoise(float x, float y, float z, float w) Description copied from interface:INoiseGets 4D noise with a default or pre-set seed. -
getNoiseWithSeed
public float getNoiseWithSeed(float x, float y, float z, float w, long seed) Description copied from interface:INoiseGets 4D noise with a specific seed. If the seed cannot be retrieved or changed per-call, then this falls back to changing the position instead of the seed; you can check if this will happen withINoise.hasEfficientSetSeed().- Specified by:
getNoiseWithSeedin interfaceINoise- Parameters:
x- x position; can be any finite floaty- y position; can be any finite floatz- z position; can be any finite floatw- w position; can be any finite floatseed- can be any long- Returns:
- a noise value between -1.0f and 1.0f, both inclusive
-
getNoise
public float getNoise(float x, float y, float z, float w, float u) Description copied from interface:INoiseGets 5D noise with a default or pre-set seed.- Specified by:
getNoisein interfaceINoise- Parameters:
x- x position; can be any finite floaty- y position; can be any finite floatz- z position; can be any finite floatw- w position; can be any finite floatu- u position; can be any finite float- Returns:
- a noise value between -1.0f and 1.0f, both inclusive
-
getNoiseWithSeed
public float getNoiseWithSeed(float x, float y, float z, float w, float u, long seed) Description copied from interface:INoiseGets 5D noise with a specific seed. If the seed cannot be retrieved or changed per-call, then this falls back to changing the position instead of the seed; you can check if this will happen withINoise.hasEfficientSetSeed().- Specified by:
getNoiseWithSeedin interfaceINoise- Parameters:
x- x position; can be any finite floaty- y position; can be any finite floatz- z position; can be any finite floatw- w position; can be any finite floatu- u position; can be any finite floatseed- can be any long- Returns:
- a noise value between -1.0f and 1.0f, both inclusive
-
getNoise
public float getNoise(float x, float y, float z, float w, float u, float v) Description copied from interface:INoiseGets 6D noise with a default or pre-set seed.- Specified by:
getNoisein interfaceINoise- Parameters:
x- x position; can be any finite floaty- y position; can be any finite floatz- z position; can be any finite floatw- w position; can be any finite floatu- u position; can be any finite floatv- v position; can be any finite float- Returns:
- a noise value between -1.0f and 1.0f, both inclusive
-
getNoiseWithSeed
public float getNoiseWithSeed(float x, float y, float z, float w, float u, float v, long seed) Description copied from interface:INoiseGets 6D noise with a specific seed. If the seed cannot be retrieved or changed per-call, then this falls back to changing the position instead of the seed; you can check if this will happen withINoise.hasEfficientSetSeed().- Specified by:
getNoiseWithSeedin interfaceINoise- Parameters:
x- x position; can be any finite floaty- y position; can be any finite floatz- z position; can be any finite floatw- w position; can be any finite floatu- u position; can be any finite floatv- v position; can be any finite floatseed- can be any long- Returns:
- a noise value between -1.0f and 1.0f, both inclusive
-
equals
-
hashCode
-
toString
-