diff --git a/examples/complexplanet.rs b/examples/complexplanet.rs index 1fb9730e..9284340e 100644 --- a/examples/complexplanet.rs +++ b/examples/complexplanet.rs @@ -1,6 +1,8 @@ extern crate noise; use noise::{core::worley::ReturnType, utils::*, *}; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; mod utils; @@ -63,7 +65,7 @@ mod utils; #[allow(non_snake_case)] fn main() { /// Planet seed. Change this to generate a different planet. - const CURRENT_SEED: u32 = 0; + const CURRENT_SEED: Seed = DEFAULT_SEED; /// Frequency of the planet's continents. Higher frequency produces /// smaller, more numerous continents. This value is measured in radians. @@ -150,6 +152,8 @@ fn main() { /// Maximum depth of the rivers, in planetary elevation units. const RIVER_DEPTH: f64 = 0.0234375; + let mut rng = XorShiftRng::from_seed(CURRENT_SEED); + // //////////////////////////////////////////////////////////////////////// // Function group: continent definition // //////////////////////////////////////////////////////////////////////// @@ -165,107 +169,103 @@ fn main() { // // -1.0 represents the lowest elevations and +1.0 represents the highest // elevations. - // - fn baseContinentDef() -> impl NoiseFn { - // 1: [Continent module]: This FBM module generates the continents. This - // noise function has a high number of octaves so that detail is visible at - // high zoom levels. - let baseContinentDef_fb0 = Fbm::::new(CURRENT_SEED) - .set_frequency(CONTINENT_FREQUENCY) - .set_persistence(0.5) - .set_lacunarity(CONTINENT_LACUNARITY) - .set_octaves(14); - - // debug::render_noise_module("complexplanet_images/00_0_baseContinentDef_fb0\ - // .png", - // &baseContinentDef_fb0, - // 1024, - // 1024, - // 100); - - // 2: [Continent-with-ranges module]: Next, a curve module modifies the - // output value from the continent module so that very high values appear - // near sea level. This defines the positions of the mountain ranges. - let baseContinentDef_cu = Curve::new(baseContinentDef_fb0) - .add_control_point(-2.0000 + SEA_LEVEL, -1.625 + SEA_LEVEL) - .add_control_point(-1.0000 + SEA_LEVEL, -1.375 + SEA_LEVEL) - .add_control_point(0.0000 + SEA_LEVEL, -0.375 + SEA_LEVEL) - .add_control_point(0.0625 + SEA_LEVEL, 0.125 + SEA_LEVEL) - .add_control_point(0.1250 + SEA_LEVEL, 0.250 + SEA_LEVEL) - .add_control_point(0.2500 + SEA_LEVEL, 1.000 + SEA_LEVEL) - .add_control_point(0.5000 + SEA_LEVEL, 0.250 + SEA_LEVEL) - .add_control_point(0.7500 + SEA_LEVEL, 0.250 + SEA_LEVEL) - .add_control_point(1.0000 + SEA_LEVEL, 0.500 + SEA_LEVEL) - .add_control_point(2.0000 + SEA_LEVEL, 0.500 + SEA_LEVEL); - - // debug::render_noise_module("complexplanet_images/00_1_baseContinentDef_cu\ - // .png", - // &baseContinentDef_cu, - // 1024, - // 1024, - // 100); - - // 3: [Carver module]: This higher-frequency BasicMulti module will be - // used by subsequent noise functions to carve out chunks from the - // mountain ranges within the continent-with-ranges module so that the - // mountain ranges will not be completely impassible. - let baseContinentDef_fb1 = Fbm::::new(CURRENT_SEED + 1) - .set_frequency(CONTINENT_FREQUENCY * 4.34375) - .set_persistence(0.5) - .set_lacunarity(CONTINENT_LACUNARITY) - .set_octaves(11); - - // debug::render_noise_module("complexplanet_images/00_2_baseContinentDef_fb1\ - // .png", - // &baseContinentDef_fb1, - // 1024, - // 1024, - // 100); - - // 4: [Scaled-carver module]: This scale/bias module scales the output - // value from the carver module such that it is usually near 1.0. This - // is required for step 5. - let baseContinentDef_sb = ScaleBias::new(baseContinentDef_fb1) - .set_scale(0.375) - .set_bias(0.625); - - // debug::render_noise_module("complexplanet_images/00_3_baseContinentDef_sb\ - // .png", - // &baseContinentDef_sb, - // 1024, - // 1024, - // 100); - - // 5: [Carved-continent module]: This minimum-value module carves out - // chunks from the continent-with-ranges module. it does this by ensuring - // that only the minimum of the output values from the scaled-carver - // module and the continent-with-ranges module contributes to the output - // value of this subgroup. Most of the time, the minimum value module will - // select the output value from the continent-with-ranges module since the - // output value from the scaled-carver is usually near 1.0. Occasionally, - // the output from the scaled-carver module will be less than the output - // value from the continent-with-ranges module, so in this case, the output - // value from the scaled-carver module is selected. - let baseContinentDef_mi = Min::new(baseContinentDef_sb, baseContinentDef_cu); - - // debug::render_noise_module("complexplanet_images/00_4_baseContinentDef_mi\ - // .png", - // &baseContinentDef_mi, - // 1024, - // 1024, - // 100); - - // 6: [Clamped-continent module]: Finally, a clamp module modifies the - // carved continent module to ensure that the output value of this subgroup - // is between -1.0 and 1.0. - let baseContinentDef_cl = Clamp::new(baseContinentDef_mi).set_bounds(-1.0, 1.0); - - // 7: [Base-continent-definition subgroup]: Caches the output value from - // the clamped-continent module. - let baseContinentDef = Cache::new(baseContinentDef_cl); - - baseContinentDef - } + + // 1: [Continent module]: This FBM module generates the continents. This + // noise function has a high number of octaves so that detail is visible at + // high zoom levels. + let baseContinentDef_fb0 = Fbm::::new(rng.gen()) + .set_frequency(CONTINENT_FREQUENCY) + .set_persistence(0.5) + .set_lacunarity(CONTINENT_LACUNARITY) + .set_octaves(14); + + // debug::render_noise_module("complexplanet_images/00_0_baseContinentDef_fb0\ + // .png", + // &baseContinentDef_fb0, + // 1024, + // 1024, + // 100); + + // 2: [Continent-with-ranges module]: Next, a curve module modifies the + // output value from the continent module so that very high values appear + // near sea level. This defines the positions of the mountain ranges. + let baseContinentDef_cu = Curve::new(baseContinentDef_fb0) + .add_control_point(-2.0000 + SEA_LEVEL, -1.625 + SEA_LEVEL) + .add_control_point(-1.0000 + SEA_LEVEL, -1.375 + SEA_LEVEL) + .add_control_point(0.0000 + SEA_LEVEL, -0.375 + SEA_LEVEL) + .add_control_point(0.0625 + SEA_LEVEL, 0.125 + SEA_LEVEL) + .add_control_point(0.1250 + SEA_LEVEL, 0.250 + SEA_LEVEL) + .add_control_point(0.2500 + SEA_LEVEL, 1.000 + SEA_LEVEL) + .add_control_point(0.5000 + SEA_LEVEL, 0.250 + SEA_LEVEL) + .add_control_point(0.7500 + SEA_LEVEL, 0.250 + SEA_LEVEL) + .add_control_point(1.0000 + SEA_LEVEL, 0.500 + SEA_LEVEL) + .add_control_point(2.0000 + SEA_LEVEL, 0.500 + SEA_LEVEL); + + // debug::render_noise_module("complexplanet_images/00_1_baseContinentDef_cu\ + // .png", + // &baseContinentDef_cu, + // 1024, + // 1024, + // 100); + + // 3: [Carver module]: This higher-frequency BasicMulti module will be + // used by subsequent noise functions to carve out chunks from the + // mountain ranges within the continent-with-ranges module so that the + // mountain ranges will not be completely impassible. + let baseContinentDef_fb1 = Fbm::::new(rng.gen()) + .set_frequency(CONTINENT_FREQUENCY * 4.34375) + .set_persistence(0.5) + .set_lacunarity(CONTINENT_LACUNARITY) + .set_octaves(11); + + // debug::render_noise_module("complexplanet_images/00_2_baseContinentDef_fb1\ + // .png", + // &baseContinentDef_fb1, + // 1024, + // 1024, + // 100); + + // 4: [Scaled-carver module]: This scale/bias module scales the output + // value from the carver module such that it is usually near 1.0. This + // is required for step 5. + let baseContinentDef_sb = ScaleBias::new(baseContinentDef_fb1) + .set_scale(0.375) + .set_bias(0.625); + + // debug::render_noise_module("complexplanet_images/00_3_baseContinentDef_sb\ + // .png", + // &baseContinentDef_sb, + // 1024, + // 1024, + // 100); + + // 5: [Carved-continent module]: This minimum-value module carves out + // chunks from the continent-with-ranges module. it does this by ensuring + // that only the minimum of the output values from the scaled-carver + // module and the continent-with-ranges module contributes to the output + // value of this subgroup. Most of the time, the minimum value module will + // select the output value from the continent-with-ranges module since the + // output value from the scaled-carver is usually near 1.0. Occasionally, + // the output from the scaled-carver module will be less than the output + // value from the continent-with-ranges module, so in this case, the output + // value from the scaled-carver module is selected. + let baseContinentDef_mi = Min::new(baseContinentDef_sb, baseContinentDef_cu); + + // debug::render_noise_module("complexplanet_images/00_4_baseContinentDef_mi\ + // .png", + // &baseContinentDef_mi, + // 1024, + // 1024, + // 100); + + // 6: [Clamped-continent module]: Finally, a clamp module modifies the + // carved continent module to ensure that the output value of this subgroup + // is between -1.0 and 1.0. + let baseContinentDef_cl = Clamp::new(baseContinentDef_mi).set_bounds(-1.0, 1.0); + + // 7: [Base-continent-definition subgroup]: Caches the output value from + // the clamped-continent module. + let baseContinentDef = Cache::new(baseContinentDef_cl); // debug::render_noise_module("complexplanet_images/00_5_baseContinentDef.png", // &baseContinentDef, @@ -289,8 +289,8 @@ fn main() { // 1: [Coarse-turbulence module]: This turbulence module warps the output // value from the base-continent-definition subgroup, adding some coarse // detail to it. - let continentDef_tu0 = Turbulence::<_, Perlin>::new(baseContinentDef()) - .set_seed(CURRENT_SEED + 10) + let continentDef_tu0 = Turbulence::<_, Perlin>::new(&baseContinentDef) + .set_seed(rng.gen()) .set_frequency(CONTINENT_FREQUENCY * 15.25) .set_power(CONTINENT_FREQUENCY / 113.75) .set_roughness(13); @@ -306,7 +306,7 @@ fn main() { // higher frequency, but lower power, than the coarse-turbulence module, // adding some intermediate detail to it. let continentDef_tu1 = Turbulence::<_, Perlin>::new(continentDef_tu0) - .set_seed(CURRENT_SEED + 11) + .set_seed(rng.gen()) .set_frequency(CONTINENT_FREQUENCY * 47.25) .set_power(CONTINENT_FREQUENCY / 433.75) .set_roughness(12); @@ -322,7 +322,7 @@ fn main() { // turbulence has a higher frequency, but lower power, than the // intermediate-turbulence module, adding some fine detail to it. let continentDef_tu2 = Turbulence::<_, Perlin>::new(continentDef_tu1) - .set_seed(CURRENT_SEED + 12) + .set_seed(rng.gen()) .set_frequency(CONTINENT_FREQUENCY * 95.25) .set_power(CONTINENT_FREQUENCY / 1019.75) .set_roughness(11); @@ -343,7 +343,7 @@ fn main() { // transition. In effect, only the higher areas of the base-continent- // definition subgroup become warped; the underwater and coastal areas // remain unaffected. - let continentDef_se = Select::new(baseContinentDef(), continentDef_tu2, baseContinentDef()) + let continentDef_se = Select::new(&baseContinentDef, continentDef_tu2, &baseContinentDef) .set_bounds(SEA_LEVEL - 0.0375, SEA_LEVEL + 1000.0375) .set_falloff(0.0625); @@ -390,7 +390,7 @@ fn main() { // areas may now appear in the the ocean, creating rocky islands and // fjords. let terrainTypeDef_tu = Turbulence::<_, Perlin>::new(&continentDef) - .set_seed(CURRENT_SEED + 20) + .set_seed(rng.gen()) .set_frequency(CONTINENT_FREQUENCY * 18.125) .set_power(CONTINENT_FREQUENCY / 20.59375 * TERRAIN_OFFSET) .set_roughness(3); @@ -426,7 +426,7 @@ fn main() { // 1: [Mountain-ridge module]: This ridged-multifractal-noise function // generates the mountain ridges. - let mountainBaseDef_rm0 = RidgedMulti::::new(CURRENT_SEED + 30) + let mountainBaseDef_rm0 = RidgedMulti::::new(rng.gen()) .set_frequency(1723.0) .set_lacunarity(MOUNTAIN_LACUNARITY) .set_octaves(4); @@ -445,7 +445,7 @@ fn main() { // of the valleys. Note that this noise function generates ridged-multifractal // noise using only one octave; this information will be important in the // next step. - let mountainBaseDef_rm1 = RidgedMulti::::new(CURRENT_SEED + 31) + let mountainBaseDef_rm1 = RidgedMulti::::new(rng.gen()) .set_frequency(367.0) .set_lacunarity(MOUNTAIN_LACUNARITY) .set_octaves(1); @@ -481,7 +481,7 @@ fn main() { // value from the mountain-and-valleys module, adding some coarse detail to // it. let mountainBaseDef_tu0 = Turbulence::<_, Perlin>::new(mountainBaseDef_bl) - .set_seed(CURRENT_SEED + 32) + .set_seed(rng.gen()) .set_frequency(1337.0) .set_power(1.0 / 6730.0 * MOUNTAINS_TWIST) .set_roughness(4); @@ -491,7 +491,7 @@ fn main() { // a higher frequency, but lower power, than the coarse-turbulence module, // adding some fine detail to it. let mountainBaseDef_tu1 = Turbulence::<_, Perlin>::new(mountainBaseDef_tu0) - .set_seed(CURRENT_SEED + 33) + .set_seed(rng.gen()) .set_frequency(21221.0) .set_power(1.0 / 120157.0 * MOUNTAINS_TWIST) .set_roughness(6); @@ -513,7 +513,7 @@ fn main() { // 1: [Mountain-basis-0 module]: This ridged-multifractal-noise function, // along with the mountain-basis-1 module, generates the individual // mountains. - let mountainousHigh_rm0 = RidgedMulti::::new(CURRENT_SEED + 40) + let mountainousHigh_rm0 = RidgedMulti::::new(rng.gen()) .set_frequency(2371.0) .set_lacunarity(MOUNTAIN_LACUNARITY) .set_octaves(3); @@ -521,7 +521,7 @@ fn main() { // 2: [Mountain-basis-1 module]: This ridged-multifractal-noise function, // along with the mountain-basis-0 module, generates the individual // mountains. - let mountainousHigh_rm1 = RidgedMulti::::new(CURRENT_SEED + 41) + let mountainousHigh_rm1 = RidgedMulti::::new(rng.gen()) .set_frequency(2341.0) .set_lacunarity(MOUNTAIN_LACUNARITY) .set_octaves(3); @@ -536,7 +536,7 @@ fn main() { // 4: [Warped-high-mountains module]: This turbulence module warps the // output value from the high-mountains module, adding some detail to it. let mountainousHigh_tu = Turbulence::<_, Perlin>::new(mountainousHigh_ma) - .set_seed(CURRENT_SEED + 42) + .set_seed(rng.gen()) .set_frequency(31511.0) .set_power(1.0 / 180371.0 * MOUNTAINS_TWIST) .set_roughness(4); @@ -558,7 +558,7 @@ fn main() { // 1: [Lowland-basis-0 module]: This ridged-multifractal-noise function, // along with the lowland-basis-1 module, produces the low mountainous // terrain. - let mountainousLow_rm0 = RidgedMulti::::new(CURRENT_SEED + 50) + let mountainousLow_rm0 = RidgedMulti::::new(rng.gen()) .set_frequency(1381.0) .set_lacunarity(MOUNTAIN_LACUNARITY) .set_octaves(8); @@ -566,7 +566,7 @@ fn main() { // 1: [Lowland-basis-1 module]: This ridged-multifractal-noise function, // along with the lowland-basis-0 module, produces the low mountainous // terrain. - let mountainousLow_rm1 = RidgedMulti::::new(CURRENT_SEED + 51) + let mountainousLow_rm1 = RidgedMulti::::new(rng.gen()) .set_frequency(1427.0) .set_lacunarity(MOUNTAIN_LACUNARITY) .set_octaves(8); @@ -670,7 +670,7 @@ fn main() { // // 1: [Hills module]: This billow-noise function generates the hills. - let hillyTerrain_bi = Billow::::new(CURRENT_SEED + 60) + let hillyTerrain_bi = Billow::::new(rng.gen()) .set_frequency(1663.0) .set_persistence(0.5) .set_lacunarity(HILLS_LACUNARITY) @@ -687,7 +687,7 @@ fn main() { // appear in between the valleys. Note that this noise function generates // ridged-multifractal noise using only one octave; this information will be // important in the next step. - let hillyTerrain_rm = RidgedMulti::::new(CURRENT_SEED + 61) + let hillyTerrain_rm = RidgedMulti::::new(rng.gen()) .set_frequency(367.5) .set_lacunarity(HILLS_LACUNARITY) .set_octaves(1); @@ -733,7 +733,7 @@ fn main() { // value from the increased-slope-hilly-terrain module, adding some // coarse detail to it. let hillyTerrain_tu0 = Turbulence::<_, Perlin>::new(hillyTerrain_ex) - .set_seed(CURRENT_SEED + 62) + .set_seed(rng.gen()) .set_frequency(1531.0) .set_power(1.0 / 16921.0 * HILLS_TWIST) .set_roughness(4); @@ -743,7 +743,7 @@ fn main() { // higher frequency, but lower power, than the coarse-turbulence module, // adding some fine detail to it. let hillyTerrain_tu1 = Turbulence::<_, Perlin>::new(hillyTerrain_tu0) - .set_seed(CURRENT_SEED + 63) + .set_seed(rng.gen()) .set_frequency(21617.0) .set_power(1.0 / 117529.0 * HILLS_TWIST) .set_roughness(6); @@ -772,7 +772,7 @@ fn main() { // 1: [Plains-basis-0 module]: This billow-noise function, along with the // plains-basis-1 module, produces the plains. - let plainsTerrain_bi0 = Billow::::new(CURRENT_SEED + 70) + let plainsTerrain_bi0 = Billow::::new(rng.gen()) .set_frequency(1097.5) .set_persistence(0.5) .set_lacunarity(PLAINS_LACUNARITY) @@ -788,7 +788,7 @@ fn main() { // 3: [Plains-basis-1 module]: This billow-noise function, along with the // plains-basis-2 module, produces the plains. - let plainsTerrain_bi1 = Billow::::new(CURRENT_SEED + 71) + let plainsTerrain_bi1 = Billow::::new(rng.gen()) .set_frequency(1097.5) .set_persistence(0.5) .set_lacunarity(PLAINS_LACUNARITY) @@ -834,7 +834,7 @@ fn main() { // 1: [Sand-dunes module]: This ridged-multifractal-noise function generates // sand dunes. This ridged-multifractal noise is generated with a single // octave, which makes very smooth dunes. - let badlandsSand_rm = RidgedMulti::::new(CURRENT_SEED + 80) + let badlandsSand_rm = RidgedMulti::::new(rng.gen()) .set_frequency(6163.5) .set_lacunarity(BADLANDS_LACUNARITY) .set_octaves(1); @@ -850,7 +850,7 @@ fn main() { // generate the detail to add to the dunes. By enabling the distance // algorithm, small polygonal pits are generated; the edges of the pits // are joined to the edges of nearby pits. - let badlandsSand_wo = Worley::new(CURRENT_SEED + 81) + let badlandsSand_wo = Worley::new(rng.gen()) .set_frequency(16183.25) .set_return_type(ReturnType::Distance); @@ -881,7 +881,7 @@ fn main() { // 1: [Cliff-basis module]: This Perlin-noise function generates some coherent // noise that will be used to generate the cliffs. - let badlandsCliffs_fb = Fbm::::new(CURRENT_SEED + 90) + let badlandsCliffs_fb = Fbm::::new(rng.gen()) .set_frequency(CONTINENT_FREQUENCY * 839.0) .set_persistence(0.5) .set_lacunarity(BADLANDS_LACUNARITY) @@ -920,7 +920,7 @@ fn main() { // 5: [Coarse-turbulence module]: This turbulence module warps the output // value from the terraced-cliffs module, adding some coarse detail to it. let badlandsCliffs_tu0 = Turbulence::<_, Perlin>::new(badlandsCliffs_te) - .set_seed(CURRENT_SEED + 91) + .set_seed(rng.gen()) .set_frequency(16111.0) .set_power(1.0 / 141539.0 * BADLANDS_TWIST) .set_roughness(3); @@ -930,7 +930,7 @@ fn main() { // frequency, but lower power, than the coarse-turbulence module, adding // some fine detail to it. let badlandsCliffs_tu1 = Turbulence::<_, Perlin>::new(badlandsCliffs_tu0) - .set_seed(CURRENT_SEED + 92) + .set_seed(rng.gen()) .set_frequency(36107.0) .set_power(1.0 / 211543.0 * BADLANDS_TWIST) .set_roughness(3); @@ -991,7 +991,7 @@ fn main() { // 1: [Large-river-basis module]: This ridged-multifractal-noise function // creates the large, deep rivers. - let riverPositions_rm0 = RidgedMulti::::new(CURRENT_SEED + 100) + let riverPositions_rm0 = RidgedMulti::::new(rng.gen()) .set_frequency(18.75) .set_lacunarity(CONTINENT_LACUNARITY) .set_octaves(1); @@ -1011,7 +1011,7 @@ fn main() { // 3: [Small-river-basis module]: This ridged-multifractal-noise function // creates the small, shallow rivers. - let riverPositions_rm1 = RidgedMulti::::new(CURRENT_SEED + 101) + let riverPositions_rm1 = RidgedMulti::::new(rng.gen()) .set_frequency(43.25) .set_lacunarity(CONTINENT_LACUNARITY) .set_octaves(1); @@ -1039,7 +1039,7 @@ fn main() { // from the combined-rivers module, which twists the rivers. The high // roughness produces less-smooth rivers. let riverPositions_tu = Turbulence::<_, Perlin>::new(riverPositions_mi) - .set_seed(CURRENT_SEED + 102) + .set_seed(rng.gen()) .set_frequency(9.25) .set_power(1.0 / 57.75) .set_roughness(6); @@ -1081,7 +1081,7 @@ fn main() { // roughly the same elevation. This BasicMulti module generates some // random values that will be used by subsequent noise functions to randomly // change the elevations of the mountain peaks. - let scaledMountainousTerrain_fb = Fbm::::new(CURRENT_SEED + 110) + let scaledMountainousTerrain_fb = Fbm::::new(rng.gen()) .set_frequency(14.5) .set_persistence(0.5) .set_lacunarity(MOUNTAIN_LACUNARITY) @@ -1147,7 +1147,7 @@ fn main() { // roughly the same elevation. This BasicMulti module generates some // random values that will be used by subsequent noise functions to // randomly change the elevations of the hilltops. - let scaledHillyTerrain_fb = Fbm::::new(CURRENT_SEED + 120) + let scaledHillyTerrain_fb = Fbm::::new(rng.gen()) .set_frequency(13.5) .set_persistence(0.5) .set_lacunarity(HILLS_LACUNARITY) @@ -1302,7 +1302,7 @@ fn main() { // 3: [Oceanic-trench-basis module]: This ridged-multifractal-noise function // generates some coherent noise that will be used to generate the oceanic // trenches. The ridges represent the bottom of the trenches. - let continentalShelf_rm = RidgedMulti::::new(CURRENT_SEED + 130) + let continentalShelf_rm = RidgedMulti::::new(rng.gen()) .set_frequency(CONTINENT_FREQUENCY * 4.375) .set_lacunarity(CONTINENT_LACUNARITY) .set_octaves(16); @@ -1552,7 +1552,7 @@ fn main() { // 1: [Badlands-positions module]: This BasicMulti module generates some // random noise, which is used by subsequent noise functions to specify the // locations of the badlands. - let continentsWithBadlands_bm = Fbm::::new(CURRENT_SEED + 140) + let continentsWithBadlands_bm = Fbm::::new(rng.gen()) .set_frequency(16.5) .set_persistence(0.5) .set_lacunarity(CONTINENT_LACUNARITY) diff --git a/examples/power.rs b/examples/power.rs index 46006ddc..69d928b9 100644 --- a/examples/power.rs +++ b/examples/power.rs @@ -1,12 +1,14 @@ extern crate noise; -use noise::{utils::*, Perlin, Power}; +use noise::{utils::*, Perlin, Power, DEFAULT_SEED}; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; mod utils; fn main() { let perlin1 = Perlin::default(); - let perlin2 = Perlin::new(1); + let perlin2 = Perlin::new(XorShiftRng::from_seed(DEFAULT_SEED).gen()); let power = Power::new(perlin1, perlin2); utils::write_example_to_file(&PlaneMapBuilder::new(power).build(), "power.png"); diff --git a/examples/ridgedmulti.rs b/examples/ridgedmulti.rs index d9b3cff7..2af0a483 100644 --- a/examples/ridgedmulti.rs +++ b/examples/ridgedmulti.rs @@ -2,12 +2,16 @@ extern crate noise; -use noise::{utils::*, Perlin, RidgedMulti, Worley}; +use noise::{utils::*, Perlin, RidgedMulti, Worley, DEFAULT_SEED}; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; mod utils; fn main() { - let ridged_multi = RidgedMulti::::default(); + let mut rng = XorShiftRng::from_seed(DEFAULT_SEED); + + let ridged_multi = RidgedMulti::::new(rng.gen()); utils::write_example_to_file( &PlaneMapBuilder::new(ridged_multi).build(), @@ -21,7 +25,7 @@ fn main() { "ridged_multi_worley.png", ); - let ridged_multi = RidgedMulti::>::default(); + let ridged_multi = RidgedMulti::>::new(rng.gen()); utils::write_example_to_file( &PlaneMapBuilder::new(ridged_multi).build(), diff --git a/examples/texturegranite.rs b/examples/texturegranite.rs index 11db74c1..f93238c1 100644 --- a/examples/texturegranite.rs +++ b/examples/texturegranite.rs @@ -1,20 +1,24 @@ extern crate noise; use noise::{core::worley::ReturnType, utils::*, *}; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; mod utils; fn main() { + let mut rng = XorShiftRng::from_seed(DEFAULT_SEED); + // Primary granite texture. This generates the "roughness" of the texture // when lit by a light source. - let primary_granite = Billow::::new(0) + let primary_granite = Billow::::new(rng.gen()) .set_frequency(8.0) .set_persistence(0.625) .set_lacunarity(2.18359375) .set_octaves(6); // Use Worley polygons to produce the small grains for the granite texture. - let base_grains = Worley::new(1) + let base_grains = Worley::new(rng.gen()) .set_frequency(16.0) .set_return_type(ReturnType::Distance); @@ -28,7 +32,7 @@ fn main() { // Finally, perturb the granite texture to add realism. let final_granite = Turbulence::<_, Perlin>::new(combined_granite) - .set_seed(2) + .set_seed(rng.gen()) .set_frequency(4.0) .set_power(1.0 / 8.0) .set_roughness(6); diff --git a/examples/texturejade.rs b/examples/texturejade.rs index 8c89778f..85a209d1 100644 --- a/examples/texturejade.rs +++ b/examples/texturejade.rs @@ -1,13 +1,17 @@ extern crate noise; use noise::{utils::*, *}; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; mod utils; fn main() { + let mut rng = XorShiftRng::from_seed(DEFAULT_SEED); + // Primary jade texture. The ridges from the ridged-multifractal function // produces the veins. - let primary_jade = RidgedMulti::::new(0) + let primary_jade = RidgedMulti::::new(rng.gen()) .set_frequency(2.0) .set_lacunarity(2.20703125) .set_octaves(6); @@ -24,7 +28,7 @@ fn main() { // Slightly perturb the secondary jade texture for more realism. let perturbed_base_secondary_jade = Turbulence::<_, Perlin>::new(rotated_base_secondary_jade) - .set_seed(1) + .set_seed(rng.gen()) .set_frequency(4.0) .set_power(1.0 / 4.0) .set_roughness(4); @@ -43,7 +47,7 @@ fn main() { // Finally, perturb the combined jade texture to produce the final jade // texture. A low roughness produces nice veins. let final_jade = Turbulence::<_, Perlin>::new(combined_jade) - .set_seed(2) + .set_seed(rng.gen()) .set_frequency(4.0) .set_power(1.0 / 16.0) .set_roughness(2); diff --git a/examples/textureslime.rs b/examples/textureslime.rs index 5ad714d9..f992d00d 100644 --- a/examples/textureslime.rs +++ b/examples/textureslime.rs @@ -1,19 +1,23 @@ extern crate noise; use noise::{utils::*, *}; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; mod utils; fn main() { + let mut rng = XorShiftRng::from_seed(DEFAULT_SEED); + // Large slime bubble texture. - let large_slime = Billow::::new(0) + let large_slime = Billow::::new(rng.gen()) .set_frequency(4.0) .set_lacunarity(2.12109375) .set_octaves(1); // Base of the small slime bubble texture. This texture will eventually // appear inside cracks in the large slime bubble texture. - let small_slime_base = Billow::::new(1) + let small_slime_base = Billow::::new(rng.gen()) .set_frequency(24.0) .set_lacunarity(2.14453125) .set_octaves(1); @@ -25,7 +29,7 @@ fn main() { // Create a map that specifies where the large and small slime bubble // textures will appear in the final texture map. - let slime_map = RidgedMulti::::new(2) + let slime_map = RidgedMulti::::new(rng.gen()) .set_frequency(2.0) .set_lacunarity(2.20703125) .set_octaves(3); @@ -42,7 +46,7 @@ fn main() { // Finally, perturb the slime texture to add realism. let final_slime = Turbulence::<_, Perlin>::new(slime_chooser) - .set_seed(3) + .set_seed(rng.gen()) .set_frequency(8.0) .set_power(1.0 / 32.0) .set_roughness(2); diff --git a/examples/texturewood.rs b/examples/texturewood.rs index 80f31906..9ec290c7 100644 --- a/examples/texturewood.rs +++ b/examples/texturewood.rs @@ -1,15 +1,19 @@ extern crate noise; use noise::{utils::*, *}; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; mod utils; fn main() { + let mut rng = XorShiftRng::from_seed(DEFAULT_SEED); + // Base wood texture. Uses concentric cylinders aligned on the z-axis, like a log. let base_wood = Cylinders::new().set_frequency(16.0); // Basic Multifractal noise to use for the wood grain. - let wood_grain_noise = BasicMulti::::new(0) + let wood_grain_noise = BasicMulti::::new(rng.gen()) .set_frequency(48.0) .set_persistence(0.5) .set_lacunarity(2.20703125) @@ -29,7 +33,7 @@ fn main() { // Slightly perturb the wood to create a more realistic texture. let perturbed_wood = Turbulence::<_, Perlin>::new(combined_wood) - .set_seed(1) + .set_seed(rng.gen()) .set_frequency(4.0) .set_power(1.0 / 256.0) .set_roughness(4); @@ -42,7 +46,7 @@ fn main() { // Finally, perturb the wood texture again to produce the final texture. let final_wood = Turbulence::<_, Perlin>::new(rotated_wood) - .set_seed(2) + .set_seed(rng.gen()) .set_frequency(2.0) .set_power(1.0 / 64.0) .set_roughness(4); diff --git a/src/lib.rs b/src/lib.rs index ffc9deef..ba74ca9b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,9 +3,9 @@ //! # Example //! //! ```rust -//! use noise::{NoiseFn, Perlin, Seedable}; +//! use noise::{NoiseFn, Perlin, Seedable, DEFAULT_SEED}; //! -//! let perlin = Perlin::new(1); +//! let perlin = Perlin::new(DEFAULT_SEED); //! let val = perlin.get([42.4, 37.7, 2.8]); //! ``` diff --git a/src/noise_fns.rs b/src/noise_fns.rs index 03e6a599..3b499d52 100644 --- a/src/noise_fns.rs +++ b/src/noise_fns.rs @@ -50,8 +50,14 @@ where /// Trait for functions that require a seed before generating their values pub trait Seedable { /// Set the seed for the function implementing the `Seedable` trait - fn set_seed(self, seed: u32) -> Self; + fn set_seed(self, seed: Seed) -> Self; /// Getter to retrieve the seed from the function - fn seed(&self) -> u32; + fn seed(&self) -> Seed; } + +pub type Seed = [u8; 16]; + +pub const DEFAULT_SEED: Seed = [ + 0x4f, 0x09, 0xd6, 0x9f, 0x62, 0x9b, 0x09, 0x0c, 0x0c, 0x49, 0x09, 0xfe, 0x6f, 0x1d, 0x4a, 0x38, +]; diff --git a/src/noise_fns/generators/fractals.rs b/src/noise_fns/generators/fractals.rs index 159e4d88..1fd0eeeb 100644 --- a/src/noise_fns/generators/fractals.rs +++ b/src/noise_fns/generators/fractals.rs @@ -7,7 +7,7 @@ mod fbm; mod hybridmulti; mod ridgedmulti; -use crate::Seedable; +use crate::{Seed, Seedable}; /// Trait for `MultiFractal` functions pub trait MultiFractal { @@ -20,14 +20,16 @@ pub trait MultiFractal { fn set_persistence(self, persistence: f64) -> Self; } -fn build_sources(seed: u32, octaves: usize) -> Vec +fn build_sources(seed: Seed, octaves: usize) -> Vec where Source: Default + Seedable, { let mut sources = Vec::with_capacity(octaves); for x in 0..octaves { let source = Source::default(); - sources.push(source.set_seed(seed + x as u32)); + let mut seed = seed; + seed[0] += x as u8; + sources.push(source.set_seed(seed)); } sources } diff --git a/src/noise_fns/generators/fractals/basicmulti.rs b/src/noise_fns/generators/fractals/basicmulti.rs index 69d8ab62..a63a6517 100644 --- a/src/noise_fns/generators/fractals/basicmulti.rs +++ b/src/noise_fns/generators/fractals/basicmulti.rs @@ -1,6 +1,7 @@ use crate::{ math::vectors::*, - noise_fns::{MultiFractal, NoiseFn, Seedable}, + noise_fns::{MultiFractal, NoiseFn, Seedable, DEFAULT_SEED}, + Seed, }; use alloc::vec::Vec; @@ -44,7 +45,8 @@ pub struct BasicMulti { /// persistence produces "rougher" noise. pub persistence: f64, - seed: u32, + seed: Seed, + sources: Vec, scale_factor: f64, } @@ -53,14 +55,13 @@ impl BasicMulti where T: Default + Seedable, { - pub const DEFAULT_SEED: u32 = 0; pub const DEFAULT_OCTAVES: usize = 6; pub const DEFAULT_FREQUENCY: f64 = 2.0; pub const DEFAULT_LACUNARITY: f64 = core::f64::consts::PI * 2.0 / 3.0; pub const DEFAULT_PERSISTENCE: f64 = 0.5; pub const MAX_OCTAVES: usize = 32; - pub fn new(seed: u32) -> Self { + pub fn new(seed: Seed) -> Self { Self { seed, octaves: Self::DEFAULT_OCTAVES, @@ -92,7 +93,7 @@ where T: Default + Seedable, { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } @@ -135,7 +136,7 @@ impl Seedable for BasicMulti where T: Default + Seedable, { - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { if self.seed == seed { return self; } @@ -147,7 +148,7 @@ where } } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/fractals/billow.rs b/src/noise_fns/generators/fractals/billow.rs index d72df0b3..a93288df 100644 --- a/src/noise_fns/generators/fractals/billow.rs +++ b/src/noise_fns/generators/fractals/billow.rs @@ -1,6 +1,7 @@ use crate::{ math::{scale_shift, vectors::*}, - noise_fns::{MultiFractal, NoiseFn, Seedable}, + noise_fns::{MultiFractal, NoiseFn, Seedable, DEFAULT_SEED}, + Seed, }; use alloc::vec::Vec; @@ -41,7 +42,8 @@ pub struct Billow { /// persistence produces "rougher" noise. pub persistence: f64, - seed: u32, + seed: Seed, + sources: Vec, scale_factor: f64, } @@ -50,14 +52,13 @@ impl Billow where T: Default + Seedable, { - pub const DEFAULT_SEED: u32 = 0; pub const DEFAULT_OCTAVE_COUNT: usize = 6; pub const DEFAULT_FREQUENCY: f64 = 1.0; pub const DEFAULT_LACUNARITY: f64 = core::f64::consts::PI * 2.0 / 3.0; pub const DEFAULT_PERSISTENCE: f64 = 0.5; pub const MAX_OCTAVES: usize = 32; - pub fn new(seed: u32) -> Self { + pub fn new(seed: Seed) -> Self { Self { seed, octaves: Self::DEFAULT_OCTAVE_COUNT, @@ -88,7 +89,7 @@ where T: Default + Seedable, { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } @@ -131,7 +132,7 @@ impl Seedable for Billow where T: Default + Seedable, { - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { if self.seed == seed { return self; } @@ -143,7 +144,7 @@ where } } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/fractals/fbm.rs b/src/noise_fns/generators/fractals/fbm.rs index 12238143..2f9c0190 100644 --- a/src/noise_fns/generators/fractals/fbm.rs +++ b/src/noise_fns/generators/fractals/fbm.rs @@ -1,6 +1,7 @@ use crate::{ math::vectors::*, - noise_fns::{MultiFractal, NoiseFn, Seedable}, + noise_fns::{MultiFractal, NoiseFn, Seedable, DEFAULT_SEED}, + Seed, }; use alloc::vec::Vec; @@ -50,7 +51,7 @@ pub struct Fbm { /// persistence produces "rougher" noise. pub persistence: f64, - seed: u32, + seed: Seed, sources: Vec, scale_factor: f64, } @@ -59,14 +60,13 @@ impl Fbm where T: Default + Seedable, { - pub const DEFAULT_SEED: u32 = 0; pub const DEFAULT_OCTAVE_COUNT: usize = 6; pub const DEFAULT_FREQUENCY: f64 = 1.0; pub const DEFAULT_LACUNARITY: f64 = core::f64::consts::PI * 2.0 / 3.0; pub const DEFAULT_PERSISTENCE: f64 = 0.5; pub const MAX_OCTAVES: usize = 32; - pub fn new(seed: u32) -> Self { + pub fn new(seed: Seed) -> Self { Self { seed, octaves: Self::DEFAULT_OCTAVE_COUNT, @@ -97,7 +97,7 @@ where T: Default + Seedable, { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } @@ -140,7 +140,7 @@ impl Seedable for Fbm where T: Default + Seedable, { - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { if self.seed == seed { return self; } @@ -152,7 +152,7 @@ where } } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/fractals/hybridmulti.rs b/src/noise_fns/generators/fractals/hybridmulti.rs index 70db30c4..82498cd3 100644 --- a/src/noise_fns/generators/fractals/hybridmulti.rs +++ b/src/noise_fns/generators/fractals/hybridmulti.rs @@ -1,6 +1,7 @@ use crate::{ math::vectors::*, - noise_fns::{MultiFractal, NoiseFn, Seedable}, + noise_fns::{MultiFractal, NoiseFn, Seedable, DEFAULT_SEED}, + Seed, }; use alloc::vec::Vec; @@ -38,7 +39,7 @@ pub struct HybridMulti { /// persistence produces "rougher" noise. pub persistence: f64, - seed: u32, + seed: Seed, sources: Vec, scale_factor: f64, } @@ -47,14 +48,13 @@ impl HybridMulti where T: Default + Seedable, { - pub const DEFAULT_SEED: u32 = 0; pub const DEFAULT_OCTAVES: usize = 6; pub const DEFAULT_FREQUENCY: f64 = 2.0; pub const DEFAULT_LACUNARITY: f64 = core::f64::consts::PI * 2.0 / 3.0; pub const DEFAULT_PERSISTENCE: f64 = 0.25; pub const MAX_OCTAVES: usize = 32; - pub fn new(seed: u32) -> Self { + pub fn new(seed: Seed) -> Self { Self { seed, octaves: Self::DEFAULT_OCTAVES, @@ -100,7 +100,7 @@ where T: Default + Seedable, { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } @@ -143,7 +143,7 @@ impl Seedable for HybridMulti where T: Default + Seedable, { - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { if self.seed == seed { return self; } @@ -155,7 +155,7 @@ where } } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/fractals/ridgedmulti.rs b/src/noise_fns/generators/fractals/ridgedmulti.rs index 158be7fc..e816ff4e 100644 --- a/src/noise_fns/generators/fractals/ridgedmulti.rs +++ b/src/noise_fns/generators/fractals/ridgedmulti.rs @@ -1,6 +1,7 @@ use crate::{ math::vectors::*, - noise_fns::{MultiFractal, NoiseFn, Seedable}, + noise_fns::{MultiFractal, NoiseFn, Seedable, DEFAULT_SEED}, + Seed, }; use alloc::vec::Vec; @@ -56,7 +57,8 @@ pub struct RidgedMulti { /// half the height of the previous. pub attenuation: f64, - seed: u32, + seed: Seed, + sources: Vec, scale_factor: f64, } @@ -65,7 +67,6 @@ impl RidgedMulti where T: Default + Seedable, { - pub const DEFAULT_SEED: u32 = 0; pub const DEFAULT_OCTAVE_COUNT: usize = 6; pub const DEFAULT_FREQUENCY: f64 = 1.0; pub const DEFAULT_LACUNARITY: f64 = core::f64::consts::PI * 2.0 / 3.0; @@ -73,7 +74,7 @@ where pub const DEFAULT_ATTENUATION: f64 = 2.0; pub const MAX_OCTAVES: usize = 32; - pub fn new(seed: u32) -> Self { + pub fn new(seed: Seed) -> Self { Self { seed, octaves: Self::DEFAULT_OCTAVE_COUNT, @@ -130,7 +131,7 @@ where T: Default + Seedable, { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } @@ -173,7 +174,7 @@ impl Seedable for RidgedMulti where T: Default + Seedable, { - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { if self.seed == seed { return self; } @@ -185,7 +186,7 @@ where } } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/open_simplex.rs b/src/noise_fns/generators/open_simplex.rs index 83ed222a..f6dc9406 100644 --- a/src/noise_fns/generators/open_simplex.rs +++ b/src/noise_fns/generators/open_simplex.rs @@ -2,52 +2,53 @@ //! Instead, these functions use the `OpenSimplex` algorithm, as detailed here: //! +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; + use crate::{ core::open_simplex::{open_simplex_2d, open_simplex_3d, open_simplex_4d}, - noise_fns::{NoiseFn, Seedable}, + noise_fns::{NoiseFn, Seedable, DEFAULT_SEED}, permutationtable::PermutationTable, + Seed, }; /// Noise function that outputs 2/3/4-dimensional Open Simplex noise. #[derive(Clone, Copy, Debug)] pub struct OpenSimplex { - seed: u32, + seed: Seed, perm_table: PermutationTable, } impl OpenSimplex { - const DEFAULT_SEED: u32 = 0; + pub fn new(seed: Seed) -> Self { + let mut rng = XorShiftRng::from_seed(seed); - pub fn new(seed: u32) -> Self { Self { seed, - perm_table: PermutationTable::new(seed), + perm_table: rng.gen(), } } } impl Default for OpenSimplex { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } impl Seedable for OpenSimplex { /// Sets the seed value for Open Simplex noise - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { // If the new seed is the same as the current seed, just return self. if self.seed == seed { return self; } // Otherwise, regenerate the permutation table based on the new seed. - Self { - seed, - perm_table: PermutationTable::new(seed), - } + Self::new(seed) } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/perlin.rs b/src/noise_fns/generators/perlin.rs index 0904107e..76bf27a3 100644 --- a/src/noise_fns/generators/perlin.rs +++ b/src/noise_fns/generators/perlin.rs @@ -1,49 +1,57 @@ +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; + use crate::{ core::perlin::*, - noise_fns::{NoiseFn, Seedable}, + noise_fns::{NoiseFn, Seedable, DEFAULT_SEED}, permutationtable::PermutationTable, + Seed, }; /// Noise function that outputs 1/2/3/4-dimensional Perlin noise. #[derive(Clone, Copy, Debug)] pub struct Perlin { - seed: u32, + seed: Seed, perm_table: PermutationTable, } impl Perlin { pub const DEFAULT_SEED: u32 = 0; - pub fn new(seed: u32) -> Self { + pub fn new(seed: Seed) -> Self { + let mut rng = XorShiftRng::from_seed(seed); + Self { seed, - perm_table: PermutationTable::new(seed), + perm_table: rng.gen(), } } } impl Default for Perlin { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } impl Seedable for Perlin { /// Sets the seed value for Perlin noise - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { // If the new seed is the same as the current seed, just return self. if self.seed == seed { return self; } // Otherwise, regenerate the permutation table based on the new seed. + let mut rng = XorShiftRng::from_seed(seed); + Self { seed, - perm_table: PermutationTable::new(seed), + perm_table: rng.gen(), } } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/perlin_surflet.rs b/src/noise_fns/generators/perlin_surflet.rs index d0c946d1..591c0550 100644 --- a/src/noise_fns/generators/perlin_surflet.rs +++ b/src/noise_fns/generators/perlin_surflet.rs @@ -1,7 +1,11 @@ +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; + use crate::{ core::perlin_surflet::*, - noise_fns::{NoiseFn, Seedable}, + noise_fns::{NoiseFn, Seedable, DEFAULT_SEED}, permutationtable::PermutationTable, + Seed, }; /// Noise function that outputs 2/3/4-dimensional Perlin noise. @@ -10,43 +14,40 @@ use crate::{ /// calculate the values at a point using wavelets instead of interpolated gradients. #[derive(Clone, Copy, Debug)] pub struct PerlinSurflet { - seed: u32, + seed: Seed, perm_table: PermutationTable, } impl PerlinSurflet { - pub const DEFAULT_SEED: u32 = 0; + pub fn new(seed: Seed) -> Self { + let mut rng = XorShiftRng::from_seed(seed); - pub fn new(seed: u32) -> Self { Self { seed, - perm_table: PermutationTable::new(seed), + perm_table: rng.gen(), } } } impl Default for PerlinSurflet { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } impl Seedable for PerlinSurflet { /// Sets the seed value for Perlin noise - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { // If the new seed is the same as the current seed, just return self. if self.seed == seed { return self; } // Otherwise, regenerate the permutation table based on the new seed. - Self { - seed, - perm_table: PermutationTable::new(seed), - } + Self::new(seed) } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/simplex.rs b/src/noise_fns/generators/simplex.rs index 61a5194e..ef5aee94 100644 --- a/src/noise_fns/generators/simplex.rs +++ b/src/noise_fns/generators/simplex.rs @@ -1,50 +1,51 @@ +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; + use crate::{ core::simplex::*, - noise_fns::{NoiseFn, Seedable}, + noise_fns::{NoiseFn, Seedable, DEFAULT_SEED}, permutationtable::PermutationTable, + Seed, }; /// Noise function that outputs N-dimensional Simplex noise. /// #[derive(Clone, Copy, Debug)] pub struct Simplex { - seed: u32, + seed: Seed, hasher: PermutationTable, } impl Simplex { - pub const DEFAULT_SEED: u32 = 0; + pub fn new(seed: Seed) -> Self { + let mut rng = XorShiftRng::from_seed(seed); - pub fn new(seed: u32) -> Self { Simplex { seed, - hasher: PermutationTable::new(seed), + hasher: rng.gen(), } } } impl Default for Simplex { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } impl Seedable for Simplex { /// Sets the seed value for Simplex noise - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { // If the new seed is the same as the current seed, just return self. if self.seed == seed { return self; } // Otherwise, regenerate the permutation table based on the new seed. - Simplex { - seed, - hasher: PermutationTable::new(seed), - } + Simplex::new(seed) } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/super_simplex.rs b/src/noise_fns/generators/super_simplex.rs index f265148f..3def0322 100644 --- a/src/noise_fns/generators/super_simplex.rs +++ b/src/noise_fns/generators/super_simplex.rs @@ -1,49 +1,49 @@ +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; + use crate::{ core::super_simplex::*, - noise_fns::{NoiseFn, Seedable}, + noise_fns::{NoiseFn, Seedable, DEFAULT_SEED}, permutationtable::PermutationTable, + Seed, }; /// Noise function that outputs 2/3-dimensional Super Simplex noise. #[derive(Clone, Copy, Debug)] pub struct SuperSimplex { - seed: u32, + seed: Seed, perm_table: PermutationTable, } impl SuperSimplex { - pub const DEFAULT_SEED: u32 = 0; - - pub fn new(seed: u32) -> Self { + pub fn new(seed: Seed) -> Self { + let mut rng = XorShiftRng::from_seed(seed); Self { seed, - perm_table: PermutationTable::new(seed), + perm_table: rng.gen(), } } } impl Default for SuperSimplex { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } impl Seedable for SuperSimplex { /// Sets the seed value for Super Simplex noise - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { // If the new seed is the same as the current seed, just return self. if self.seed == seed { return self; } // Otherwise, regenerate the permutation table based on the new seed. - Self { - seed, - perm_table: PermutationTable::new(seed), - } + Self::new(seed) } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/value.rs b/src/noise_fns/generators/value.rs index 8d401bfc..474b4197 100644 --- a/src/noise_fns/generators/value.rs +++ b/src/noise_fns/generators/value.rs @@ -1,49 +1,50 @@ +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; + use crate::{ core::value::{value_2d, value_3d, value_4d}, - noise_fns::{NoiseFn, Seedable}, + noise_fns::{NoiseFn, Seedable, DEFAULT_SEED}, permutationtable::PermutationTable, + Seed, }; /// Noise function that outputs 2/3/4-dimensional Value noise. #[derive(Clone, Copy, Debug)] pub struct Value { - seed: u32, + seed: Seed, perm_table: PermutationTable, } impl Value { - pub const DEFAULT_SEED: u32 = 0; + pub fn new(seed: Seed) -> Self { + let mut rng = XorShiftRng::from_seed(seed); - pub fn new(seed: u32) -> Self { Self { seed, - perm_table: PermutationTable::new(seed), + perm_table: rng.gen(), } } } impl Default for Value { fn default() -> Self { - Self::new(Self::DEFAULT_SEED) + Self::new(DEFAULT_SEED) } } impl Seedable for Value { /// Sets the seed value for Value noise - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { // If the new seed is the same as the current seed, just return self. if self.seed == seed { return self; } // Otherwise, regenerate the permutation table based on the new seed. - Self { - seed, - perm_table: PermutationTable::new(seed), - } + Self::new(seed) } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/generators/worley.rs b/src/noise_fns/generators/worley.rs index be7589f1..a33d25ee 100644 --- a/src/noise_fns/generators/worley.rs +++ b/src/noise_fns/generators/worley.rs @@ -1,10 +1,13 @@ use crate::{ core::worley::*, math::vectors::*, - noise_fns::{NoiseFn, Seedable}, + noise_fns::{NoiseFn, Seedable, DEFAULT_SEED}, permutationtable::PermutationTable, + Seed, }; use alloc::rc::Rc; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; /// Noise function that outputs Worley noise. #[derive(Clone)] @@ -20,19 +23,20 @@ pub struct Worley { /// Frequency of the seed points. pub frequency: f64, - seed: u32, + seed: Seed, perm_table: PermutationTable, } type DistanceFunction = dyn Fn(&[f64], &[f64]) -> f64; impl Worley { - pub const DEFAULT_SEED: u32 = 0; pub const DEFAULT_FREQUENCY: f64 = 1.0; - pub fn new(seed: u32) -> Self { + pub fn new(seed: Seed) -> Self { + let mut rng = XorShiftRng::from_seed(seed); + Self { - perm_table: PermutationTable::new(seed), + perm_table: rng.gen(), seed, distance_function: Rc::new(distance_functions::euclidean), return_type: ReturnType::Value, @@ -68,27 +72,29 @@ impl Worley { impl Default for Worley { fn default() -> Self { - Self::new(0) + Self::new(DEFAULT_SEED) } } impl Seedable for Worley { /// Sets the seed value used by the Worley cells. - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { // If the new seed is the same as the current seed, just return self. if self.seed == seed { return self; } // Otherwise, regenerate the permutation table based on the new seed. + let mut rng = XorShiftRng::from_seed(seed); + Self { - perm_table: PermutationTable::new(seed), + perm_table: rng.gen(), seed, ..self } } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } } diff --git a/src/noise_fns/transformers/turbulence.rs b/src/noise_fns/transformers/turbulence.rs index 0d6d16ce..a61cf582 100644 --- a/src/noise_fns/transformers/turbulence.rs +++ b/src/noise_fns/transformers/turbulence.rs @@ -1,4 +1,10 @@ -use crate::noise_fns::{Fbm, MultiFractal, NoiseFn, Seedable}; +use rand::{Rng, SeedableRng}; +use rand_xorshift::XorShiftRng; + +use crate::{ + noise_fns::{Fbm, MultiFractal, NoiseFn, Seedable, DEFAULT_SEED}, + Seed, +}; /// Noise function that randomly displaces the input value before returning the /// output value from the source function. @@ -26,7 +32,8 @@ where /// Affects the roughness of the turbulence. Higher values are rougher. pub roughness: usize, - seed: u32, + seed: Seed, + x_distort_function: Fbm, y_distort_function: Fbm, z_distort_function: Fbm, @@ -37,32 +44,37 @@ impl Turbulence where F: Default + Seedable, { - pub const DEFAULT_SEED: u32 = 0; pub const DEFAULT_FREQUENCY: f64 = 1.0; pub const DEFAULT_POWER: f64 = 1.0; pub const DEFAULT_ROUGHNESS: usize = 3; pub fn new(source: Source) -> Self { + Self::new_with_seed(source, DEFAULT_SEED) + } + + pub fn new_with_seed(source: Source, seed: Seed) -> Self { + let mut rng = XorShiftRng::from_seed(seed); + Self { source, - seed: Self::DEFAULT_SEED, + seed: DEFAULT_SEED, frequency: Self::DEFAULT_FREQUENCY, power: Self::DEFAULT_POWER, roughness: Self::DEFAULT_ROUGHNESS, x_distort_function: Fbm::default() - .set_seed(Self::DEFAULT_SEED) + .set_seed(rng.gen()) .set_octaves(Self::DEFAULT_ROUGHNESS) .set_frequency(Self::DEFAULT_FREQUENCY), y_distort_function: Fbm::default() - .set_seed(Self::DEFAULT_SEED + 1) + .set_seed(rng.gen()) .set_octaves(Self::DEFAULT_ROUGHNESS) .set_frequency(Self::DEFAULT_FREQUENCY), z_distort_function: Fbm::default() - .set_seed(Self::DEFAULT_SEED + 2) + .set_seed(rng.gen()) .set_octaves(Self::DEFAULT_ROUGHNESS) .set_frequency(Self::DEFAULT_FREQUENCY), u_distort_function: Fbm::default() - .set_seed(Self::DEFAULT_SEED + 3) + .set_seed(rng.gen()) .set_octaves(Self::DEFAULT_ROUGHNESS) .set_frequency(Self::DEFAULT_FREQUENCY), } @@ -99,18 +111,20 @@ impl Seedable for Turbulence where F: Default + Seedable, { - fn set_seed(self, seed: u32) -> Self { + fn set_seed(self, seed: Seed) -> Self { + let mut rng = XorShiftRng::from_seed(seed); + Self { seed, - x_distort_function: self.x_distort_function.set_seed(seed), - y_distort_function: self.y_distort_function.set_seed(seed + 1), - z_distort_function: self.z_distort_function.set_seed(seed + 2), - u_distort_function: self.u_distort_function.set_seed(seed + 3), + x_distort_function: self.x_distort_function.set_seed(rng.gen()), + y_distort_function: self.y_distort_function.set_seed(rng.gen()), + z_distort_function: self.z_distort_function.set_seed(rng.gen()), + u_distort_function: self.u_distort_function.set_seed(rng.gen()), ..self } } - fn seed(&self) -> u32 { + fn seed(&self) -> Seed { self.seed } }