├── .gitattributes ├── .github └── workflows │ └── rust.yml ├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── benches ├── open_simplex.rs ├── perlin.rs ├── perlin_surflet.rs ├── simplex.rs ├── super_simplex.rs ├── value.rs ├── worley_2d.rs ├── worley_3d.rs └── worley_4d.rs ├── examples ├── README.md ├── abs.rs ├── add.rs ├── basicmulti.rs ├── billow.rs ├── blend.rs ├── cache.rs ├── checkerboard.rs ├── clamp.rs ├── complexplanet.rs ├── constant.rs ├── curve.rs ├── cylinders.rs ├── displace.rs ├── exponent.rs ├── fbm.rs ├── hybridmulti.rs ├── max.rs ├── min.rs ├── multiply.rs ├── negate.rs ├── open_simplex.rs ├── perlin.rs ├── perlin_surflet.rs ├── power.rs ├── ridgedmulti.rs ├── rotate_point.rs ├── scale_bias.rs ├── scale_point.rs ├── select.rs ├── simplex.rs ├── spheres.rs ├── super_simplex.rs ├── terrace.rs ├── texturegranite.rs ├── texturejade.rs ├── textureslime.rs ├── texturewood.rs ├── translate_point.rs ├── turbulence.rs ├── utils.rs ├── value.rs └── worley.rs ├── images ├── examples │ ├── abs.png │ ├── add.png │ ├── basicmulti_basicmulti_perlin.png │ ├── basicmulti_perlin.png │ ├── basicmulti_worley.png │ ├── billow_billow_perlin.png │ ├── billow_perlin.png │ ├── billow_worley.png │ ├── blend.png │ ├── cache.png │ ├── checkerboard.png │ ├── clamp.png │ ├── constant_-1.png │ ├── constant_0.png │ ├── constant_1.png │ ├── curve.png │ ├── cylinders-f5.png │ ├── cylinders.png │ ├── displace.png │ ├── exponent.png │ ├── fbm_fbm_perlin.png │ ├── fbm_perlin.png │ ├── fbm_worley.png │ ├── hybrid_multi_hybrid_multi_perlin.png │ ├── hybrid_multi_perlin.png │ ├── hybrid_multi_worley.png │ ├── max.png │ ├── min.png │ ├── multiply.png │ ├── negate.png │ ├── open_simplex 2d.png │ ├── open_simplex 3d.png │ ├── open_simplex 4d.png │ ├── perlin surflet 2d.png │ ├── perlin surflet 3d.png │ ├── perlin surflet 4d.png │ ├── perlin_2d.png │ ├── perlin_3d.png │ ├── perlin_4d.png │ ├── power.png │ ├── ridged_multi_perlin.png │ ├── ridged_multi_ridged_multi_perlin.png │ ├── ridged_multi_worley.png │ ├── rotate_point.png │ ├── scale_bias.png │ ├── scale_point.png │ ├── select1.png │ ├── select2.png │ ├── simplex 2d.png │ ├── simplex 3d.png │ ├── simplex 4d.png │ ├── spheres 2d.png │ ├── spheres 3d.png │ ├── spheres 4d.png │ ├── super_simplex 2d.png │ ├── super_simplex 3d.png │ ├── terrace.png │ ├── terrace_inverted.png │ ├── texture_granite_planar.png │ ├── texture_granite_seamless.png │ ├── texture_granite_sphere.png │ ├── texture_jade_planar.png │ ├── texture_jade_seamless.png │ ├── texture_slime_planar.png │ ├── texture_slime_seamless.png │ ├── texture_wood_planar.png │ ├── translate_point.png │ ├── turbulence.png │ ├── unscaledFinalPlanet.png │ ├── unscaledFinalPlanet_16x_zoom.png │ ├── unscaledFinalPlanet_4x_zoom.png │ ├── unscaledFinalPlanet_sphere.png │ ├── value 2d.png │ ├── value 3d.png │ ├── value 4d.png │ └── worley │ │ ├── 2d_chebyshev_distance.png │ │ ├── 2d_chebyshev_value.png │ │ ├── 2d_euclidean_distance.png │ │ ├── 2d_euclidean_squared_distance.png │ │ ├── 2d_euclidean_squared_value.png │ │ ├── 2d_euclidean_value.png │ │ ├── 2d_manhattan_distance.png │ │ ├── 2d_manhattan_value.png │ │ ├── 3d_chebyshev_distance.png │ │ ├── 3d_chebyshev_value.png │ │ ├── 3d_euclidean_distance.png │ │ ├── 3d_euclidean_squared_distance.png │ │ ├── 3d_euclidean_squared_value.png │ │ ├── 3d_euclidean_value.png │ │ ├── 3d_manhattan_distance.png │ │ ├── 3d_manhattan_value.png │ │ ├── 4d_chebyshev_distance.png │ │ ├── 4d_chebyshev_value.png │ │ ├── 4d_euclidean_distance.png │ │ ├── 4d_euclidean_squared_distance.png │ │ ├── 4d_euclidean_squared_value.png │ │ ├── 4d_euclidean_value.png │ │ ├── 4d_manhattan_distance.png │ │ └── 4d_manhattan_value.png ├── fbm.png ├── unscaledFinalPlanet.png ├── unscaledFinalPlanet_16x_zoom.png └── unscaledFinalPlanet_4x_zoom.png └── src ├── core.rs ├── core ├── checkerboard.rs ├── open_simplex.rs ├── perlin.rs ├── perlin_surflet.rs ├── simplex.rs ├── spheres.rs ├── super_simplex.rs ├── value.rs └── worley.rs ├── gradient.rs ├── lib.rs ├── math.rs ├── math ├── interpolate.rs ├── s_curve.rs ├── s_curve │ ├── cubic.rs │ └── quintic.rs └── vectors.rs ├── noise_fns.rs ├── noise_fns ├── cache.rs ├── combiners.rs ├── combiners │ ├── add.rs │ ├── max.rs │ ├── min.rs │ ├── multiply.rs │ └── power.rs ├── generators.rs ├── generators │ ├── checkerboard.rs │ ├── constant.rs │ ├── cylinders.rs │ ├── fractals.rs │ ├── fractals │ │ ├── basicmulti.rs │ │ ├── billow.rs │ │ ├── fbm.rs │ │ ├── hybridmulti.rs │ │ └── ridgedmulti.rs │ ├── open_simplex.rs │ ├── perlin.rs │ ├── perlin_surflet.rs │ ├── simplex.rs │ ├── super_simplex.rs │ ├── value.rs │ └── worley.rs ├── modifiers.rs ├── modifiers │ ├── abs.rs │ ├── clamp.rs │ ├── curve.rs │ ├── exponent.rs │ ├── negate.rs │ ├── scale_bias.rs │ └── terrace.rs ├── selectors.rs ├── selectors │ ├── blend.rs │ └── select.rs ├── transformers.rs └── transformers │ ├── displace.rs │ ├── rotate_point.rs │ ├── scale_point.rs │ ├── translate_point.rs │ └── turbulence.rs ├── permutationtable.rs ├── utils.rs └── utils ├── color_gradient.rs ├── image_renderer.rs ├── noise_image.rs ├── noise_map.rs ├── noise_map_builder.rs └── noise_map_builder ├── cylinder_map.rs ├── plane_map.rs └── sphere_map.rs /.gitattributes: -------------------------------------------------------------------------------- 1 | # same .gitattributes as rust-lang/rust 2 | [attr]rust text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4 3 | 4 | * text=auto eol=lf 5 | *.rs rust 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /doc/ 2 | /target/ 3 | /.idea/ 4 | /.criterion/ 5 | *.iml 6 | Cargo.lock 7 | /example_images/ 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "noise" 3 | description = "Procedural noise generation library." 4 | homepage = "https://github.com/razaekel/noise-rs" 5 | repository = "https://github.com/razaekel/noise-rs" 6 | documentation = "https://docs.rs/noise/" 7 | version = "0.9.0" 8 | license = "Apache-2.0/MIT" 9 | keywords = ["math", "random"] 10 | authors = ["The Noise-rs Developers."] 11 | edition = "2021" 12 | resolver = "2" 13 | exclude = ["images/"] 14 | 15 | [lib] 16 | name = "noise" 17 | 18 | [dependencies] 19 | rand = { version = "0.9", default-features = false } 20 | rand_xorshift = "0.4" 21 | image = { version = "0.25.5", optional = true } 22 | num-traits = "0.2" 23 | 24 | [features] 25 | default = [] 26 | images = ["image", "std"] 27 | std = [] 28 | 29 | [dev-dependencies] 30 | criterion = { version = "0.5.1", features = ["html_reports"] } 31 | rand = { version = "0.9", default-features = true } 32 | rand_pcg = "0.9" 33 | 34 | [[bench]] 35 | name = "open_simplex" 36 | harness = false 37 | 38 | [[bench]] 39 | name = "perlin" 40 | harness = false 41 | 42 | [[bench]] 43 | name = "perlin_surflet" 44 | harness = false 45 | 46 | [[bench]] 47 | name = "simplex" 48 | harness = false 49 | 50 | [[bench]] 51 | name = "super_simplex" 52 | harness = false 53 | 54 | [[bench]] 55 | name = "value" 56 | harness = false 57 | 58 | [[bench]] 59 | name = "worley_2d" 60 | harness = false 61 | 62 | [[bench]] 63 | name = "worley_3d" 64 | harness = false 65 | 66 | [[bench]] 67 | name = "worley_4d" 68 | harness = false 69 | 70 | [[example]] 71 | name = "perlin" 72 | required-features = ["images"] 73 | 74 | [[example]] 75 | name = "perlin_surflet" 76 | required-features = ["images"] 77 | 78 | [[example]] 79 | name = "open_simplex" 80 | required-features = ["images"] 81 | 82 | [[example]] 83 | name = "super_simplex" 84 | required-features = ["images"] 85 | 86 | [[example]] 87 | name = "value" 88 | required-features = ["images"] 89 | 90 | [[example]] 91 | name = "constant" 92 | required-features = ["images"] 93 | 94 | [[example]] 95 | name = "checkerboard" 96 | required-features = ["images"] 97 | 98 | [[example]] 99 | name = "cylinders" 100 | required-features = ["images"] 101 | 102 | [[example]] 103 | name = "select" 104 | required-features = ["images"] 105 | 106 | [[example]] 107 | name = "blend" 108 | required-features = ["images"] 109 | 110 | [[example]] 111 | name = "abs" 112 | required-features = ["images"] 113 | 114 | [[example]] 115 | name = "clamp" 116 | required-features = ["images"] 117 | 118 | [[example]] 119 | name = "curve" 120 | required-features = ["images"] 121 | 122 | [[example]] 123 | name = "exponent" 124 | required-features = ["images"] 125 | 126 | [[example]] 127 | name = "negate" 128 | required-features = ["images"] 129 | 130 | [[example]] 131 | name = "scale_bias" 132 | required-features = ["images"] 133 | 134 | [[example]] 135 | name = "terrace" 136 | required-features = ["images"] 137 | 138 | [[example]] 139 | name = "add" 140 | required-features = ["images"] 141 | 142 | [[example]] 143 | name = "max" 144 | required-features = ["images"] 145 | 146 | [[example]] 147 | name = "min" 148 | required-features = ["images"] 149 | 150 | [[example]] 151 | name = "multiply" 152 | required-features = ["images"] 153 | 154 | [[example]] 155 | name = "power" 156 | required-features = ["images"] 157 | 158 | [[example]] 159 | name = "fbm" 160 | required-features = ["images"] 161 | 162 | [[example]] 163 | name = "billow" 164 | required-features = ["images"] 165 | 166 | [[example]] 167 | name = "basicmulti" 168 | required-features = ["images"] 169 | 170 | [[example]] 171 | name = "ridgedmulti" 172 | required-features = ["images"] 173 | 174 | [[example]] 175 | name = "hybridmulti" 176 | required-features = ["images"] 177 | 178 | [[example]] 179 | name = "cache" 180 | required-features = ["images"] 181 | 182 | [[example]] 183 | name = "worley" 184 | required-features = ["images"] 185 | 186 | [[example]] 187 | name = "displace" 188 | required-features = ["images"] 189 | 190 | [[example]] 191 | name = "rotate_point" 192 | required-features = ["images"] 193 | 194 | [[example]] 195 | name = "scale_point" 196 | required-features = ["images"] 197 | 198 | [[example]] 199 | name = "translate_point" 200 | required-features = ["images"] 201 | 202 | [[example]] 203 | name = "turbulence" 204 | required-features = ["images"] 205 | 206 | [[example]] 207 | name = "texturewood" 208 | required-features = ["images"] 209 | 210 | [[example]] 211 | name = "texturejade" 212 | required-features = ["images"] 213 | 214 | [[example]] 215 | name = "texturegranite" 216 | required-features = ["images"] 217 | 218 | [[example]] 219 | name = "textureslime" 220 | required-features = ["images"] 221 | 222 | [[example]] 223 | name = "complexplanet" 224 | required-features = ["images"] 225 | 226 | [[example]] 227 | name = "simplex" 228 | required-features = ["images"] 229 | 230 | [[example]] 231 | name = "spheres" 232 | required-features = ["images"] 233 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 The Noise-rs Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /benches/open_simplex.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate criterion; 3 | extern crate noise; 4 | 5 | use criterion::{black_box, Criterion}; 6 | use noise::{ 7 | core::open_simplex::{open_simplex_2d, open_simplex_3d, open_simplex_4d}, 8 | math::vectors::{Vector2, Vector3, Vector4}, 9 | permutationtable::PermutationTable, 10 | }; 11 | 12 | criterion_group!( 13 | open_simplex, 14 | bench_open_simplex2, 15 | bench_open_simplex3, 16 | bench_open_simplex4 17 | ); 18 | criterion_group!( 19 | open_simplex_64x64, 20 | bench_open_simplex2_64x64, 21 | bench_open_simplex3_64x64, 22 | bench_open_simplex4_64x64 23 | ); 24 | criterion_main!(open_simplex, open_simplex_64x64); 25 | 26 | fn bench_open_simplex2(c: &mut Criterion) { 27 | let hasher = PermutationTable::new(0); 28 | c.bench_function("open simplex 2d", |b| { 29 | b.iter(|| open_simplex_2d(black_box(Vector2::new(42.0_f64, 37.0)), &hasher)) 30 | }); 31 | } 32 | 33 | fn bench_open_simplex3(c: &mut Criterion) { 34 | let hasher = PermutationTable::new(0); 35 | c.bench_function("open simplex 3d", |b| { 36 | b.iter(|| open_simplex_3d(black_box(Vector3::new(42.0_f64, 37.0, 26.0)), &hasher)) 37 | }); 38 | } 39 | 40 | fn bench_open_simplex4(c: &mut Criterion) { 41 | let hasher = PermutationTable::new(0); 42 | c.bench_function("open simplex 4d", |b| { 43 | b.iter(|| { 44 | open_simplex_4d( 45 | black_box(Vector4::new(42.0_f64, 37.0, 26.0, 128.0)), 46 | &hasher, 47 | ) 48 | }) 49 | }); 50 | } 51 | 52 | fn bench_open_simplex2_64x64(c: &mut Criterion) { 53 | let hasher = PermutationTable::new(0); 54 | c.bench_function("open simplex 2d (64x64)", |b| { 55 | b.iter(|| { 56 | for y in 0i8..64 { 57 | for x in 0i8..64 { 58 | open_simplex_2d(black_box(Vector2::new(x as f64, y as f64)), &hasher); 59 | } 60 | } 61 | }) 62 | }); 63 | } 64 | 65 | fn bench_open_simplex3_64x64(c: &mut Criterion) { 66 | let hasher = PermutationTable::new(0); 67 | c.bench_function("open simplex 3d (64x64)", |b| { 68 | b.iter(|| { 69 | for y in 0i8..64 { 70 | for x in 0i8..64 { 71 | open_simplex_3d( 72 | black_box(Vector3::new(x as f64, y as f64, x as f64)), 73 | &hasher, 74 | ); 75 | } 76 | } 77 | }) 78 | }); 79 | } 80 | 81 | fn bench_open_simplex4_64x64(c: &mut Criterion) { 82 | let hasher = PermutationTable::new(0); 83 | c.bench_function("open simplex 4d (64x64)", |b| { 84 | b.iter(|| { 85 | for y in 0i8..64 { 86 | for x in 0i8..64 { 87 | open_simplex_4d( 88 | black_box(Vector4::new(x as f64, y as f64, x as f64, y as f64)), 89 | &hasher, 90 | ); 91 | } 92 | } 93 | }) 94 | }); 95 | } 96 | -------------------------------------------------------------------------------- /benches/perlin.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate criterion; 3 | extern crate noise; 4 | 5 | use criterion::{black_box, Criterion}; 6 | use noise::{ 7 | core::perlin::{perlin_1d, perlin_2d, perlin_3d, perlin_4d}, 8 | permutationtable::PermutationTable, 9 | Vector2, Vector3, Vector4, 10 | }; 11 | 12 | criterion_group!( 13 | perlin, 14 | bench_perlin1, 15 | bench_perlin2, 16 | bench_perlin3, 17 | bench_perlin4 18 | ); 19 | criterion_group!( 20 | perlin_64x64, 21 | bench_perlin2_64x64, 22 | bench_perlin3_64x64, 23 | bench_perlin4_64x64 24 | ); 25 | criterion_main!(perlin, perlin_64x64); 26 | 27 | fn bench_perlin1(c: &mut Criterion) { 28 | let hasher = PermutationTable::new(0); 29 | c.bench_function("perlin 1d", |b| { 30 | b.iter(|| perlin_1d(black_box(42.0_f64), &hasher)) 31 | }); 32 | } 33 | 34 | fn bench_perlin2(c: &mut Criterion) { 35 | let hasher = PermutationTable::new(0); 36 | c.bench_function("perlin 2d", |b| { 37 | b.iter(|| perlin_2d(black_box(Vector2::new(42.0_f64, 37.0)), &hasher)) 38 | }); 39 | } 40 | 41 | fn bench_perlin3(c: &mut Criterion) { 42 | let hasher = PermutationTable::new(0); 43 | c.bench_function("perlin 3d", |b| { 44 | b.iter(|| perlin_3d(black_box(Vector3::new(42.0_f64, 37.0, 26.0)), &hasher)) 45 | }); 46 | } 47 | 48 | fn bench_perlin4(c: &mut Criterion) { 49 | let hasher = PermutationTable::new(0); 50 | c.bench_function("perlin 4d", |b| { 51 | b.iter(|| { 52 | perlin_4d( 53 | black_box(Vector4::new(42.0_f64, 37.0, 26.0, 128.0)), 54 | &hasher, 55 | ) 56 | }) 57 | }); 58 | } 59 | 60 | fn bench_perlin2_64x64(c: &mut Criterion) { 61 | let hasher = PermutationTable::new(0); 62 | c.bench_function("perlin 2d (64x64)", |b| { 63 | b.iter(|| { 64 | for y in 0i8..64 { 65 | for x in 0i8..64 { 66 | perlin_2d(black_box(Vector2::new(x as f64, y as f64)), &hasher); 67 | } 68 | } 69 | }) 70 | }); 71 | } 72 | 73 | fn bench_perlin3_64x64(c: &mut Criterion) { 74 | let hasher = PermutationTable::new(0); 75 | c.bench_function("perlin 3d (64x64)", |b| { 76 | b.iter(|| { 77 | for y in 0i8..64 { 78 | for x in 0i8..64 { 79 | perlin_3d( 80 | black_box(Vector3::new(x as f64, y as f64, x as f64)), 81 | &hasher, 82 | ); 83 | } 84 | } 85 | }) 86 | }); 87 | } 88 | 89 | fn bench_perlin4_64x64(c: &mut Criterion) { 90 | let hasher = PermutationTable::new(0); 91 | c.bench_function("perlin 4d (64x64)", |b| { 92 | b.iter(|| { 93 | for y in 0i8..64 { 94 | for x in 0i8..64 { 95 | perlin_4d( 96 | black_box(Vector4::new(x as f64, y as f64, x as f64, y as f64)), 97 | &hasher, 98 | ); 99 | } 100 | } 101 | }) 102 | }); 103 | } 104 | -------------------------------------------------------------------------------- /benches/perlin_surflet.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate criterion; 3 | extern crate noise; 4 | 5 | use criterion::{black_box, Criterion}; 6 | use noise::{ 7 | core::perlin_surflet::{perlin_surflet_2d, perlin_surflet_3d, perlin_surflet_4d}, 8 | math::vectors::{Vector2, Vector3, Vector4}, 9 | permutationtable::PermutationTable, 10 | }; 11 | 12 | criterion_group!( 13 | perlin_surflet, 14 | bench_perlin_surflet2, 15 | bench_perlin_surflet3, 16 | bench_perlin_surflet4 17 | ); 18 | criterion_group!( 19 | perlin_surflet_64x64, 20 | bench_perlin_surflet2_64x64, 21 | bench_perlin_surflet3_64x64, 22 | bench_perlin_surflet4_64x64 23 | ); 24 | criterion_main!(perlin_surflet, perlin_surflet_64x64); 25 | 26 | fn bench_perlin_surflet2(c: &mut Criterion) { 27 | let hasher = PermutationTable::new(0); 28 | c.bench_function("perlin surflet 2d", |b| { 29 | b.iter(|| perlin_surflet_2d(black_box(Vector2::new(42.0_f64, 37.0)), &hasher)) 30 | }); 31 | } 32 | 33 | fn bench_perlin_surflet3(c: &mut Criterion) { 34 | let hasher = PermutationTable::new(0); 35 | c.bench_function("perlin surflet 3d", |b| { 36 | b.iter(|| perlin_surflet_3d(black_box(Vector3::new(42.0_f64, 37.0, 26.0)), &hasher)) 37 | }); 38 | } 39 | 40 | fn bench_perlin_surflet4(c: &mut Criterion) { 41 | let hasher = PermutationTable::new(0); 42 | c.bench_function("perlin surflet 4d", |b| { 43 | b.iter(|| { 44 | perlin_surflet_4d( 45 | black_box(Vector4::new(42.0_f64, 37.0, 26.0, 128.0)), 46 | &hasher, 47 | ) 48 | }) 49 | }); 50 | } 51 | 52 | fn bench_perlin_surflet2_64x64(c: &mut Criterion) { 53 | let hasher = PermutationTable::new(0); 54 | c.bench_function("perlin surflet 2d (64x64)", |b| { 55 | b.iter(|| { 56 | for y in 0i8..64 { 57 | for x in 0i8..64 { 58 | perlin_surflet_2d(black_box(Vector2::new(x as f64, y as f64)), &hasher); 59 | } 60 | } 61 | }) 62 | }); 63 | } 64 | 65 | fn bench_perlin_surflet3_64x64(c: &mut Criterion) { 66 | let hasher = PermutationTable::new(0); 67 | c.bench_function("perlin surflet 3d (64x64)", |b| { 68 | b.iter(|| { 69 | for y in 0i8..64 { 70 | for x in 0i8..64 { 71 | perlin_surflet_3d( 72 | black_box(Vector3::new(x as f64, y as f64, x as f64)), 73 | &hasher, 74 | ); 75 | } 76 | } 77 | }) 78 | }); 79 | } 80 | 81 | fn bench_perlin_surflet4_64x64(c: &mut Criterion) { 82 | let hasher = PermutationTable::new(0); 83 | c.bench_function("perlin surflet 4d (64x64)", |b| { 84 | b.iter(|| { 85 | for y in 0i8..64 { 86 | for x in 0i8..64 { 87 | perlin_surflet_4d( 88 | black_box(Vector4::new(x as f64, y as f64, x as f64, y as f64)), 89 | &hasher, 90 | ); 91 | } 92 | } 93 | }) 94 | }); 95 | } 96 | -------------------------------------------------------------------------------- /benches/simplex.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate criterion; 3 | extern crate noise; 4 | 5 | use criterion::{black_box, Criterion}; 6 | use noise::{ 7 | core::simplex::{simplex_2d, simplex_3d, simplex_4d}, 8 | permutationtable::PermutationTable, 9 | }; 10 | 11 | criterion_group!(simplex, bench_simplex2, bench_simplex3, bench_simplex4); 12 | criterion_group!( 13 | simplex_64x64, 14 | bench_simplex2_64x64, 15 | bench_simplex3_64x64, 16 | bench_simplex4_64x64 17 | ); 18 | criterion_main!(simplex, simplex_64x64); 19 | 20 | fn bench_simplex2(c: &mut Criterion) { 21 | let hasher = PermutationTable::new(0); 22 | c.bench_function("simplex 2d", |b| { 23 | b.iter(|| simplex_2d(black_box([42.0_f64, 37.0].into()), &hasher)) 24 | }); 25 | } 26 | 27 | fn bench_simplex3(c: &mut Criterion) { 28 | let hasher = PermutationTable::new(0); 29 | c.bench_function("simplex 3d", |b| { 30 | b.iter(|| simplex_3d(black_box([42.0_f64, 37.0, 26.0].into()), &hasher)) 31 | }); 32 | } 33 | 34 | fn bench_simplex4(c: &mut Criterion) { 35 | let hasher = PermutationTable::new(0); 36 | c.bench_function("simplex 4d", |b| { 37 | b.iter(|| simplex_4d(black_box([42.0_f64, 37.0, 26.0, 128.0].into()), &hasher)) 38 | }); 39 | } 40 | 41 | fn bench_simplex2_64x64(c: &mut Criterion) { 42 | let hasher = PermutationTable::new(0); 43 | c.bench_function("simplex 2d (64x64)", |b| { 44 | b.iter(|| { 45 | for y in 0i8..64 { 46 | for x in 0i8..64 { 47 | black_box(simplex_2d([x as f64, y as f64].into(), &hasher)); 48 | } 49 | } 50 | }) 51 | }); 52 | } 53 | 54 | fn bench_simplex3_64x64(c: &mut Criterion) { 55 | let hasher = PermutationTable::new(0); 56 | c.bench_function("simplex 3d (64x64)", |b| { 57 | b.iter(|| { 58 | for y in 0i8..64 { 59 | for x in 0i8..64 { 60 | black_box(simplex_3d([x as f64, y as f64, x as f64].into(), &hasher)); 61 | } 62 | } 63 | }) 64 | }); 65 | } 66 | 67 | fn bench_simplex4_64x64(c: &mut Criterion) { 68 | let hasher = PermutationTable::new(0); 69 | c.bench_function("simplex 4d (64x64)", |b| { 70 | b.iter(|| { 71 | for y in 0i8..64 { 72 | for x in 0i8..64 { 73 | black_box(simplex_4d( 74 | [x as f64, y as f64, x as f64, y as f64].into(), 75 | &hasher, 76 | )); 77 | } 78 | } 79 | }) 80 | }); 81 | } 82 | -------------------------------------------------------------------------------- /benches/super_simplex.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate criterion; 3 | extern crate noise; 4 | 5 | use criterion::{black_box, Criterion}; 6 | use noise::{ 7 | core::super_simplex::{super_simplex_2d, super_simplex_3d}, 8 | math::vectors::{Vector2, Vector3}, 9 | permutationtable::PermutationTable, 10 | }; 11 | 12 | criterion_group!(super_simplex, bench_super_simplex2, bench_super_simplex3,); 13 | criterion_group!( 14 | super_simplex_64x64, 15 | bench_super_simplex2_64x64, 16 | bench_super_simplex3_64x64, 17 | ); 18 | criterion_main!(super_simplex, super_simplex_64x64); 19 | 20 | fn bench_super_simplex2(c: &mut Criterion) { 21 | let hasher = PermutationTable::new(0); 22 | c.bench_function("super simplex 2d", |b| { 23 | b.iter(|| super_simplex_2d(black_box(Vector2::new(42.0_f64, 37.0)), &hasher)) 24 | }); 25 | } 26 | 27 | fn bench_super_simplex3(c: &mut Criterion) { 28 | let hasher = PermutationTable::new(0); 29 | c.bench_function("super simplex 3d", |b| { 30 | b.iter(|| super_simplex_3d(black_box(Vector3::new(42.0_f64, 37.0, 26.0)), &hasher)) 31 | }); 32 | } 33 | 34 | fn bench_super_simplex2_64x64(c: &mut Criterion) { 35 | let hasher = PermutationTable::new(0); 36 | c.bench_function("super simplex 2d (64x64)", |b| { 37 | b.iter(|| { 38 | for y in 0i8..64 { 39 | for x in 0i8..64 { 40 | super_simplex_2d(black_box(Vector2::new(x as f64, y as f64)), &hasher); 41 | } 42 | } 43 | }) 44 | }); 45 | } 46 | 47 | fn bench_super_simplex3_64x64(c: &mut Criterion) { 48 | let hasher = PermutationTable::new(0); 49 | c.bench_function("super simplex 3d (64x64)", |b| { 50 | b.iter(|| { 51 | for y in 0i8..64 { 52 | for x in 0i8..64 { 53 | super_simplex_3d( 54 | black_box(Vector3::new(x as f64, y as f64, x as f64)), 55 | &hasher, 56 | ); 57 | } 58 | } 59 | }) 60 | }); 61 | } 62 | -------------------------------------------------------------------------------- /benches/value.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate criterion; 3 | extern crate noise; 4 | 5 | use criterion::{black_box, Criterion}; 6 | use noise::{ 7 | core::value::{value_2d, value_3d, value_4d}, 8 | math::vectors::{Vector2, Vector3, Vector4}, 9 | permutationtable::PermutationTable, 10 | }; 11 | 12 | criterion_group!(value, bench_value2, bench_value3, bench_value4); 13 | criterion_group!( 14 | value_64x64, 15 | bench_value2_64x64, 16 | bench_value3_64x64, 17 | bench_value4_64x64 18 | ); 19 | criterion_main!(value, value_64x64); 20 | 21 | fn bench_value2(c: &mut Criterion) { 22 | let hasher = PermutationTable::new(0); 23 | c.bench_function("value 2d", |b| { 24 | b.iter(|| black_box(value_2d(Vector2::new(42.0_f64, 37.0), &hasher))) 25 | }); 26 | } 27 | 28 | fn bench_value3(c: &mut Criterion) { 29 | let hasher = PermutationTable::new(0); 30 | c.bench_function("value 3d", |b| { 31 | b.iter(|| black_box(value_3d(Vector3::new(42.0_f64, 37.0, 26.0), &hasher))) 32 | }); 33 | } 34 | 35 | fn bench_value4(c: &mut Criterion) { 36 | let hasher = PermutationTable::new(0); 37 | c.bench_function("value 4d", |b| { 38 | b.iter(|| black_box(value_4d(Vector4::new(42.0_f64, 37.0, 26.0, 128.0), &hasher))) 39 | }); 40 | } 41 | 42 | fn bench_value2_64x64(c: &mut Criterion) { 43 | let hasher = PermutationTable::new(0); 44 | c.bench_function("value 2d (64x64)", |b| { 45 | b.iter(|| { 46 | for y in 0i8..64 { 47 | for x in 0i8..64 { 48 | black_box(value_2d(Vector2::new(x as f64, y as f64), &hasher)); 49 | } 50 | } 51 | }) 52 | }); 53 | } 54 | 55 | fn bench_value3_64x64(c: &mut Criterion) { 56 | let hasher = PermutationTable::new(0); 57 | c.bench_function("value 3d (64x64)", |b| { 58 | b.iter(|| { 59 | for y in 0i8..64 { 60 | for x in 0i8..64 { 61 | black_box(value_3d( 62 | Vector3::new(x as f64, y as f64, x as f64), 63 | &hasher, 64 | )); 65 | } 66 | } 67 | }) 68 | }); 69 | } 70 | 71 | fn bench_value4_64x64(c: &mut Criterion) { 72 | let hasher = PermutationTable::new(0); 73 | c.bench_function("value 4d (64x64)", |b| { 74 | b.iter(|| { 75 | for y in 0i8..64 { 76 | for x in 0i8..64 { 77 | black_box(value_4d( 78 | Vector4::new(x as f64, y as f64, x as f64, y as f64), 79 | &hasher, 80 | )); 81 | } 82 | } 83 | }) 84 | }); 85 | } 86 | -------------------------------------------------------------------------------- /benches/worley_2d.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate criterion; 3 | extern crate noise; 4 | 5 | use criterion::{black_box, Criterion}; 6 | use noise::{ 7 | core::worley::{distance_functions::*, worley_2d, ReturnType}, 8 | math::vectors::Vector2, 9 | permutationtable::PermutationTable, 10 | }; 11 | 12 | criterion_group!( 13 | bench_worley_2d, 14 | bench_worley2d_euclidean_value, 15 | bench_worley2d_euclidean_range, 16 | bench_worley2d_squared_value, 17 | bench_worley2d_squared_range, 18 | bench_worley2d_manhattan_value, 19 | bench_worley2d_manhattan_range, 20 | bench_worley2d_chebyshev_value, 21 | bench_worley2d_chebyshev_range, 22 | ); 23 | criterion_group!( 24 | bench_worley_2d_64x64, 25 | bench_worley2d_euclidean_value_64x64, 26 | bench_worley2d_euclidean_range_64x64, 27 | bench_worley2d_squared_value_64x64, 28 | bench_worley2d_squared_range_64x64, 29 | bench_worley2d_manhattan_value_64x64, 30 | bench_worley2d_manhattan_range_64x64, 31 | bench_worley2d_chebyshev_value_64x64, 32 | bench_worley2d_chebyshev_range_64x64, 33 | ); 34 | criterion_main!(bench_worley_2d, bench_worley_2d_64x64); 35 | 36 | fn bench_worley2d(c: &mut Criterion, distance_function: &F, return_type: ReturnType, name: &str) 37 | where 38 | F: Fn(&[f64], &[f64]) -> f64, 39 | { 40 | let hasher = PermutationTable::new(0); 41 | c.bench_function(format!("worley 2d {}", name).as_str(), |b| { 42 | b.iter(|| { 43 | worley_2d( 44 | &hasher, 45 | distance_function, 46 | return_type, 47 | black_box(Vector2::new(42.0f64, 37.0)), 48 | ) 49 | }) 50 | }); 51 | } 52 | 53 | fn bench_worley2d_64x64( 54 | c: &mut Criterion, 55 | distance_function: &F, 56 | return_type: ReturnType, 57 | name: &str, 58 | ) where 59 | F: Fn(&[f64], &[f64]) -> f64, 60 | { 61 | let hasher = PermutationTable::new(0); 62 | c.bench_function(format!("worley 2d {} (64x64)", name).as_str(), |b| { 63 | b.iter(|| { 64 | for y in 0i8..64 { 65 | for x in 0i8..64 { 66 | black_box(worley_2d( 67 | &hasher, 68 | distance_function, 69 | return_type, 70 | Vector2::new(x as f64, y as f64), 71 | )); 72 | } 73 | } 74 | }) 75 | }); 76 | } 77 | 78 | fn bench_worley2d_euclidean_value(c: &mut Criterion) { 79 | bench_worley2d(c, &euclidean, ReturnType::Value, "euclidean value"); 80 | } 81 | 82 | fn bench_worley2d_euclidean_range(c: &mut Criterion) { 83 | bench_worley2d(c, &euclidean, ReturnType::Distance, "euclidean distance"); 84 | } 85 | 86 | fn bench_worley2d_squared_value(c: &mut Criterion) { 87 | bench_worley2d(c, &euclidean_squared, ReturnType::Value, "squared value"); 88 | } 89 | 90 | fn bench_worley2d_squared_range(c: &mut Criterion) { 91 | bench_worley2d( 92 | c, 93 | &euclidean_squared, 94 | ReturnType::Distance, 95 | "squared distance", 96 | ); 97 | } 98 | 99 | fn bench_worley2d_manhattan_value(c: &mut Criterion) { 100 | bench_worley2d(c, &manhattan, ReturnType::Value, "manhattan value"); 101 | } 102 | 103 | fn bench_worley2d_manhattan_range(c: &mut Criterion) { 104 | bench_worley2d(c, &manhattan, ReturnType::Distance, "manhattan distance"); 105 | } 106 | 107 | fn bench_worley2d_chebyshev_value(c: &mut Criterion) { 108 | bench_worley2d(c, &chebyshev, ReturnType::Value, "chebyshev value"); 109 | } 110 | 111 | fn bench_worley2d_chebyshev_range(c: &mut Criterion) { 112 | bench_worley2d(c, &chebyshev, ReturnType::Distance, "chebyshev distance"); 113 | } 114 | 115 | fn bench_worley2d_euclidean_value_64x64(c: &mut Criterion) { 116 | bench_worley2d_64x64(c, &euclidean, ReturnType::Value, "euclidean value"); 117 | } 118 | 119 | fn bench_worley2d_euclidean_range_64x64(c: &mut Criterion) { 120 | bench_worley2d_64x64(c, &euclidean, ReturnType::Distance, "euclidean distance"); 121 | } 122 | 123 | fn bench_worley2d_squared_value_64x64(c: &mut Criterion) { 124 | bench_worley2d_64x64(c, &euclidean_squared, ReturnType::Value, "squared value"); 125 | } 126 | 127 | fn bench_worley2d_squared_range_64x64(c: &mut Criterion) { 128 | bench_worley2d_64x64( 129 | c, 130 | &euclidean_squared, 131 | ReturnType::Distance, 132 | "squared distance", 133 | ); 134 | } 135 | 136 | fn bench_worley2d_manhattan_value_64x64(c: &mut Criterion) { 137 | bench_worley2d_64x64(c, &manhattan, ReturnType::Value, "manhattan value"); 138 | } 139 | 140 | fn bench_worley2d_manhattan_range_64x64(c: &mut Criterion) { 141 | bench_worley2d_64x64(c, &manhattan, ReturnType::Distance, "manhattan distance"); 142 | } 143 | 144 | fn bench_worley2d_chebyshev_value_64x64(c: &mut Criterion) { 145 | bench_worley2d_64x64(c, &chebyshev, ReturnType::Value, "chebyshev value"); 146 | } 147 | 148 | fn bench_worley2d_chebyshev_range_64x64(c: &mut Criterion) { 149 | bench_worley2d_64x64(c, &chebyshev, ReturnType::Distance, "chebyshev distance"); 150 | } 151 | -------------------------------------------------------------------------------- /benches/worley_3d.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate criterion; 3 | extern crate noise; 4 | 5 | use criterion::{black_box, Criterion}; 6 | use noise::{ 7 | core::worley::{distance_functions::*, worley_3d, ReturnType}, 8 | math::vectors::Vector3, 9 | permutationtable::PermutationTable, 10 | }; 11 | 12 | criterion_group!( 13 | bench_worley_3d, 14 | bench_worley3d_euclidean_value, 15 | bench_worley3d_euclidean_range, 16 | bench_worley3d_squared_value, 17 | bench_worley3d_squared_range, 18 | bench_worley3d_manhattan_value, 19 | bench_worley3d_manhattan_range, 20 | bench_worley3d_chebyshev_value, 21 | bench_worley3d_chebyshev_range, 22 | ); 23 | criterion_group!( 24 | bench_worley_3d_64x64, 25 | bench_worley3d_euclidean_value_64x64, 26 | bench_worley3d_euclidean_range_64x64, 27 | bench_worley3d_squared_value_64x64, 28 | bench_worley3d_squared_range_64x64, 29 | bench_worley3d_manhattan_value_64x64, 30 | bench_worley3d_manhattan_range_64x64, 31 | bench_worley3d_chebyshev_value_64x64, 32 | bench_worley3d_chebyshev_range_64x64, 33 | ); 34 | criterion_main!(bench_worley_3d, bench_worley_3d_64x64); 35 | 36 | fn bench_worley3d(c: &mut Criterion, distance_function: &F, return_type: ReturnType, name: &str) 37 | where 38 | F: Fn(&[f64], &[f64]) -> f64, 39 | { 40 | let hasher = PermutationTable::new(0); 41 | c.bench_function(format!("worley 3d {}", name).as_str(), |b| { 42 | b.iter(|| { 43 | worley_3d( 44 | &hasher, 45 | distance_function, 46 | return_type, 47 | black_box(Vector3::new(42.0f64, 37.0, 26.0)), 48 | ) 49 | }) 50 | }); 51 | } 52 | 53 | fn bench_worley3d_64x64( 54 | c: &mut Criterion, 55 | distance_function: &F, 56 | return_type: ReturnType, 57 | name: &str, 58 | ) where 59 | F: Fn(&[f64], &[f64]) -> f64, 60 | { 61 | let hasher = PermutationTable::new(0); 62 | c.bench_function(format!("worley 3d {} (64x64)", name).as_str(), |b| { 63 | b.iter(|| { 64 | for y in 0i8..64 { 65 | for x in 0i8..64 { 66 | black_box(worley_3d( 67 | &hasher, 68 | distance_function, 69 | return_type, 70 | Vector3::new(x as f64, y as f64, x as f64), 71 | )); 72 | } 73 | } 74 | }) 75 | }); 76 | } 77 | 78 | fn bench_worley3d_euclidean_value(c: &mut Criterion) { 79 | bench_worley3d(c, &euclidean, ReturnType::Value, "euclidean value"); 80 | } 81 | 82 | fn bench_worley3d_euclidean_range(c: &mut Criterion) { 83 | bench_worley3d(c, &euclidean, ReturnType::Distance, "euclidean distance"); 84 | } 85 | 86 | fn bench_worley3d_squared_value(c: &mut Criterion) { 87 | bench_worley3d(c, &euclidean_squared, ReturnType::Value, "squared value"); 88 | } 89 | 90 | fn bench_worley3d_squared_range(c: &mut Criterion) { 91 | bench_worley3d( 92 | c, 93 | &euclidean_squared, 94 | ReturnType::Distance, 95 | "squared distance", 96 | ); 97 | } 98 | 99 | fn bench_worley3d_manhattan_value(c: &mut Criterion) { 100 | bench_worley3d(c, &manhattan, ReturnType::Value, "manhattan value"); 101 | } 102 | 103 | fn bench_worley3d_manhattan_range(c: &mut Criterion) { 104 | bench_worley3d(c, &manhattan, ReturnType::Distance, "manhattan distance"); 105 | } 106 | 107 | fn bench_worley3d_chebyshev_value(c: &mut Criterion) { 108 | bench_worley3d(c, &chebyshev, ReturnType::Value, "chebyshev value"); 109 | } 110 | 111 | fn bench_worley3d_chebyshev_range(c: &mut Criterion) { 112 | bench_worley3d(c, &chebyshev, ReturnType::Distance, "chebyshev distance"); 113 | } 114 | 115 | fn bench_worley3d_euclidean_value_64x64(c: &mut Criterion) { 116 | bench_worley3d_64x64(c, &euclidean, ReturnType::Value, "euclidean value"); 117 | } 118 | 119 | fn bench_worley3d_euclidean_range_64x64(c: &mut Criterion) { 120 | bench_worley3d_64x64(c, &euclidean, ReturnType::Distance, "euclidean distance"); 121 | } 122 | 123 | fn bench_worley3d_squared_value_64x64(c: &mut Criterion) { 124 | bench_worley3d_64x64(c, &euclidean_squared, ReturnType::Value, "squared value"); 125 | } 126 | 127 | fn bench_worley3d_squared_range_64x64(c: &mut Criterion) { 128 | bench_worley3d_64x64( 129 | c, 130 | &euclidean_squared, 131 | ReturnType::Distance, 132 | "squared distance", 133 | ); 134 | } 135 | 136 | fn bench_worley3d_manhattan_value_64x64(c: &mut Criterion) { 137 | bench_worley3d_64x64(c, &manhattan, ReturnType::Value, "manhattan value"); 138 | } 139 | 140 | fn bench_worley3d_manhattan_range_64x64(c: &mut Criterion) { 141 | bench_worley3d_64x64(c, &manhattan, ReturnType::Distance, "manhattan distance"); 142 | } 143 | 144 | fn bench_worley3d_chebyshev_value_64x64(c: &mut Criterion) { 145 | bench_worley3d_64x64(c, &chebyshev, ReturnType::Value, "chebyshev value"); 146 | } 147 | 148 | fn bench_worley3d_chebyshev_range_64x64(c: &mut Criterion) { 149 | bench_worley3d_64x64(c, &chebyshev, ReturnType::Distance, "chebyshev distance"); 150 | } 151 | -------------------------------------------------------------------------------- /benches/worley_4d.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate criterion; 3 | extern crate noise; 4 | 5 | use criterion::{black_box, Criterion}; 6 | use noise::{ 7 | core::worley::{distance_functions::*, worley_4d, ReturnType}, 8 | math::vectors::Vector4, 9 | permutationtable::PermutationTable, 10 | }; 11 | 12 | criterion_group!( 13 | bench_worley_4d, 14 | bench_worley4d_euclidean_value, 15 | bench_worley4d_euclidean_range, 16 | bench_worley4d_squared_value, 17 | bench_worley4d_squared_range, 18 | bench_worley4d_manhattan_value, 19 | bench_worley4d_manhattan_range, 20 | bench_worley4d_chebyshev_value, 21 | bench_worley4d_chebyshev_range, 22 | ); 23 | criterion_group!( 24 | bench_worley_4d_64x64, 25 | bench_worley4d_euclidean_value_64x64, 26 | bench_worley4d_euclidean_range_64x64, 27 | bench_worley4d_squared_value_64x64, 28 | bench_worley4d_squared_range_64x64, 29 | bench_worley4d_manhattan_value_64x64, 30 | bench_worley4d_manhattan_range_64x64, 31 | bench_worley4d_chebyshev_value_64x64, 32 | bench_worley4d_chebyshev_range_64x64, 33 | ); 34 | criterion_main!(bench_worley_4d, bench_worley_4d_64x64); 35 | 36 | fn bench_worley4d(c: &mut Criterion, distance_function: &F, return_type: ReturnType, name: &str) 37 | where 38 | F: Fn(&[f64], &[f64]) -> f64, 39 | { 40 | let hasher = PermutationTable::new(0); 41 | c.bench_function(format!("worley 4d {}", name).as_str(), |b| { 42 | b.iter(|| { 43 | worley_4d( 44 | &hasher, 45 | distance_function, 46 | return_type, 47 | black_box(Vector4::new(42.0f64, 37.0, 26.0, 128.0)), 48 | ) 49 | }) 50 | }); 51 | } 52 | 53 | fn bench_worley4d_64x64( 54 | c: &mut Criterion, 55 | distance_function: &F, 56 | return_type: ReturnType, 57 | name: &str, 58 | ) where 59 | F: Fn(&[f64], &[f64]) -> f64, 60 | { 61 | let hasher = PermutationTable::new(0); 62 | c.bench_function(format!("worley 4d {} (64x64)", name).as_str(), |b| { 63 | b.iter(|| { 64 | for y in 0i8..64 { 65 | for x in 0i8..64 { 66 | black_box(worley_4d( 67 | &hasher, 68 | distance_function, 69 | return_type, 70 | Vector4::new(x as f64, y as f64, x as f64, y as f64), 71 | )); 72 | } 73 | } 74 | }) 75 | }); 76 | } 77 | 78 | fn bench_worley4d_euclidean_value(c: &mut Criterion) { 79 | bench_worley4d(c, &euclidean, ReturnType::Value, "euclidean value"); 80 | } 81 | 82 | fn bench_worley4d_euclidean_range(c: &mut Criterion) { 83 | bench_worley4d(c, &euclidean, ReturnType::Distance, "euclidean distance"); 84 | } 85 | 86 | fn bench_worley4d_squared_value(c: &mut Criterion) { 87 | bench_worley4d(c, &euclidean_squared, ReturnType::Value, "squared value"); 88 | } 89 | 90 | fn bench_worley4d_squared_range(c: &mut Criterion) { 91 | bench_worley4d( 92 | c, 93 | &euclidean_squared, 94 | ReturnType::Distance, 95 | "squared distance", 96 | ); 97 | } 98 | 99 | fn bench_worley4d_manhattan_value(c: &mut Criterion) { 100 | bench_worley4d(c, &manhattan, ReturnType::Value, "manhattan value"); 101 | } 102 | 103 | fn bench_worley4d_manhattan_range(c: &mut Criterion) { 104 | bench_worley4d(c, &manhattan, ReturnType::Distance, "manhattan distance"); 105 | } 106 | 107 | fn bench_worley4d_chebyshev_value(c: &mut Criterion) { 108 | bench_worley4d(c, &chebyshev, ReturnType::Value, "chebyshev value"); 109 | } 110 | 111 | fn bench_worley4d_chebyshev_range(c: &mut Criterion) { 112 | bench_worley4d(c, &chebyshev, ReturnType::Distance, "chebyshev distance"); 113 | } 114 | 115 | fn bench_worley4d_euclidean_value_64x64(c: &mut Criterion) { 116 | bench_worley4d_64x64(c, &euclidean, ReturnType::Value, "euclidean value"); 117 | } 118 | 119 | fn bench_worley4d_euclidean_range_64x64(c: &mut Criterion) { 120 | bench_worley4d_64x64(c, &euclidean, ReturnType::Distance, "euclidean distance"); 121 | } 122 | 123 | fn bench_worley4d_squared_value_64x64(c: &mut Criterion) { 124 | bench_worley4d_64x64(c, &euclidean_squared, ReturnType::Value, "squared value"); 125 | } 126 | 127 | fn bench_worley4d_squared_range_64x64(c: &mut Criterion) { 128 | bench_worley4d_64x64( 129 | c, 130 | &euclidean_squared, 131 | ReturnType::Distance, 132 | "squared distance", 133 | ); 134 | } 135 | 136 | fn bench_worley4d_manhattan_value_64x64(c: &mut Criterion) { 137 | bench_worley4d_64x64(c, &manhattan, ReturnType::Value, "manhattan value"); 138 | } 139 | 140 | fn bench_worley4d_manhattan_range_64x64(c: &mut Criterion) { 141 | bench_worley4d_64x64(c, &manhattan, ReturnType::Distance, "manhattan distance"); 142 | } 143 | 144 | fn bench_worley4d_chebyshev_value_64x64(c: &mut Criterion) { 145 | bench_worley4d_64x64(c, &chebyshev, ReturnType::Value, "chebyshev value"); 146 | } 147 | 148 | fn bench_worley4d_chebyshev_range_64x64(c: &mut Criterion) { 149 | bench_worley4d_64x64(c, &chebyshev, ReturnType::Distance, "chebyshev distance"); 150 | } 151 | -------------------------------------------------------------------------------- /examples/abs.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Abs, Perlin}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let perlin = Perlin::default(); 9 | let abs = Abs::new(perlin); 10 | 11 | utils::write_example_to_file(&PlaneMapBuilder::new(abs).build(), "abs.png"); 12 | } 13 | -------------------------------------------------------------------------------- /examples/add.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Add, Cylinders, Perlin}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let cyl = Cylinders::new(); 9 | let perlin = Perlin::default(); 10 | 11 | let add = Add::new(cyl, perlin); 12 | 13 | utils::write_example_to_file(&PlaneMapBuilder::new(add).build(), "add.png"); 14 | } 15 | -------------------------------------------------------------------------------- /examples/basicmulti.rs: -------------------------------------------------------------------------------- 1 | //! An example of using the `BasicMulti` noise function 2 | 3 | extern crate noise; 4 | 5 | use noise::{utils::*, BasicMulti, Perlin, Worley}; 6 | 7 | mod utils; 8 | 9 | fn main() { 10 | let basicmulti = BasicMulti::::default(); 11 | 12 | utils::write_example_to_file( 13 | &PlaneMapBuilder::new(basicmulti).build(), 14 | "basicmulti_perlin.png", 15 | ); 16 | 17 | let basicmulti = BasicMulti::::default(); 18 | 19 | utils::write_example_to_file( 20 | &PlaneMapBuilder::new(basicmulti).build(), 21 | "basicmulti_worley.png", 22 | ); 23 | 24 | let basicmulti = BasicMulti::>::default(); 25 | 26 | utils::write_example_to_file( 27 | &PlaneMapBuilder::new(basicmulti).build(), 28 | "basicmulti_basicmulti_perlin.png", 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /examples/billow.rs: -------------------------------------------------------------------------------- 1 | //! An example of using the Billow noise function 2 | 3 | extern crate noise; 4 | 5 | use noise::{utils::*, Billow, Perlin, Worley}; 6 | 7 | mod utils; 8 | 9 | fn main() { 10 | let billow = Billow::::default(); 11 | 12 | utils::write_example_to_file(&PlaneMapBuilder::new(billow).build(), "billow_perlin.png"); 13 | 14 | let billow = Billow::::default(); 15 | 16 | utils::write_example_to_file(&PlaneMapBuilder::new(billow).build(), "billow_worley.png"); 17 | 18 | let billow = Billow::>::default(); 19 | 20 | utils::write_example_to_file( 21 | &PlaneMapBuilder::new(billow).build(), 22 | "billow_billow_perlin.png", 23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /examples/blend.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Blend, Fbm, Perlin, RidgedMulti}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let perlin = Perlin::default(); 9 | let ridged = RidgedMulti::::default(); 10 | let fbm = Fbm::::default(); 11 | let blend = Blend::new(perlin, ridged, fbm); 12 | 13 | utils::write_example_to_file(&PlaneMapBuilder::new(blend).build(), "blend.png"); 14 | } 15 | -------------------------------------------------------------------------------- /examples/cache.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Cache, Checkerboard}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let cboard = Checkerboard::default(); 9 | let cache = Cache::new(cboard); 10 | 11 | utils::write_example_to_file(&PlaneMapBuilder::new(cache).build(), "cache.png"); 12 | } 13 | -------------------------------------------------------------------------------- /examples/checkerboard.rs: -------------------------------------------------------------------------------- 1 | //! An example of generating constant valued noise 2 | 3 | extern crate noise; 4 | 5 | use noise::{utils::*, Checkerboard}; 6 | 7 | mod utils; 8 | 9 | fn main() { 10 | let checker = Checkerboard::new(0); 11 | 12 | utils::write_example_to_file( 13 | &PlaneMapBuilder::new(checker) 14 | .set_x_bounds(-5.0, 5.0) 15 | .set_y_bounds(-5.0, 5.0) 16 | .build(), 17 | "checkerboard.png", 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /examples/clamp.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Clamp, Perlin}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let perlin = Perlin::default(); 9 | let clamp = Clamp::new(perlin).set_lower_bound(0.0).set_upper_bound(0.5); 10 | 11 | utils::write_example_to_file(&PlaneMapBuilder::new(clamp).build(), "clamp.png"); 12 | } 13 | -------------------------------------------------------------------------------- /examples/constant.rs: -------------------------------------------------------------------------------- 1 | //! An example of generating constant valued noise 2 | 3 | extern crate noise; 4 | 5 | use noise::{utils::*, Constant}; 6 | 7 | mod utils; 8 | 9 | fn main() { 10 | utils::write_example_to_file( 11 | &PlaneMapBuilder::new(Constant::new(-1.0)).build(), 12 | "constant_-1.png", 13 | ); 14 | utils::write_example_to_file( 15 | &PlaneMapBuilder::new(Constant::new(0.0)).build(), 16 | "constant_0.png", 17 | ); 18 | utils::write_example_to_file( 19 | &PlaneMapBuilder::new(Constant::new(1.0)).build(), 20 | "constant_1.png", 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /examples/curve.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Curve, Perlin}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let perlin = Perlin::default(); 9 | let curve = Curve::new(perlin) 10 | .add_control_point(-2.0, -2.0) 11 | .add_control_point(-1.0, -1.25) 12 | .add_control_point(0.0, -0.75) 13 | .add_control_point(0.5, -0.25) 14 | .add_control_point(0.625, 0.875) 15 | .add_control_point(0.75, 1.0) 16 | .add_control_point(2.0, 1.25); 17 | 18 | utils::write_example_to_file(&PlaneMapBuilder::new(curve).build(), "curve.png"); 19 | } 20 | -------------------------------------------------------------------------------- /examples/cylinders.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Cylinders}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | utils::write_example_to_file( 9 | &PlaneMapBuilder::new(Cylinders::new()).build(), 10 | "cylinders.png", 11 | ); 12 | 13 | utils::write_example_to_file( 14 | &PlaneMapBuilder::new(Cylinders::new().set_frequency(5.0)).build(), 15 | "cylinders-f5.png", 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /examples/displace.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Checkerboard, Constant, Cylinders, Displace, Perlin}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let cboard = Checkerboard::default(); 9 | let constant = Constant::new(0.0); 10 | let cylinders = Cylinders::new(); 11 | let perlin = Perlin::default(); 12 | let displace = Displace::new(cylinders, cboard, perlin, constant, constant); 13 | 14 | utils::write_example_to_file(&PlaneMapBuilder::new(displace).build(), "displace.png"); 15 | } 16 | -------------------------------------------------------------------------------- /examples/exponent.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Exponent, Perlin}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let perlin = Perlin::default(); 9 | let exponent = Exponent::new(perlin).set_exponent(3.0); 10 | 11 | utils::write_example_to_file(&PlaneMapBuilder::new(exponent).build(), "exponent.png"); 12 | } 13 | -------------------------------------------------------------------------------- /examples/fbm.rs: -------------------------------------------------------------------------------- 1 | //! An example of using the fBm noise function 2 | 3 | extern crate noise; 4 | 5 | use noise::{utils::*, Fbm, Perlin, Worley}; 6 | 7 | mod utils; 8 | 9 | fn main() { 10 | let fbm = Fbm::::default(); 11 | 12 | utils::write_example_to_file( 13 | &PlaneMapBuilder::new(fbm) 14 | .set_size(1000, 1000) 15 | .set_x_bounds(-5.0, 5.0) 16 | .set_y_bounds(-5.0, 5.0) 17 | .build(), 18 | "fbm_perlin.png", 19 | ); 20 | 21 | let fbm = Fbm::::default(); 22 | 23 | utils::write_example_to_file( 24 | &PlaneMapBuilder::new(fbm) 25 | .set_size(1000, 1000) 26 | .set_x_bounds(-5.0, 5.0) 27 | .set_y_bounds(-5.0, 5.0) 28 | .build(), 29 | "fbm_worley.png", 30 | ); 31 | 32 | let fbm = Fbm::>::default(); 33 | 34 | utils::write_example_to_file( 35 | &PlaneMapBuilder::new(fbm) 36 | .set_size(1000, 1000) 37 | .set_x_bounds(-5.0, 5.0) 38 | .set_y_bounds(-5.0, 5.0) 39 | .build(), 40 | "fbm_fbm_perlin.png", 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /examples/hybridmulti.rs: -------------------------------------------------------------------------------- 1 | //! An example of using the `HybridMulti` noise function 2 | 3 | extern crate noise; 4 | 5 | use noise::{utils::*, HybridMulti, Perlin, Worley}; 6 | 7 | mod utils; 8 | 9 | fn main() { 10 | let hybrid_multi = HybridMulti::::default(); 11 | 12 | utils::write_example_to_file( 13 | &PlaneMapBuilder::new(hybrid_multi).build(), 14 | "hybrid_multi_perlin.png", 15 | ); 16 | 17 | let hybrid_multi = HybridMulti::::default(); 18 | 19 | utils::write_example_to_file( 20 | &PlaneMapBuilder::new(hybrid_multi).build(), 21 | "hybrid_multi_worley.png", 22 | ); 23 | 24 | let hybrid_multi = HybridMulti::>::default(); 25 | 26 | utils::write_example_to_file( 27 | &PlaneMapBuilder::new(hybrid_multi).build(), 28 | "hybrid_multi_hybrid_multi_perlin.png", 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /examples/max.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Cylinders, Max, Perlin}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let cyl = Cylinders::new(); 9 | let perlin = Perlin::default(); 10 | let max = Max::new(cyl, perlin); 11 | 12 | utils::write_example_to_file(&PlaneMapBuilder::new(max).build(), "max.png"); 13 | } 14 | -------------------------------------------------------------------------------- /examples/min.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Cylinders, Min, Perlin}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let cyl = Cylinders::new(); 9 | let perlin = Perlin::default(); 10 | let min = Min::new(cyl, perlin); 11 | 12 | utils::write_example_to_file(&PlaneMapBuilder::new(min).build(), "min.png"); 13 | } 14 | -------------------------------------------------------------------------------- /examples/multiply.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Cylinders, Multiply, Perlin}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let cyl = Cylinders::new(); 9 | let perlin = Perlin::default(); 10 | let multiply = Multiply::new(cyl, perlin); 11 | 12 | utils::write_example_to_file(&PlaneMapBuilder::new(multiply).build(), "multiply.png"); 13 | } 14 | -------------------------------------------------------------------------------- /examples/negate.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Abs, Negate, Perlin}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let perlin = Perlin::default(); 9 | let abs = Abs::new(perlin); 10 | 11 | utils::write_example_to_file( 12 | &PlaneMapBuilder::new(Negate::new(abs)).build(), 13 | "negate.png", 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /examples/open_simplex.rs: -------------------------------------------------------------------------------- 1 | //! An example of using simplex noise 2 | 3 | extern crate noise; 4 | 5 | use noise::{ 6 | core::open_simplex::{open_simplex_2d, open_simplex_3d, open_simplex_4d}, 7 | permutationtable::PermutationTable, 8 | utils::*, 9 | }; 10 | 11 | mod utils; 12 | 13 | fn main() { 14 | let hasher = PermutationTable::new(0); 15 | 16 | utils::write_example_to_file( 17 | &PlaneMapBuilder::new_fn(|point| open_simplex_2d(point.into(), &hasher)) 18 | .set_size(1024, 1024) 19 | .set_x_bounds(-5.0, 5.0) 20 | .set_y_bounds(-5.0, 5.0) 21 | .build(), 22 | "open_simplex 2d.png", 23 | ); 24 | 25 | utils::write_example_to_file( 26 | &PlaneMapBuilder::new_fn(|point| open_simplex_3d(point.into(), &hasher)) 27 | .set_size(1024, 1024) 28 | .set_x_bounds(-5.0, 5.0) 29 | .set_y_bounds(-5.0, 5.0) 30 | .build(), 31 | "open_simplex 3d.png", 32 | ); 33 | 34 | utils::write_example_to_file( 35 | &PlaneMapBuilder::new_fn(|point| open_simplex_4d(point.into(), &hasher)) 36 | .set_size(1024, 1024) 37 | .set_x_bounds(-5.0, 5.0) 38 | .set_y_bounds(-5.0, 5.0) 39 | .build(), 40 | "open_simplex 4d.png", 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /examples/perlin.rs: -------------------------------------------------------------------------------- 1 | //! An example of using perlin noise 2 | 3 | extern crate noise; 4 | 5 | use noise::{ 6 | core::perlin::{perlin_2d, perlin_3d, perlin_4d}, 7 | permutationtable::PermutationTable, 8 | utils::*, 9 | }; 10 | 11 | mod utils; 12 | 13 | fn main() { 14 | let hasher = PermutationTable::new(0); 15 | utils::write_example_to_file( 16 | &PlaneMapBuilder::new_fn(|point| perlin_2d(point.into(), &hasher)) 17 | .set_size(1024, 1024) 18 | .set_x_bounds(-5.0, 5.0) 19 | .set_y_bounds(-5.0, 5.0) 20 | .build(), 21 | "perlin_2d.png", 22 | ); 23 | 24 | utils::write_example_to_file( 25 | &PlaneMapBuilder::new_fn(|point| perlin_3d(point.into(), &hasher)) 26 | .set_size(1024, 1024) 27 | .set_x_bounds(-5.0, 5.0) 28 | .set_y_bounds(-5.0, 5.0) 29 | .build(), 30 | "perlin_3d.png", 31 | ); 32 | 33 | utils::write_example_to_file( 34 | &PlaneMapBuilder::new_fn(|point| perlin_4d(point.into(), &hasher)) 35 | .set_size(1024, 1024) 36 | .set_x_bounds(-5.0, 5.0) 37 | .set_y_bounds(-5.0, 5.0) 38 | .build(), 39 | "perlin_4d.png", 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /examples/perlin_surflet.rs: -------------------------------------------------------------------------------- 1 | //! An example of using perlin_surflet noise 2 | 3 | extern crate noise; 4 | 5 | use noise::{ 6 | core::perlin_surflet::{perlin_surflet_2d, perlin_surflet_3d, perlin_surflet_4d}, 7 | permutationtable::PermutationTable, 8 | utils::*, 9 | }; 10 | 11 | mod utils; 12 | 13 | fn main() { 14 | let hasher = PermutationTable::new(0); 15 | 16 | utils::write_example_to_file( 17 | &PlaneMapBuilder::new_fn(|point| perlin_surflet_2d(point.into(), &hasher)) 18 | .set_size(1024, 1024) 19 | .set_x_bounds(-5.0, 5.0) 20 | .set_y_bounds(-5.0, 5.0) 21 | .build(), 22 | "perlin surflet 2d.png", 23 | ); 24 | 25 | utils::write_example_to_file( 26 | &PlaneMapBuilder::new_fn(|point| perlin_surflet_3d(point.into(), &hasher)) 27 | .set_size(1024, 1024) 28 | .set_x_bounds(-5.0, 5.0) 29 | .set_y_bounds(-5.0, 5.0) 30 | .build(), 31 | "perlin surflet 3d.png", 32 | ); 33 | 34 | utils::write_example_to_file( 35 | &PlaneMapBuilder::new_fn(|point| perlin_surflet_4d(point.into(), &hasher)) 36 | .set_size(1024, 1024) 37 | .set_x_bounds(-5.0, 5.0) 38 | .set_y_bounds(-5.0, 5.0) 39 | .build(), 40 | "perlin surflet 4d.png", 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /examples/power.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Perlin, Power}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let perlin1 = Perlin::default(); 9 | let perlin2 = Perlin::new(1); 10 | let power = Power::new(perlin1, perlin2); 11 | 12 | utils::write_example_to_file(&PlaneMapBuilder::new(power).build(), "power.png"); 13 | } 14 | -------------------------------------------------------------------------------- /examples/ridgedmulti.rs: -------------------------------------------------------------------------------- 1 | //! An example of using the `RidgedMulti` noise function 2 | 3 | extern crate noise; 4 | 5 | use noise::{utils::*, Perlin, RidgedMulti, Worley}; 6 | 7 | mod utils; 8 | 9 | fn main() { 10 | let ridged_multi = RidgedMulti::::default(); 11 | 12 | utils::write_example_to_file( 13 | &PlaneMapBuilder::new(ridged_multi).build(), 14 | "ridged_multi_perlin.png", 15 | ); 16 | 17 | let ridged_multi = RidgedMulti::::default(); 18 | 19 | utils::write_example_to_file( 20 | &PlaneMapBuilder::new(ridged_multi).build(), 21 | "ridged_multi_worley.png", 22 | ); 23 | 24 | let ridged_multi = RidgedMulti::>::default(); 25 | 26 | utils::write_example_to_file( 27 | &PlaneMapBuilder::new(ridged_multi).build(), 28 | "ridged_multi_ridged_multi_perlin.png", 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /examples/rotate_point.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Cylinders, RotatePoint}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let cylinders = Cylinders::new(); 9 | let rotate_point = RotatePoint::new(cylinders).set_x_angle(60.0); 10 | 11 | utils::write_example_to_file( 12 | &PlaneMapBuilder::new(rotate_point).build(), 13 | "rotate_point.png", 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /examples/scale_bias.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Perlin, ScaleBias}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let perlin = Perlin::default(); 9 | let scale_bias = ScaleBias::new(perlin).set_scale(0.0625).set_bias(0.0); 10 | 11 | utils::write_example_to_file(&PlaneMapBuilder::new(scale_bias).build(), "scale_bias.png"); 12 | } 13 | -------------------------------------------------------------------------------- /examples/scale_point.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Checkerboard, ScalePoint}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let cboard = Checkerboard::default(); 9 | let scale_point = ScalePoint::new(cboard).set_all_scales(1.0, 2.0, 3.0, 1.0); 10 | 11 | utils::write_example_to_file( 12 | &PlaneMapBuilder::new(scale_point) 13 | .set_size(500, 500) 14 | .set_x_bounds(-5.0, 5.0) 15 | .set_y_bounds(-5.0, 5.0) 16 | .build(), 17 | "scale_point.png", 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /examples/select.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Checkerboard, Constant, Cylinders, Perlin, Select}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let checkerboard = Checkerboard::default(); 9 | let cylinders = Cylinders::new(); 10 | let perlin = Perlin::default(); 11 | let constant = Constant::new(0.5); 12 | let select1 = Select::new(perlin, cylinders, checkerboard) 13 | .set_bounds(0.0, 1.0) 14 | .set_falloff(0.5); 15 | let select2 = Select::new(perlin, constant, checkerboard) 16 | .set_bounds(0.0, 1.0) 17 | .set_falloff(0.0); 18 | 19 | utils::write_example_to_file( 20 | &PlaneMapBuilder::new(select1) 21 | .set_x_bounds(-1.0, 1.0) 22 | .set_y_bounds(-1.0, 1.0) 23 | .build(), 24 | "select1.png", 25 | ); 26 | utils::write_example_to_file(&PlaneMapBuilder::new(select2).build(), "select2.png"); 27 | } 28 | -------------------------------------------------------------------------------- /examples/simplex.rs: -------------------------------------------------------------------------------- 1 | //! An example of using simplex noise 2 | 3 | extern crate noise; 4 | 5 | use noise::{ 6 | core::simplex::{simplex_2d, simplex_3d, simplex_4d}, 7 | permutationtable::PermutationTable, 8 | utils::*, 9 | }; 10 | 11 | mod utils; 12 | 13 | fn main() { 14 | let hasher = PermutationTable::new(0); 15 | 16 | utils::write_example_to_file( 17 | &PlaneMapBuilder::new_fn(|point| simplex_2d(point.into(), &hasher).0) 18 | .set_size(1024, 1024) 19 | .set_x_bounds(-5.0, 5.0) 20 | .set_y_bounds(-5.0, 5.0) 21 | .build(), 22 | "simplex 2d.png", 23 | ); 24 | 25 | utils::write_example_to_file( 26 | &PlaneMapBuilder::new_fn(|point| simplex_3d(point.into(), &hasher).0) 27 | .set_size(1024, 1024) 28 | .set_x_bounds(-5.0, 5.0) 29 | .set_y_bounds(-5.0, 5.0) 30 | .build(), 31 | "simplex 3d.png", 32 | ); 33 | 34 | utils::write_example_to_file( 35 | &PlaneMapBuilder::new_fn(|point| simplex_4d(point.into(), &hasher).0) 36 | .set_size(1024, 1024) 37 | .set_x_bounds(-5.0, 5.0) 38 | .set_y_bounds(-5.0, 5.0) 39 | .build(), 40 | "simplex 4d.png", 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /examples/spheres.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{core::spheres::*, utils::*}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | utils::write_example_to_file( 9 | &PlaneMapBuilder::new_fn(|point| spheres_2d(point.into(), 1.0)) 10 | .set_size(1024, 1024) 11 | .set_x_bounds(-5.0, 5.0) 12 | .set_y_bounds(-5.0, 5.0) 13 | .build(), 14 | "spheres 2d.png", 15 | ); 16 | 17 | utils::write_example_to_file( 18 | &PlaneMapBuilder::new_fn(|point| spheres_3d(point.into(), 2.0)) 19 | .set_size(1024, 1024) 20 | .set_x_bounds(-5.0, 5.0) 21 | .set_y_bounds(-5.0, 5.0) 22 | .build(), 23 | "spheres 3d.png", 24 | ); 25 | 26 | utils::write_example_to_file( 27 | &PlaneMapBuilder::new_fn(|point| spheres_4d(point.into(), 3.0)) 28 | .set_size(1024, 1024) 29 | .set_x_bounds(-5.0, 5.0) 30 | .set_y_bounds(-5.0, 5.0) 31 | .build(), 32 | "spheres 4d.png", 33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /examples/super_simplex.rs: -------------------------------------------------------------------------------- 1 | //! An example of using Super Simplex noise 2 | 3 | extern crate noise; 4 | 5 | use noise::{ 6 | core::super_simplex::{super_simplex_2d, super_simplex_3d}, 7 | permutationtable::PermutationTable, 8 | utils::*, 9 | }; 10 | 11 | mod utils; 12 | 13 | fn main() { 14 | let hasher = PermutationTable::new(0); 15 | 16 | utils::write_example_to_file( 17 | &PlaneMapBuilder::new_fn(|point| super_simplex_2d(point.into(), &hasher)) 18 | .set_size(1024, 1024) 19 | .set_x_bounds(-5.0, 5.0) 20 | .set_y_bounds(-5.0, 5.0) 21 | .build(), 22 | "super_simplex 2d.png", 23 | ); 24 | 25 | utils::write_example_to_file( 26 | &PlaneMapBuilder::new_fn(|point| super_simplex_3d(point.into(), &hasher)) 27 | .set_size(1024, 1024) 28 | .set_x_bounds(-5.0, 5.0) 29 | .set_y_bounds(-5.0, 5.0) 30 | .build(), 31 | "super_simplex 3d.png", 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /examples/terrace.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Perlin, Terrace}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let perlin = Perlin::default(); 9 | let terrace = Terrace::new(perlin) 10 | .add_control_point(-1.0) 11 | .add_control_point(-0.5) 12 | .add_control_point(0.1) 13 | .add_control_point(1.0); 14 | 15 | let terrace_inverted = Terrace::new(perlin) 16 | .add_control_point(-1.0) 17 | .add_control_point(-0.5) 18 | .add_control_point(0.1) 19 | .add_control_point(1.0) 20 | .invert_terraces(true); 21 | 22 | utils::write_example_to_file(&PlaneMapBuilder::new(terrace).build(), "terrace.png"); 23 | 24 | utils::write_example_to_file( 25 | &PlaneMapBuilder::new(terrace_inverted).build(), 26 | "terrace_inverted.png", 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /examples/texturegranite.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{core::worley::ReturnType, utils::*, *}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | // Primary granite texture. This generates the "roughness" of the texture 9 | // when lit by a light source. 10 | let primary_granite = Billow::::new(0) 11 | .set_frequency(8.0) 12 | .set_persistence(0.625) 13 | .set_lacunarity(2.18359375) 14 | .set_octaves(6); 15 | 16 | // Use Worley polygons to produce the small grains for the granite texture. 17 | let base_grains = Worley::new(1) 18 | .set_frequency(16.0) 19 | .set_return_type(ReturnType::Distance); 20 | 21 | // Scale the small grain values so that they can be added to the base 22 | // granite texture. Worley polygons normally generate pits, so apply a 23 | // negative scaling factor to produce bumps instead. 24 | let scaled_grains = ScaleBias::new(base_grains).set_scale(-0.5).set_bias(0.0); 25 | 26 | // Combine the primary granite texture with the small grain texture. 27 | let combined_granite = Add::new(primary_granite, scaled_grains); 28 | 29 | // Finally, perturb the granite texture to add realism. 30 | let final_granite = Turbulence::<_, Perlin>::new(combined_granite) 31 | .set_seed(2) 32 | .set_frequency(4.0) 33 | .set_power(1.0 / 8.0) 34 | .set_roughness(6); 35 | 36 | let planar_texture = PlaneMapBuilder::new(&final_granite) 37 | .set_size(1024, 1024) 38 | .build(); 39 | 40 | let seamless_texture = PlaneMapBuilder::new(&final_granite) 41 | .set_size(1024, 1024) 42 | .set_is_seamless(true) 43 | .build(); 44 | 45 | let sphere_texture = SphereMapBuilder::new(final_granite) 46 | .set_size(1024, 512) 47 | .set_bounds(-90.0, 90.0, -180.0, 180.0) 48 | .build(); 49 | 50 | // Create a gray granite palette. Black and pink appear at either ends of the palette; these 51 | // colors provide the characteristic flecks in granite. 52 | let granite_gradient = ColorGradient::new() 53 | .clear_gradient() 54 | .add_gradient_point(-1.0000, [0, 0, 0, 255]) 55 | .add_gradient_point(-0.9375, [0, 0, 0, 255]) 56 | .add_gradient_point(-0.8750, [216, 216, 242, 255]) 57 | .add_gradient_point(0.0000, [191, 191, 191, 255]) 58 | .add_gradient_point(0.5000, [210, 116, 125, 255]) 59 | .add_gradient_point(0.7500, [210, 113, 98, 255]) 60 | .add_gradient_point(1.0000, [255, 176, 192, 255]); 61 | 62 | let mut renderer = ImageRenderer::new().set_gradient(granite_gradient); 63 | 64 | utils::write_image_to_file( 65 | &renderer.render(&planar_texture), 66 | "texture_granite_planar.png", 67 | ); 68 | 69 | utils::write_image_to_file( 70 | &renderer.render(&seamless_texture), 71 | "texture_granite_seamless.png", 72 | ); 73 | 74 | utils::write_image_to_file( 75 | &renderer.render(&sphere_texture), 76 | "texture_granite_sphere.png", 77 | ); 78 | } 79 | -------------------------------------------------------------------------------- /examples/texturejade.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, *}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | // Primary jade texture. The ridges from the ridged-multifractal function 9 | // produces the veins. 10 | let primary_jade = RidgedMulti::::new(0) 11 | .set_frequency(2.0) 12 | .set_lacunarity(2.20703125) 13 | .set_octaves(6); 14 | 15 | // Base of the secondary jade texture. The base texture uses concentric 16 | // cylinders aligned on the z axis, which will eventually be perturbed. 17 | let base_secondary_jade = Cylinders::new().set_frequency(2.0); 18 | 19 | // Rotate the base secondary jade texture so that the cylinders are not 20 | // aligned with any axis. This produces more variation in the secondary 21 | // jade texture since the texture is parallel to the y-axis. 22 | let rotated_base_secondary_jade = 23 | RotatePoint::new(base_secondary_jade).set_angles(90.0, 25.0, 5.0, 0.0); 24 | 25 | // Slightly perturb the secondary jade texture for more realism. 26 | let perturbed_base_secondary_jade = Turbulence::<_, Perlin>::new(rotated_base_secondary_jade) 27 | .set_seed(1) 28 | .set_frequency(4.0) 29 | .set_power(1.0 / 4.0) 30 | .set_roughness(4); 31 | 32 | // Scale the secondary jade texture so it makes a small contribution to the 33 | // final jade texture. 34 | let secondary_jade = ScaleBias::new(perturbed_base_secondary_jade) 35 | .set_scale(0.25) 36 | .set_bias(0.0); 37 | 38 | // Add the two jade textures together. These two textures were produced 39 | // using different combinations of coherent noise, so the final texture 40 | // will have a lot of variation. 41 | let combined_jade = Add::new(primary_jade, secondary_jade); 42 | 43 | // Finally, perturb the combined jade texture to produce the final jade 44 | // texture. A low roughness produces nice veins. 45 | let final_jade = Turbulence::<_, Perlin>::new(combined_jade) 46 | .set_seed(2) 47 | .set_frequency(4.0) 48 | .set_power(1.0 / 16.0) 49 | .set_roughness(2); 50 | 51 | let planar_texture = PlaneMapBuilder::new(&final_jade) 52 | .set_size(1024, 1024) 53 | .build(); 54 | 55 | let seamless_texture = PlaneMapBuilder::new(final_jade) 56 | .set_size(1024, 1024) 57 | .set_is_seamless(true) 58 | .build(); 59 | 60 | // Create a jade palette. 61 | let jade_gradient = ColorGradient::new() 62 | .clear_gradient() 63 | .add_gradient_point(-1.000, [24, 146, 102, 255]) 64 | .add_gradient_point(0.000, [78, 154, 115, 255]) 65 | .add_gradient_point(0.250, [128, 204, 165, 255]) 66 | .add_gradient_point(0.375, [78, 154, 115, 255]) 67 | .add_gradient_point(1.000, [29, 135, 102, 255]); 68 | 69 | let mut renderer = ImageRenderer::new().set_gradient(jade_gradient); 70 | 71 | utils::write_image_to_file(&renderer.render(&planar_texture), "texture_jade_planar.png"); 72 | 73 | utils::write_image_to_file( 74 | &renderer.render(&seamless_texture), 75 | "texture_jade_seamless.png", 76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /examples/textureslime.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, *}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | // Large slime bubble texture. 9 | let large_slime = Billow::::new(0) 10 | .set_frequency(4.0) 11 | .set_lacunarity(2.12109375) 12 | .set_octaves(1); 13 | 14 | // Base of the small slime bubble texture. This texture will eventually 15 | // appear inside cracks in the large slime bubble texture. 16 | let small_slime_base = Billow::::new(1) 17 | .set_frequency(24.0) 18 | .set_lacunarity(2.14453125) 19 | .set_octaves(1); 20 | 21 | // Scale and lower the small slime bubble values. 22 | let small_slime = ScaleBias::new(small_slime_base) 23 | .set_scale(0.5) 24 | .set_bias(-0.5); 25 | 26 | // Create a map that specifies where the large and small slime bubble 27 | // textures will appear in the final texture map. 28 | let slime_map = RidgedMulti::::new(2) 29 | .set_frequency(2.0) 30 | .set_lacunarity(2.20703125) 31 | .set_octaves(3); 32 | 33 | // Choose between the large or small slime bubble textures depending on 34 | // the corresponding value from the slime map. Choose the small slime 35 | // bubble texture if the slime map value is within a narrow range of 36 | // values, otherwise choose the large slime bubble texture. The edge 37 | // falloff is non-zero so that there is a smooth transition between the 38 | // two textures. 39 | let slime_chooser = Select::new(large_slime, small_slime, slime_map) 40 | .set_bounds(-0.375, 0.375) 41 | .set_falloff(0.5); 42 | 43 | // Finally, perturb the slime texture to add realism. 44 | let final_slime = Turbulence::<_, Perlin>::new(slime_chooser) 45 | .set_seed(3) 46 | .set_frequency(8.0) 47 | .set_power(1.0 / 32.0) 48 | .set_roughness(2); 49 | 50 | let planar_texture = PlaneMapBuilder::new(&final_slime) 51 | .set_size(1024, 1024) 52 | .build(); 53 | 54 | let seamless_texture = PlaneMapBuilder::new(final_slime) 55 | .set_size(1024, 1024) 56 | .set_is_seamless(true) 57 | .build(); 58 | 59 | // Create a slime palette. 60 | let slime_gradient = ColorGradient::new() 61 | .clear_gradient() 62 | .add_gradient_point(-1.0, [160, 64, 42, 255]) 63 | .add_gradient_point(0.0, [64, 192, 64, 255]) 64 | .add_gradient_point(1.0, [128, 255, 128, 255]); 65 | 66 | let mut renderer = ImageRenderer::new().set_gradient(slime_gradient); 67 | 68 | utils::write_image_to_file( 69 | &renderer.render(&planar_texture), 70 | "texture_slime_planar.png", 71 | ); 72 | 73 | utils::write_image_to_file( 74 | &renderer.render(&seamless_texture), 75 | "texture_slime_seamless.png", 76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /examples/texturewood.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, *}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | // Base wood texture. Uses concentric cylinders aligned on the z-axis, like a log. 9 | let base_wood = Cylinders::new().set_frequency(16.0); 10 | 11 | // Basic Multifractal noise to use for the wood grain. 12 | let wood_grain_noise = BasicMulti::::new(0) 13 | .set_frequency(48.0) 14 | .set_persistence(0.5) 15 | .set_lacunarity(2.20703125) 16 | .set_octaves(3); 17 | 18 | // Stretch the perlin noise in the same direction as the center of the log. Should 19 | // produce a nice wood-grain texture. 20 | let scaled_base_wood_grain = ScalePoint::new(wood_grain_noise).set_z_scale(0.25); 21 | 22 | // Scale the wood-grain values so that they can be added to the base wood texture. 23 | let wood_grain = ScaleBias::new(scaled_base_wood_grain) 24 | .set_scale(0.25) 25 | .set_bias(0.125); 26 | 27 | // Add the wood grain texture to the base wood texture. 28 | let combined_wood = Add::new(base_wood, wood_grain); 29 | 30 | // Slightly perturb the wood to create a more realistic texture. 31 | let perturbed_wood = Turbulence::<_, Perlin>::new(combined_wood) 32 | .set_seed(1) 33 | .set_frequency(4.0) 34 | .set_power(1.0 / 256.0) 35 | .set_roughness(4); 36 | 37 | // Cut the wood texture a small distance from the center of the log. 38 | let translated_wood = TranslatePoint::new(perturbed_wood).set_y_translation(1.48); 39 | 40 | // Set the cut on a angle to produce a more interesting texture. 41 | let rotated_wood = RotatePoint::new(translated_wood).set_angles(84.0, 0.0, 0.0, 0.0); 42 | 43 | // Finally, perturb the wood texture again to produce the final texture. 44 | let final_wood = Turbulence::<_, Perlin>::new(rotated_wood) 45 | .set_seed(2) 46 | .set_frequency(2.0) 47 | .set_power(1.0 / 64.0) 48 | .set_roughness(4); 49 | 50 | let planar_texture = PlaneMapBuilder::new(final_wood) 51 | .set_size(1024, 1024) 52 | .build(); 53 | 54 | // Create a wood palette. 55 | let wood_gradient = ColorGradient::new() 56 | .clear_gradient() 57 | .add_gradient_point(-1.000, [189, 94, 4, 255]) 58 | .add_gradient_point(0.500, [144, 48, 6, 255]) 59 | .add_gradient_point(1.0, [60, 10, 8, 255]); 60 | 61 | let mut renderer = ImageRenderer::new().set_gradient(wood_gradient); 62 | 63 | utils::write_image_to_file(&renderer.render(&planar_texture), "texture_wood_planar.png"); 64 | } 65 | -------------------------------------------------------------------------------- /examples/translate_point.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Checkerboard, TranslatePoint}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let cboard = Checkerboard::default(); 9 | let translate_point = TranslatePoint::new(cboard).set_all_translations(0.5, 0.5, 0.0, 0.0); 10 | 11 | utils::write_example_to_file( 12 | &PlaneMapBuilder::new(translate_point).build(), 13 | "translate_point.png", 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /examples/turbulence.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{utils::*, Perlin, Turbulence}; 4 | 5 | mod utils; 6 | 7 | fn main() { 8 | let perlin = Perlin::default(); 9 | let turbulence = Turbulence::<_, Perlin>::new(perlin); 10 | 11 | utils::write_example_to_file(&PlaneMapBuilder::new(turbulence).build(), "turbulence.png"); 12 | } 13 | -------------------------------------------------------------------------------- /examples/utils.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "images")] 2 | use noise::utils::{NoiseImage, NoiseMap}; 3 | 4 | #[allow(dead_code)] 5 | #[cfg(feature = "images")] 6 | pub fn write_example_to_file(map: &NoiseMap, filename: &str) { 7 | use std::{fs, path::Path}; 8 | 9 | let target = Path::new("example_images/").join(Path::new(filename)); 10 | 11 | fs::create_dir_all(target.clone().parent().expect("No parent directory found.")) 12 | .expect("Failed to create directories."); 13 | 14 | map.write_to_file(&target) 15 | } 16 | 17 | #[allow(dead_code)] 18 | #[cfg(feature = "images")] 19 | pub fn write_image_to_file(image: &NoiseImage, filename: &str) { 20 | use std::{fs, path::Path}; 21 | 22 | let target = Path::new("example_images/").join(Path::new(filename)); 23 | 24 | fs::create_dir_all(target.clone().parent().expect("No parent directory found.")) 25 | .expect("Failed to create directories."); 26 | 27 | image.write_to_file(&target) 28 | } 29 | 30 | #[allow(dead_code)] 31 | fn main() { 32 | println!("This is not an example") 33 | } 34 | -------------------------------------------------------------------------------- /examples/value.rs: -------------------------------------------------------------------------------- 1 | //! An example of using value noise 2 | 3 | extern crate noise; 4 | 5 | use noise::{ 6 | core::value::{value_2d, value_3d, value_4d}, 7 | permutationtable::PermutationTable, 8 | utils::*, 9 | }; 10 | 11 | mod utils; 12 | 13 | fn main() { 14 | let hasher = PermutationTable::new(0); 15 | utils::write_example_to_file( 16 | &PlaneMapBuilder::new_fn(|point| value_2d(point.into(), &hasher)) 17 | .set_size(1024, 1024) 18 | .set_x_bounds(-5.0, 5.0) 19 | .set_y_bounds(-5.0, 5.0) 20 | .build(), 21 | "value 2d.png", 22 | ); 23 | 24 | utils::write_example_to_file( 25 | &PlaneMapBuilder::new_fn(|point| value_3d(point.into(), &hasher)) 26 | .set_size(1024, 1024) 27 | .set_x_bounds(-5.0, 5.0) 28 | .set_y_bounds(-5.0, 5.0) 29 | .build(), 30 | "value 3d.png", 31 | ); 32 | 33 | utils::write_example_to_file( 34 | &PlaneMapBuilder::new_fn(|point| value_4d(point.into(), &hasher)) 35 | .set_size(1024, 1024) 36 | .set_x_bounds(-5.0, 5.0) 37 | .set_y_bounds(-5.0, 5.0) 38 | .build(), 39 | "value 4d.png", 40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /examples/worley.rs: -------------------------------------------------------------------------------- 1 | extern crate noise; 2 | 3 | use noise::{ 4 | core::worley::{distance_functions::*, worley_2d, worley_3d, worley_4d, ReturnType}, 5 | permutationtable::PermutationTable, 6 | utils::*, 7 | Vector2, Vector3, Vector4, 8 | }; 9 | 10 | mod utils; 11 | 12 | fn output_2d(distance_function: &F, return_type: ReturnType, name: &str) 13 | where 14 | F: Fn(&[f64], &[f64]) -> f64, 15 | { 16 | let hasher = PermutationTable::new(0); 17 | let closure = |point: Vector2, hasher: &PermutationTable| { 18 | worley_2d(hasher, distance_function, return_type, point) 19 | }; 20 | utils::write_example_to_file( 21 | &PlaneMapBuilder::new_fn(|point| closure(point.into(), &hasher)) 22 | .set_size(256, 256) 23 | .build(), 24 | name, 25 | ); 26 | } 27 | 28 | fn output_3d(distance_function: &F, return_type: ReturnType, name: &str) 29 | where 30 | F: Fn(&[f64], &[f64]) -> f64, 31 | { 32 | let hasher = PermutationTable::new(0); 33 | let closure = |point: Vector3, hasher: &PermutationTable| { 34 | worley_3d(hasher, distance_function, return_type, point) 35 | }; 36 | utils::write_example_to_file( 37 | &PlaneMapBuilder::new_fn(|point| closure(point.into(), &hasher)) 38 | .set_size(256, 256) 39 | .build(), 40 | name, 41 | ); 42 | } 43 | 44 | fn output_4d(distance_function: &F, return_type: ReturnType, name: &str) 45 | where 46 | F: Fn(&[f64], &[f64]) -> f64, 47 | { 48 | let hasher = PermutationTable::new(0); 49 | let closure = |point: Vector4, hasher: &PermutationTable| { 50 | worley_4d(hasher, distance_function, return_type, point) 51 | }; 52 | utils::write_example_to_file( 53 | &PlaneMapBuilder::new_fn(|point| closure(point.into(), &hasher)) 54 | .set_size(256, 256) 55 | .build(), 56 | name, 57 | ); 58 | } 59 | 60 | fn main() { 61 | output_2d( 62 | &euclidean, 63 | ReturnType::Value, 64 | "worley/2d_euclidean_value.png", 65 | ); 66 | output_3d( 67 | &euclidean, 68 | ReturnType::Value, 69 | "worley/3d_euclidean_value.png", 70 | ); 71 | output_4d( 72 | &euclidean, 73 | ReturnType::Value, 74 | "worley/4d_euclidean_value.png", 75 | ); 76 | output_2d( 77 | &euclidean, 78 | ReturnType::Distance, 79 | "worley/2d_euclidean_distance.png", 80 | ); 81 | output_3d( 82 | &euclidean, 83 | ReturnType::Distance, 84 | "worley/3d_euclidean_distance.png", 85 | ); 86 | output_4d( 87 | &euclidean, 88 | ReturnType::Distance, 89 | "worley/4d_euclidean_distance.png", 90 | ); 91 | output_2d( 92 | &euclidean_squared, 93 | ReturnType::Value, 94 | "worley/2d_euclidean_squared_value.png", 95 | ); 96 | output_3d( 97 | &euclidean_squared, 98 | ReturnType::Value, 99 | "worley/3d_euclidean_squared_value.png", 100 | ); 101 | output_4d( 102 | &euclidean_squared, 103 | ReturnType::Value, 104 | "worley/4d_euclidean_squared_value.png", 105 | ); 106 | output_2d( 107 | &euclidean_squared, 108 | ReturnType::Distance, 109 | "worley/2d_euclidean_squared_distance.png", 110 | ); 111 | output_3d( 112 | &euclidean_squared, 113 | ReturnType::Distance, 114 | "worley/3d_euclidean_squared_distance.png", 115 | ); 116 | output_4d( 117 | &euclidean_squared, 118 | ReturnType::Distance, 119 | "worley/4d_euclidean_squared_distance.png", 120 | ); 121 | output_2d( 122 | &manhattan, 123 | ReturnType::Value, 124 | "worley/2d_manhattan_value.png", 125 | ); 126 | output_3d( 127 | &manhattan, 128 | ReturnType::Value, 129 | "worley/3d_manhattan_value.png", 130 | ); 131 | output_4d( 132 | &manhattan, 133 | ReturnType::Value, 134 | "worley/4d_manhattan_value.png", 135 | ); 136 | output_2d( 137 | &manhattan, 138 | ReturnType::Distance, 139 | "worley/2d_manhattan_distance.png", 140 | ); 141 | output_3d( 142 | &manhattan, 143 | ReturnType::Distance, 144 | "worley/3d_manhattan_distance.png", 145 | ); 146 | output_4d( 147 | &manhattan, 148 | ReturnType::Distance, 149 | "worley/4d_manhattan_distance.png", 150 | ); 151 | output_2d( 152 | &chebyshev, 153 | ReturnType::Value, 154 | "worley/2d_chebyshev_value.png", 155 | ); 156 | output_3d( 157 | &chebyshev, 158 | ReturnType::Value, 159 | "worley/3d_chebyshev_value.png", 160 | ); 161 | output_4d( 162 | &chebyshev, 163 | ReturnType::Value, 164 | "worley/4d_chebyshev_value.png", 165 | ); 166 | output_2d( 167 | &chebyshev, 168 | ReturnType::Distance, 169 | "worley/2d_chebyshev_distance.png", 170 | ); 171 | output_3d( 172 | &chebyshev, 173 | ReturnType::Distance, 174 | "worley/3d_chebyshev_distance.png", 175 | ); 176 | output_4d( 177 | &chebyshev, 178 | ReturnType::Distance, 179 | "worley/4d_chebyshev_distance.png", 180 | ); 181 | } 182 | -------------------------------------------------------------------------------- /images/examples/abs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/abs.png -------------------------------------------------------------------------------- /images/examples/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/add.png -------------------------------------------------------------------------------- /images/examples/basicmulti_basicmulti_perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/basicmulti_basicmulti_perlin.png -------------------------------------------------------------------------------- /images/examples/basicmulti_perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/basicmulti_perlin.png -------------------------------------------------------------------------------- /images/examples/basicmulti_worley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/basicmulti_worley.png -------------------------------------------------------------------------------- /images/examples/billow_billow_perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/billow_billow_perlin.png -------------------------------------------------------------------------------- /images/examples/billow_perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/billow_perlin.png -------------------------------------------------------------------------------- /images/examples/billow_worley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/billow_worley.png -------------------------------------------------------------------------------- /images/examples/blend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/blend.png -------------------------------------------------------------------------------- /images/examples/cache.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/cache.png -------------------------------------------------------------------------------- /images/examples/checkerboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/checkerboard.png -------------------------------------------------------------------------------- /images/examples/clamp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/clamp.png -------------------------------------------------------------------------------- /images/examples/constant_-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/constant_-1.png -------------------------------------------------------------------------------- /images/examples/constant_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/constant_0.png -------------------------------------------------------------------------------- /images/examples/constant_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/constant_1.png -------------------------------------------------------------------------------- /images/examples/curve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/curve.png -------------------------------------------------------------------------------- /images/examples/cylinders-f5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/cylinders-f5.png -------------------------------------------------------------------------------- /images/examples/cylinders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/cylinders.png -------------------------------------------------------------------------------- /images/examples/displace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/displace.png -------------------------------------------------------------------------------- /images/examples/exponent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/exponent.png -------------------------------------------------------------------------------- /images/examples/fbm_fbm_perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/fbm_fbm_perlin.png -------------------------------------------------------------------------------- /images/examples/fbm_perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/fbm_perlin.png -------------------------------------------------------------------------------- /images/examples/fbm_worley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/fbm_worley.png -------------------------------------------------------------------------------- /images/examples/hybrid_multi_hybrid_multi_perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/hybrid_multi_hybrid_multi_perlin.png -------------------------------------------------------------------------------- /images/examples/hybrid_multi_perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/hybrid_multi_perlin.png -------------------------------------------------------------------------------- /images/examples/hybrid_multi_worley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/hybrid_multi_worley.png -------------------------------------------------------------------------------- /images/examples/max.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/max.png -------------------------------------------------------------------------------- /images/examples/min.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/min.png -------------------------------------------------------------------------------- /images/examples/multiply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/multiply.png -------------------------------------------------------------------------------- /images/examples/negate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/negate.png -------------------------------------------------------------------------------- /images/examples/open_simplex 2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/open_simplex 2d.png -------------------------------------------------------------------------------- /images/examples/open_simplex 3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/open_simplex 3d.png -------------------------------------------------------------------------------- /images/examples/open_simplex 4d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/open_simplex 4d.png -------------------------------------------------------------------------------- /images/examples/perlin surflet 2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/perlin surflet 2d.png -------------------------------------------------------------------------------- /images/examples/perlin surflet 3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/perlin surflet 3d.png -------------------------------------------------------------------------------- /images/examples/perlin surflet 4d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/perlin surflet 4d.png -------------------------------------------------------------------------------- /images/examples/perlin_2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/perlin_2d.png -------------------------------------------------------------------------------- /images/examples/perlin_3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/perlin_3d.png -------------------------------------------------------------------------------- /images/examples/perlin_4d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/perlin_4d.png -------------------------------------------------------------------------------- /images/examples/power.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/power.png -------------------------------------------------------------------------------- /images/examples/ridged_multi_perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/ridged_multi_perlin.png -------------------------------------------------------------------------------- /images/examples/ridged_multi_ridged_multi_perlin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/ridged_multi_ridged_multi_perlin.png -------------------------------------------------------------------------------- /images/examples/ridged_multi_worley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/ridged_multi_worley.png -------------------------------------------------------------------------------- /images/examples/rotate_point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/rotate_point.png -------------------------------------------------------------------------------- /images/examples/scale_bias.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/scale_bias.png -------------------------------------------------------------------------------- /images/examples/scale_point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/scale_point.png -------------------------------------------------------------------------------- /images/examples/select1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/select1.png -------------------------------------------------------------------------------- /images/examples/select2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/select2.png -------------------------------------------------------------------------------- /images/examples/simplex 2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/simplex 2d.png -------------------------------------------------------------------------------- /images/examples/simplex 3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/simplex 3d.png -------------------------------------------------------------------------------- /images/examples/simplex 4d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/simplex 4d.png -------------------------------------------------------------------------------- /images/examples/spheres 2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/spheres 2d.png -------------------------------------------------------------------------------- /images/examples/spheres 3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/spheres 3d.png -------------------------------------------------------------------------------- /images/examples/spheres 4d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/spheres 4d.png -------------------------------------------------------------------------------- /images/examples/super_simplex 2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/super_simplex 2d.png -------------------------------------------------------------------------------- /images/examples/super_simplex 3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/super_simplex 3d.png -------------------------------------------------------------------------------- /images/examples/terrace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/terrace.png -------------------------------------------------------------------------------- /images/examples/terrace_inverted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/terrace_inverted.png -------------------------------------------------------------------------------- /images/examples/texture_granite_planar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/texture_granite_planar.png -------------------------------------------------------------------------------- /images/examples/texture_granite_seamless.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/texture_granite_seamless.png -------------------------------------------------------------------------------- /images/examples/texture_granite_sphere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/texture_granite_sphere.png -------------------------------------------------------------------------------- /images/examples/texture_jade_planar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/texture_jade_planar.png -------------------------------------------------------------------------------- /images/examples/texture_jade_seamless.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/texture_jade_seamless.png -------------------------------------------------------------------------------- /images/examples/texture_slime_planar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/texture_slime_planar.png -------------------------------------------------------------------------------- /images/examples/texture_slime_seamless.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/texture_slime_seamless.png -------------------------------------------------------------------------------- /images/examples/texture_wood_planar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/texture_wood_planar.png -------------------------------------------------------------------------------- /images/examples/translate_point.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/translate_point.png -------------------------------------------------------------------------------- /images/examples/turbulence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/turbulence.png -------------------------------------------------------------------------------- /images/examples/unscaledFinalPlanet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/unscaledFinalPlanet.png -------------------------------------------------------------------------------- /images/examples/unscaledFinalPlanet_16x_zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/unscaledFinalPlanet_16x_zoom.png -------------------------------------------------------------------------------- /images/examples/unscaledFinalPlanet_4x_zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/unscaledFinalPlanet_4x_zoom.png -------------------------------------------------------------------------------- /images/examples/unscaledFinalPlanet_sphere.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/unscaledFinalPlanet_sphere.png -------------------------------------------------------------------------------- /images/examples/value 2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/value 2d.png -------------------------------------------------------------------------------- /images/examples/value 3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/value 3d.png -------------------------------------------------------------------------------- /images/examples/value 4d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/value 4d.png -------------------------------------------------------------------------------- /images/examples/worley/2d_chebyshev_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/2d_chebyshev_distance.png -------------------------------------------------------------------------------- /images/examples/worley/2d_chebyshev_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/2d_chebyshev_value.png -------------------------------------------------------------------------------- /images/examples/worley/2d_euclidean_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/2d_euclidean_distance.png -------------------------------------------------------------------------------- /images/examples/worley/2d_euclidean_squared_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/2d_euclidean_squared_distance.png -------------------------------------------------------------------------------- /images/examples/worley/2d_euclidean_squared_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/2d_euclidean_squared_value.png -------------------------------------------------------------------------------- /images/examples/worley/2d_euclidean_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/2d_euclidean_value.png -------------------------------------------------------------------------------- /images/examples/worley/2d_manhattan_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/2d_manhattan_distance.png -------------------------------------------------------------------------------- /images/examples/worley/2d_manhattan_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/2d_manhattan_value.png -------------------------------------------------------------------------------- /images/examples/worley/3d_chebyshev_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/3d_chebyshev_distance.png -------------------------------------------------------------------------------- /images/examples/worley/3d_chebyshev_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/3d_chebyshev_value.png -------------------------------------------------------------------------------- /images/examples/worley/3d_euclidean_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/3d_euclidean_distance.png -------------------------------------------------------------------------------- /images/examples/worley/3d_euclidean_squared_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/3d_euclidean_squared_distance.png -------------------------------------------------------------------------------- /images/examples/worley/3d_euclidean_squared_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/3d_euclidean_squared_value.png -------------------------------------------------------------------------------- /images/examples/worley/3d_euclidean_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/3d_euclidean_value.png -------------------------------------------------------------------------------- /images/examples/worley/3d_manhattan_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/3d_manhattan_distance.png -------------------------------------------------------------------------------- /images/examples/worley/3d_manhattan_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/3d_manhattan_value.png -------------------------------------------------------------------------------- /images/examples/worley/4d_chebyshev_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/4d_chebyshev_distance.png -------------------------------------------------------------------------------- /images/examples/worley/4d_chebyshev_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/4d_chebyshev_value.png -------------------------------------------------------------------------------- /images/examples/worley/4d_euclidean_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/4d_euclidean_distance.png -------------------------------------------------------------------------------- /images/examples/worley/4d_euclidean_squared_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/4d_euclidean_squared_distance.png -------------------------------------------------------------------------------- /images/examples/worley/4d_euclidean_squared_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/4d_euclidean_squared_value.png -------------------------------------------------------------------------------- /images/examples/worley/4d_euclidean_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/4d_euclidean_value.png -------------------------------------------------------------------------------- /images/examples/worley/4d_manhattan_distance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/4d_manhattan_distance.png -------------------------------------------------------------------------------- /images/examples/worley/4d_manhattan_value.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/examples/worley/4d_manhattan_value.png -------------------------------------------------------------------------------- /images/fbm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/fbm.png -------------------------------------------------------------------------------- /images/unscaledFinalPlanet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/unscaledFinalPlanet.png -------------------------------------------------------------------------------- /images/unscaledFinalPlanet_16x_zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/unscaledFinalPlanet_16x_zoom.png -------------------------------------------------------------------------------- /images/unscaledFinalPlanet_4x_zoom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Razaekel/noise-rs/77de33887620c2a7e7263b1d30ef46afbfe705b6/images/unscaledFinalPlanet_4x_zoom.png -------------------------------------------------------------------------------- /src/core.rs: -------------------------------------------------------------------------------- 1 | pub mod checkerboard; 2 | pub mod open_simplex; 3 | pub mod perlin; 4 | pub mod perlin_surflet; 5 | pub mod simplex; 6 | pub mod spheres; 7 | pub mod super_simplex; 8 | pub mod value; 9 | pub mod worley; 10 | -------------------------------------------------------------------------------- /src/core/checkerboard.rs: -------------------------------------------------------------------------------- 1 | use crate::math::vectors::{Vector2, Vector3, Vector4}; 2 | 3 | #[inline(always)] 4 | pub fn checkerboard_2d(point: Vector2, grid_size: f64) -> f64 { 5 | let floor = (point / grid_size).floor_to_isize(); 6 | if (floor.x & 1) ^ (floor.y & 1) == 0 { 7 | -1.0 8 | } else { 9 | 1.0 10 | } 11 | } 12 | 13 | #[inline(always)] 14 | pub fn checkerboard_3d(point: Vector3, grid_size: f64) -> f64 { 15 | let floor = (point / grid_size).floor_to_isize(); 16 | if (floor.x & 1) ^ (floor.y & 1) ^ (floor.z & 1) == 0 { 17 | -1.0 18 | } else { 19 | 1.0 20 | } 21 | } 22 | 23 | #[inline(always)] 24 | pub fn checkerboard_4d(point: Vector4, grid_size: f64) -> f64 { 25 | let floor = (point / grid_size).floor_to_isize(); 26 | if (floor.x & 1) ^ (floor.y & 1) ^ (floor.z & 1) ^ (floor.w & 1) == 0 { 27 | -1.0 28 | } else { 29 | 1.0 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/core/perlin_surflet.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | gradient, 3 | math::vectors::{Vector2, Vector3, Vector4}, 4 | permutationtable::NoiseHasher, 5 | }; 6 | 7 | #[inline(always)] 8 | pub fn perlin_surflet_2d(point: Vector2, hasher: &NH) -> f64 9 | where 10 | NH: NoiseHasher + ?Sized, 11 | { 12 | const SCALE_FACTOR: f64 = 3.160_493_827_160_493_7; 13 | 14 | fn surflet(index: usize, distance: Vector2) -> f64 { 15 | let attn: f64 = 1.0 - distance.magnitude_squared(); 16 | 17 | if attn > 0.0 { 18 | let gradient = Vector2::from(gradient::grad2(index)); 19 | attn.powi(4) * distance.dot(gradient) 20 | } else { 21 | 0.0 22 | } 23 | } 24 | 25 | let corner = point.floor_to_isize(); 26 | let floored = corner.numcast().unwrap(); 27 | let distance = point - floored; 28 | 29 | macro_rules! call_surflet( 30 | ($x:expr, $y:expr) => { 31 | { 32 | let offset = Vector2::new($x, $y); 33 | let index = hasher.hash(&(corner + offset).into_array()); 34 | surflet(index, distance - offset.numcast().unwrap()) 35 | } 36 | } 37 | ); 38 | 39 | let f00 = call_surflet!(0, 0); 40 | let f10 = call_surflet!(1, 0); 41 | let f01 = call_surflet!(0, 1); 42 | let f11 = call_surflet!(1, 1); 43 | 44 | // Multiply by arbitrary value to scale to -1..1 45 | ((f00 + f10 + f01 + f11) * SCALE_FACTOR).clamp(-1.0, 1.0) 46 | } 47 | 48 | #[inline(always)] 49 | pub fn perlin_surflet_3d(point: Vector3, hasher: &NH) -> f64 50 | where 51 | NH: NoiseHasher + ?Sized, 52 | { 53 | const SCALE_FACTOR: f64 = 3.889_855_325_553_107_4; 54 | 55 | #[inline(always)] 56 | fn surflet(index: usize, distance: Vector3) -> f64 { 57 | let attn: f64 = 1.0 - distance.magnitude_squared(); 58 | 59 | if attn > 0.0 { 60 | let gradient = Vector3::from(gradient::grad3(index)); 61 | attn.powi(4) * distance.dot(gradient) 62 | } else { 63 | 0.0 64 | } 65 | } 66 | 67 | let corner = point.floor_to_isize(); 68 | let floored = corner.numcast().unwrap(); 69 | let distance = point - floored; 70 | 71 | macro_rules! call_surflet( 72 | ($x:expr, $y:expr, $z:expr) => { 73 | { 74 | let offset = Vector3::new($x, $y, $z); 75 | let index = hasher.hash(&(corner + offset).into_array()); 76 | surflet(index, distance - offset.numcast().unwrap()) 77 | } 78 | } 79 | ); 80 | 81 | let f000 = call_surflet!(0, 0, 0); 82 | let f100 = call_surflet!(1, 0, 0); 83 | let f010 = call_surflet!(0, 1, 0); 84 | let f110 = call_surflet!(1, 1, 0); 85 | let f001 = call_surflet!(0, 0, 1); 86 | let f101 = call_surflet!(1, 0, 1); 87 | let f011 = call_surflet!(0, 1, 1); 88 | let f111 = call_surflet!(1, 1, 1); 89 | 90 | // Multiply by arbitrary value to scale to -1..1 91 | ((f000 + f100 + f010 + f110 + f001 + f101 + f011 + f111) * SCALE_FACTOR).clamp(-1.0, 1.0) 92 | } 93 | 94 | #[inline(always)] 95 | pub fn perlin_surflet_4d(point: Vector4, hasher: &NH) -> f64 96 | where 97 | NH: NoiseHasher + ?Sized, 98 | { 99 | const SCALE_FACTOR: f64 = 4.424_369_240_215_691; 100 | 101 | #[inline(always)] 102 | fn surflet(index: usize, distance: Vector4) -> f64 { 103 | let attn: f64 = 1.0 - distance.magnitude_squared(); 104 | 105 | if attn > 0.0 { 106 | let gradient = Vector4::from(gradient::grad4(index)); 107 | attn.powi(4) * distance.dot(gradient) 108 | } else { 109 | 0.0 110 | } 111 | } 112 | 113 | let corner = point.floor_to_isize(); 114 | let floored = corner.numcast().unwrap(); 115 | let distance = point - floored; 116 | 117 | macro_rules! call_surflet( 118 | ($x:expr, $y:expr, $z:expr, $w:expr) => { 119 | { 120 | let offset = Vector4::new($x, $y, $z, $w); 121 | let index = hasher.hash(&(corner + offset).into_array()); 122 | surflet(index, distance - offset.numcast().unwrap()) 123 | } 124 | } 125 | ); 126 | 127 | let f0000 = call_surflet!(0, 0, 0, 0); 128 | let f1000 = call_surflet!(1, 0, 0, 0); 129 | let f0100 = call_surflet!(0, 1, 0, 0); 130 | let f1100 = call_surflet!(1, 1, 0, 0); 131 | let f0010 = call_surflet!(0, 0, 1, 0); 132 | let f1010 = call_surflet!(1, 0, 1, 0); 133 | let f0110 = call_surflet!(0, 1, 1, 0); 134 | let f1110 = call_surflet!(1, 1, 1, 0); 135 | let f0001 = call_surflet!(0, 0, 0, 1); 136 | let f1001 = call_surflet!(1, 0, 0, 1); 137 | let f0101 = call_surflet!(0, 1, 0, 1); 138 | let f1101 = call_surflet!(1, 1, 0, 1); 139 | let f0011 = call_surflet!(0, 0, 1, 1); 140 | let f1011 = call_surflet!(1, 0, 1, 1); 141 | let f0111 = call_surflet!(0, 1, 1, 1); 142 | let f1111 = call_surflet!(1, 1, 1, 1); 143 | 144 | // Multiply by arbitrary value to scale to -1..1 145 | ((f0000 146 | + f1000 147 | + f0100 148 | + f1100 149 | + f0010 150 | + f1010 151 | + f0110 152 | + f1110 153 | + f0001 154 | + f1001 155 | + f0101 156 | + f1101 157 | + f0011 158 | + f1011 159 | + f0111 160 | + f1111) 161 | * SCALE_FACTOR) 162 | .clamp(-1.0, 1.0) 163 | } 164 | -------------------------------------------------------------------------------- /src/core/spheres.rs: -------------------------------------------------------------------------------- 1 | use crate::math::vectors::{Vector2, Vector3, Vector4}; 2 | 3 | macro_rules! impl_sphere { 4 | ($name:ident, $vector:ty) => { 5 | #[inline(always)] 6 | pub fn $name(point: $vector, frequency: f64) -> f64 { 7 | let point = point * frequency; 8 | 9 | let dist_from_center = point.magnitude(); 10 | 11 | let dist_from_smaller_sphere = dist_from_center - dist_from_center.floor(); 12 | let dist_from_larger_sphere = 1.0 - dist_from_smaller_sphere; 13 | let nearest_dist = dist_from_smaller_sphere.min(dist_from_larger_sphere); 14 | 15 | 1.0 - (nearest_dist * 4.0) 16 | } 17 | }; 18 | } 19 | 20 | impl_sphere!(spheres_2d, Vector2); 21 | impl_sphere!(spheres_3d, Vector3); 22 | impl_sphere!(spheres_4d, Vector4); 23 | -------------------------------------------------------------------------------- /src/core/value.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | math::{interpolate::linear, s_curve::quintic::Quintic, vectors::*}, 3 | permutationtable::NoiseHasher, 4 | }; 5 | 6 | pub fn value_2d(point: Vector2, hasher: &NH) -> f64 7 | where 8 | NH: NoiseHasher + ?Sized, 9 | { 10 | let corner = point.floor_to_isize(); 11 | let weight = (point - corner.numcast().unwrap()).map_quintic(); 12 | 13 | macro_rules! get( 14 | ($offset:expr) => { 15 | { 16 | hasher.hash(&(corner + $offset).into_array()) as f64 / 255.0 17 | } 18 | } 19 | ); 20 | 21 | let f00 = get!(Vector2::new(0, 0)); 22 | let f10 = get!(Vector2::new(1, 0)); 23 | let f01 = get!(Vector2::new(0, 1)); 24 | let f11 = get!(Vector2::new(1, 1)); 25 | 26 | let result = linear( 27 | linear(f00, f10, weight.x), 28 | linear(f01, f11, weight.x), 29 | weight.y, 30 | ); 31 | 32 | result * 2.0 - 1.0 33 | } 34 | 35 | pub fn value_3d(point: Vector3, hasher: &NH) -> f64 36 | where 37 | NH: NoiseHasher + ?Sized, 38 | { 39 | let corner = point.floor_to_isize(); 40 | let weight = (point - corner.numcast().unwrap()).map_quintic(); 41 | 42 | macro_rules! get( 43 | ($offset:expr) => { 44 | { 45 | hasher.hash(&(corner + $offset).into_array()) as f64 / 255.0 46 | } 47 | } 48 | ); 49 | 50 | let f000 = get!(Vector3::new(0, 0, 0)); 51 | let f100 = get!(Vector3::new(1, 0, 0)); 52 | let f010 = get!(Vector3::new(0, 1, 0)); 53 | let f110 = get!(Vector3::new(1, 1, 0)); 54 | let f001 = get!(Vector3::new(0, 0, 1)); 55 | let f101 = get!(Vector3::new(1, 0, 1)); 56 | let f011 = get!(Vector3::new(0, 1, 1)); 57 | let f111 = get!(Vector3::new(1, 1, 1)); 58 | 59 | let result = linear( 60 | linear( 61 | linear(f000, f100, weight.x), 62 | linear(f010, f110, weight.x), 63 | weight.y, 64 | ), 65 | linear( 66 | linear(f001, f101, weight.x), 67 | linear(f011, f111, weight.x), 68 | weight.y, 69 | ), 70 | weight.z, 71 | ); 72 | 73 | result * 2.0 - 1.0 74 | } 75 | 76 | pub fn value_4d(point: Vector4, hasher: &NH) -> f64 77 | where 78 | NH: NoiseHasher + ?Sized, 79 | { 80 | let corner = point.floor_to_isize(); 81 | let weight = (point - corner.numcast().unwrap()).map_quintic(); 82 | 83 | macro_rules! get( 84 | ($offset:expr) => { 85 | { 86 | hasher.hash(&(corner + $offset).into_array()) as f64 / 255.0 87 | } 88 | } 89 | ); 90 | 91 | let f0000 = get!(Vector4::new(0, 0, 0, 0)); 92 | let f1000 = get!(Vector4::new(1, 0, 0, 0)); 93 | let f0100 = get!(Vector4::new(0, 1, 0, 0)); 94 | let f1100 = get!(Vector4::new(1, 1, 0, 0)); 95 | let f0010 = get!(Vector4::new(0, 0, 1, 0)); 96 | let f1010 = get!(Vector4::new(1, 0, 1, 0)); 97 | let f0110 = get!(Vector4::new(0, 1, 1, 0)); 98 | let f1110 = get!(Vector4::new(1, 1, 1, 0)); 99 | let f0001 = get!(Vector4::new(0, 0, 0, 1)); 100 | let f1001 = get!(Vector4::new(1, 0, 0, 1)); 101 | let f0101 = get!(Vector4::new(0, 1, 0, 1)); 102 | let f1101 = get!(Vector4::new(1, 1, 0, 1)); 103 | let f0011 = get!(Vector4::new(0, 0, 1, 1)); 104 | let f1011 = get!(Vector4::new(1, 0, 1, 1)); 105 | let f0111 = get!(Vector4::new(0, 1, 1, 1)); 106 | let f1111 = get!(Vector4::new(1, 1, 1, 1)); 107 | 108 | let result = linear( 109 | linear( 110 | linear( 111 | linear(f0000, f1000, weight.x), 112 | linear(f0100, f1100, weight.x), 113 | weight.y, 114 | ), 115 | linear( 116 | linear(f0010, f1010, weight.x), 117 | linear(f0110, f1110, weight.x), 118 | weight.y, 119 | ), 120 | weight.z, 121 | ), 122 | linear( 123 | linear( 124 | linear(f0001, f1001, weight.x), 125 | linear(f0101, f1101, weight.x), 126 | weight.y, 127 | ), 128 | linear( 129 | linear(f0011, f1011, weight.x), 130 | linear(f0111, f1111, weight.x), 131 | weight.y, 132 | ), 133 | weight.z, 134 | ), 135 | weight.w, 136 | ); 137 | 138 | result * 2.0 - 1.0 139 | } 140 | -------------------------------------------------------------------------------- /src/gradient.rs: -------------------------------------------------------------------------------- 1 | #[inline(always)] 2 | #[rustfmt::skip] 3 | pub(crate) fn grad2(index: usize) -> [f64; 2] { 4 | // Vectors are combinations of -1, 0, and 1 5 | // Precompute the normalized element 6 | const DIAG : f64 = core::f64::consts::FRAC_1_SQRT_2; 7 | 8 | match index % 8 { 9 | 0 => [ 1.0, 0.0], 10 | 1 => [ -1.0, 0.0], 11 | 2 => [ 0.0, 1.0], 12 | 3 => [ 0.0, -1.0], 13 | 4 => [ DIAG, DIAG], 14 | 5 => [-DIAG, DIAG], 15 | 6 => [ DIAG, -DIAG], 16 | 7 => [-DIAG, -DIAG], 17 | _ => panic!("Attempt to access gradient {} of 8", index % 8), 18 | } 19 | } 20 | 21 | #[inline(always)] 22 | #[rustfmt::skip] 23 | pub(crate) fn grad3(index: usize) -> [f64; 3] { 24 | // Vectors are combinations of -1, 0, and 1 25 | // Precompute the normalized elements 26 | const DIAG : f64 = core::f64::consts::FRAC_1_SQRT_2; 27 | const DIAG2 : f64 = 0.577_350_269_189_625_8; 28 | 29 | match index % 32 { 30 | // 12 edges repeated twice then 8 corners 31 | 0 | 12 => [ DIAG, DIAG, 0.0], 32 | 1 | 13 => [ -DIAG, DIAG, 0.0], 33 | 2 | 14 => [ DIAG, -DIAG, 0.0], 34 | 3 | 15 => [ -DIAG, -DIAG, 0.0], 35 | 4 | 16 => [ DIAG, 0.0, DIAG], 36 | 5 | 17 => [ -DIAG, 0.0, DIAG], 37 | 6 | 18 => [ DIAG, 0.0, -DIAG], 38 | 7 | 19 => [ -DIAG, 0.0, -DIAG], 39 | 8 | 20 => [ 0.0, DIAG, DIAG], 40 | 9 | 21 => [ 0.0, -DIAG, DIAG], 41 | 10 | 22 => [ 0.0, DIAG, -DIAG], 42 | 11 | 23 => [ 0.0, -DIAG, -DIAG], 43 | 24 => [ DIAG2, DIAG2, DIAG2], 44 | 25 => [-DIAG2, DIAG2, DIAG2], 45 | 26 => [ DIAG2, -DIAG2, DIAG2], 46 | 27 => [-DIAG2, -DIAG2, DIAG2], 47 | 28 => [ DIAG2, DIAG2, -DIAG2], 48 | 29 => [-DIAG2, DIAG2, -DIAG2], 49 | 30 => [ DIAG2, -DIAG2, -DIAG2], 50 | 31 => [-DIAG2, -DIAG2, -DIAG2], 51 | _ => panic!("Attempt to access gradient {} of 32", index % 32), 52 | } 53 | } 54 | 55 | #[inline(always)] 56 | #[rustfmt::skip] 57 | pub(crate) fn grad4(index: usize) -> [f64; 4] { 58 | // Vectors are combinations of -1, 0, and 1 59 | // Precompute the normalized elements 60 | const DIAG : f64 = 0.577_350_269_189_625_8; 61 | const DIAG2 : f64 = 0.5; 62 | 63 | match index % 64 { 64 | // 32 edges then 16 corners repeated twice 65 | 0 => [ 0.0, DIAG, DIAG, DIAG], 66 | 1 => [ 0.0, DIAG, DIAG, -DIAG], 67 | 2 => [ 0.0, DIAG, -DIAG, DIAG], 68 | 3 => [ 0.0, DIAG, -DIAG, -DIAG], 69 | 4 => [ 0.0, -DIAG, DIAG, DIAG], 70 | 5 => [ 0.0, -DIAG, DIAG, -DIAG], 71 | 6 => [ 0.0, -DIAG, -DIAG, DIAG], 72 | 7 => [ 0.0, -DIAG, -DIAG, -DIAG], 73 | 8 => [ DIAG, 0.0, DIAG, DIAG], 74 | 9 => [ DIAG, 0.0, DIAG, -DIAG], 75 | 10 => [ DIAG, 0.0, -DIAG, DIAG], 76 | 11 => [ DIAG, 0.0, -DIAG, -DIAG], 77 | 12 => [ -DIAG, 0.0, DIAG, DIAG], 78 | 13 => [ -DIAG, 0.0, DIAG, -DIAG], 79 | 14 => [ -DIAG, 0.0, -DIAG, DIAG], 80 | 15 => [ -DIAG, 0.0, -DIAG, -DIAG], 81 | 16 => [ DIAG, DIAG, 0.0, DIAG], 82 | 17 => [ DIAG, DIAG, 0.0, -DIAG], 83 | 18 => [ DIAG, -DIAG, 0.0, DIAG], 84 | 19 => [ DIAG, -DIAG, 0.0, -DIAG], 85 | 20 => [ -DIAG, DIAG, 0.0, DIAG], 86 | 21 => [ -DIAG, DIAG, 0.0, -DIAG], 87 | 22 => [ -DIAG, -DIAG, 0.0, DIAG], 88 | 23 => [ -DIAG, -DIAG, 0.0, -DIAG], 89 | 24 => [ DIAG, DIAG, DIAG, 0.0], 90 | 25 => [ DIAG, DIAG, -DIAG, 0.0], 91 | 26 => [ DIAG, -DIAG, DIAG, 0.0], 92 | 27 => [ DIAG, -DIAG, -DIAG, 0.0], 93 | 28 => [ -DIAG, DIAG, DIAG, 0.0], 94 | 29 => [ -DIAG, DIAG, -DIAG, 0.0], 95 | 30 => [ -DIAG, -DIAG, DIAG, 0.0], 96 | 31 => [ -DIAG, -DIAG, -DIAG, 0.0], 97 | 32 | 48 => [ DIAG2, DIAG2, DIAG2, DIAG2], 98 | 33 | 49 => [-DIAG2, DIAG2, DIAG2, DIAG2], 99 | 34 | 50 => [ DIAG2, -DIAG2, DIAG2, DIAG2], 100 | 35 | 51 => [-DIAG2, -DIAG2, DIAG2, DIAG2], 101 | 36 | 52 => [ DIAG2, DIAG2, -DIAG2, DIAG2], 102 | 37 | 53 => [-DIAG2, DIAG2, -DIAG2, DIAG2], 103 | 38 | 54 => [ DIAG2, DIAG2, DIAG2, -DIAG2], 104 | 39 | 55 => [-DIAG2, DIAG2, DIAG2, -DIAG2], 105 | 40 | 56 => [ DIAG2, -DIAG2, -DIAG2, DIAG2], 106 | 41 | 57 => [-DIAG2, -DIAG2, -DIAG2, DIAG2], 107 | 42 | 58 => [ DIAG2, -DIAG2, DIAG2, -DIAG2], 108 | 43 | 59 => [-DIAG2, -DIAG2, DIAG2, -DIAG2], 109 | 44 | 60 => [ DIAG2, DIAG2, -DIAG2, -DIAG2], 110 | 45 | 61 => [-DIAG2, DIAG2, -DIAG2, -DIAG2], 111 | 46 | 62 => [ DIAG2, -DIAG2, -DIAG2, -DIAG2], 112 | 47 | 63 => [-DIAG2, -DIAG2, -DIAG2, -DIAG2], 113 | _ => panic!("Attempt to access gradient {} of 64", index % 64), 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! A procedural noise generation library for Rust. 2 | //! 3 | //! # Example 4 | //! 5 | //! ```rust 6 | //! use noise::{NoiseFn, Perlin, Seedable}; 7 | //! 8 | //! let perlin = Perlin::new(1); 9 | //! let val = perlin.get([42.4, 37.7, 2.8]); 10 | //! ``` 11 | 12 | #![cfg_attr(not(feature = "std"), no_std)] 13 | #![deny(missing_copy_implementations)] 14 | 15 | #[macro_use] 16 | extern crate alloc; 17 | 18 | pub use crate::math::vectors::*; 19 | pub use crate::noise_fns::*; 20 | 21 | pub mod core; 22 | mod gradient; 23 | pub mod math; 24 | mod noise_fns; 25 | pub mod permutationtable; 26 | pub mod utils; 27 | -------------------------------------------------------------------------------- /src/math.rs: -------------------------------------------------------------------------------- 1 | //! An ultra-light private math library to make our short lives easier as we 2 | //! implement super-complex noise stuff. 3 | 4 | pub(crate) mod interpolate; 5 | pub(crate) mod s_curve; 6 | pub mod vectors; 7 | 8 | #[cfg(not(target_os = "emscripten"))] 9 | #[inline] 10 | pub(crate) fn scale_shift(value: f64, n: f64) -> f64 { 11 | value.abs().mul_add(n, -1.0_f64) 12 | } 13 | 14 | #[cfg(target_os = "emscripten")] 15 | #[inline] 16 | pub(crate) fn scale_shift(value: f64, n: f64) -> f64 { 17 | (value.abs() * n) + -1.0_f64 18 | } 19 | -------------------------------------------------------------------------------- /src/math/interpolate.rs: -------------------------------------------------------------------------------- 1 | use core::ops::{Add, Mul, Sub}; 2 | 3 | /// Performs linear interpolation between two values. 4 | #[inline(always)] 5 | pub fn linear(a: T, b: T, alpha: f64) -> T 6 | where 7 | T: Mul + Add, 8 | { 9 | b * alpha + a * (1.0 - alpha) 10 | } 11 | 12 | /// Performs cubic interpolation between two values bound between two other 13 | /// values. 14 | /// 15 | /// - n0 - The value before the first value. 16 | /// - n1 - The first value. 17 | /// - n2 - The second value. 18 | /// - n3 - The value after the second value. 19 | /// - alpha - The alpha value. 20 | /// 21 | /// The alpha value should range from 0.0 to 1.0. If the alpha value is 22 | /// 0.0, this function returns _n1_. If the alpha value is 1.0, this 23 | /// function returns _n2_. 24 | #[inline] 25 | pub(crate) fn cubic(n0: T, n1: T, n2: T, n3: T, alpha: T) -> T 26 | where 27 | T: Add + Mul + Sub + Copy, 28 | { 29 | let p = (n3 - n2) - (n0 - n1); 30 | let q = (n0 - n1) - p; 31 | let r = n2 - n0; 32 | let s = n1; 33 | p * alpha * alpha * alpha + q * alpha * alpha + r * alpha + s 34 | } 35 | -------------------------------------------------------------------------------- /src/math/s_curve.rs: -------------------------------------------------------------------------------- 1 | pub(crate) mod cubic; 2 | pub(crate) mod quintic; 3 | -------------------------------------------------------------------------------- /src/math/s_curve/cubic.rs: -------------------------------------------------------------------------------- 1 | use num_traits::Float; 2 | 3 | /// Cubic S-Curve 4 | /// 5 | /// Maps the provided value onto the cubic S-curve function -2x3 + 3x2. 6 | /// This creates a curve with endpoints (0,0) and (1,1), and a first derivative of zero at the 7 | /// endpoints, allowing the curves to be combined together without discontinuities. 8 | /// 9 | /// Values outside the range of [0, 1] will be clamped to the range before mapping. 10 | pub trait Cubic { 11 | fn map_cubic(&self) -> Self; 12 | } 13 | 14 | impl Cubic for f32 { 15 | fn map_cubic(&self) -> Self { 16 | let x = self.clamp(0.0, 1.0); 17 | 18 | x * x * (3.0 - (x * 2.0)) 19 | } 20 | } 21 | 22 | impl Cubic for f64 { 23 | fn map_cubic(&self) -> Self { 24 | let x = self.clamp(0.0, 1.0); 25 | 26 | x * x * (3.0 - (x * 2.0)) 27 | } 28 | } 29 | 30 | impl Cubic for [T; 2] 31 | where 32 | T: Float + Cubic, 33 | { 34 | fn map_cubic(&self) -> Self { 35 | [self[0].map_cubic(), self[1].map_cubic()] 36 | } 37 | } 38 | 39 | impl Cubic for [T; 3] 40 | where 41 | T: Float + Cubic, 42 | { 43 | fn map_cubic(&self) -> Self { 44 | [ 45 | self[0].map_cubic(), 46 | self[1].map_cubic(), 47 | self[2].map_cubic(), 48 | ] 49 | } 50 | } 51 | 52 | impl Cubic for [T; 4] 53 | where 54 | T: Float + Cubic, 55 | { 56 | fn map_cubic(&self) -> Self { 57 | [ 58 | self[0].map_cubic(), 59 | self[1].map_cubic(), 60 | self[2].map_cubic(), 61 | self[3].map_cubic(), 62 | ] 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/math/s_curve/quintic.rs: -------------------------------------------------------------------------------- 1 | use crate::math::vectors::*; 2 | use num_traits::Float; 3 | 4 | /// Quintic Interpolation Trait 5 | /// 6 | /// Interpolates the provided value according to the quintic S-curve function 7 | /// 6x5 - 15x4 + 10x3. This creates a curve with endpoints (0,0) 8 | /// and (1,1), and first and second derivatives of zero at the endpoints, allowing the curves to be 9 | /// combined together without discontinuities. 10 | /// 11 | /// Values outside the range of [0, 1] will be clamped to the range before mapping. 12 | pub trait Quintic { 13 | fn map_quintic(&self) -> Self; 14 | } 15 | 16 | impl Quintic for f32 { 17 | fn map_quintic(&self) -> Self { 18 | let x = self.clamp(0.0, 1.0); 19 | 20 | x * x * x * (x * (x * 6.0 - 15.0) + 10.0) 21 | } 22 | } 23 | 24 | impl Quintic for f64 { 25 | fn map_quintic(&self) -> Self { 26 | let x = self.clamp(0.0, 1.0); 27 | 28 | x * x * x * (x * (x * 6.0 - 15.0) + 10.0) 29 | } 30 | } 31 | 32 | impl Quintic for [T; 2] 33 | where 34 | T: Float + Quintic, 35 | { 36 | fn map_quintic(&self) -> Self { 37 | [self[0].map_quintic(), self[1].map_quintic()] 38 | } 39 | } 40 | 41 | impl Quintic for [T; 3] 42 | where 43 | T: Float + Quintic, 44 | { 45 | fn map_quintic(&self) -> Self { 46 | [ 47 | self[0].map_quintic(), 48 | self[1].map_quintic(), 49 | self[2].map_quintic(), 50 | ] 51 | } 52 | } 53 | 54 | impl Quintic for [T; 4] 55 | where 56 | T: Float + Quintic, 57 | { 58 | fn map_quintic(&self) -> Self { 59 | [ 60 | self[0].map_quintic(), 61 | self[1].map_quintic(), 62 | self[2].map_quintic(), 63 | self[3].map_quintic(), 64 | ] 65 | } 66 | } 67 | 68 | impl Quintic for Vector2 69 | where 70 | T: Float + Quintic, 71 | { 72 | fn map_quintic(&self) -> Self { 73 | self.map(|x| x.map_quintic()) 74 | } 75 | } 76 | 77 | impl Quintic for Vector3 78 | where 79 | T: Float + Quintic, 80 | { 81 | fn map_quintic(&self) -> Self { 82 | self.map(|x| x.map_quintic()) 83 | } 84 | } 85 | 86 | impl Quintic for Vector4 87 | where 88 | T: Float + Quintic, 89 | { 90 | fn map_quintic(&self) -> Self { 91 | self.map(|x| x.map_quintic()) 92 | } 93 | } 94 | 95 | // impl Quintic for V 96 | // where 97 | // T: Float + Quintic, 98 | // V: Vector, 99 | // { 100 | // fn map_quintic(&self) -> Self { 101 | // self.map(|x| x.map_quintic()) 102 | // } 103 | // } 104 | 105 | // #[inline(always)] 106 | // pub fn quintic(x: F) -> F 107 | // where 108 | // F: Float, 109 | // { 110 | // x * x * x * (x * (x * F::from(6.0).unwrap() - F::from(15.0).unwrap()) + F::from(10.0).unwrap()) 111 | // } 112 | -------------------------------------------------------------------------------- /src/noise_fns.rs: -------------------------------------------------------------------------------- 1 | pub use self::{ 2 | cache::*, combiners::*, generators::*, modifiers::*, selectors::*, transformers::*, 3 | }; 4 | use alloc::boxed::Box; 5 | 6 | mod cache; 7 | mod combiners; 8 | mod generators; 9 | mod modifiers; 10 | mod selectors; 11 | mod transformers; 12 | 13 | /// Base trait for noise functions. 14 | /// 15 | /// A noise function is a object that calculates and outputs a value given a 16 | /// n-Dimensional input value, where n is (2,3,4). 17 | /// 18 | /// Each type of noise function uses a specific method to calculate an output 19 | /// value. Some of these methods include: 20 | /// 21 | /// * Calculating a value using a coherent-noise function or some other 22 | /// mathematical function. 23 | /// * Mathematically changing the output value from another noise function 24 | /// in various ways. 25 | /// * Combining the output values from two noise functions in various ways. 26 | pub trait NoiseFn { 27 | fn get(&self, point: [T; DIM]) -> f64; 28 | } 29 | 30 | impl NoiseFn for &M 31 | where 32 | M: NoiseFn + ?Sized, 33 | { 34 | #[inline] 35 | fn get(&self, point: [T; DIM]) -> f64 { 36 | M::get(*self, point) 37 | } 38 | } 39 | 40 | impl NoiseFn for Box 41 | where 42 | M: NoiseFn + ?Sized, 43 | { 44 | #[inline] 45 | fn get(&self, point: [T; DIM]) -> f64 { 46 | M::get(self, point) 47 | } 48 | } 49 | 50 | /// Trait for functions that require a seed before generating their values 51 | pub trait Seedable { 52 | /// Set the seed for the function implementing the `Seedable` trait 53 | fn set_seed(self, seed: u32) -> Self; 54 | 55 | /// Getter to retrieve the seed from the function 56 | fn seed(&self) -> u32; 57 | } 58 | -------------------------------------------------------------------------------- /src/noise_fns/cache.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | use alloc::vec::Vec; 3 | use core::cell::{Cell, RefCell}; 4 | 5 | /// Noise function that caches the last output value generated by the source 6 | /// function. 7 | /// 8 | /// If the input coordinates passed to `Cache::get` are equal to the previous 9 | /// call, the function returns the cached result of the previous call to 10 | /// `Source::get`. Otherwise, `Source::get` is called with the new coordinates, 11 | /// overwriting the cache with the result, and returning the result to the 12 | /// caller. 13 | /// 14 | /// Caching a noise function is useful if it is used as a source function for 15 | /// multiple noise functions. If a source function is not cached, the source 16 | /// function will redundantly calculate the same output value once for each 17 | /// noise function in which it is included. 18 | #[derive(Clone, Debug)] 19 | pub struct Cache { 20 | /// Outputs the value to be cached. 21 | pub source: Source, 22 | 23 | value: Cell>, 24 | 25 | point: RefCell>, 26 | } 27 | 28 | impl Cache { 29 | pub fn new(source: Source) -> Self { 30 | Cache { 31 | source, 32 | value: Cell::new(None), 33 | point: RefCell::new(Vec::new()), 34 | } 35 | } 36 | } 37 | 38 | impl NoiseFn for Cache 39 | where 40 | Source: NoiseFn, 41 | { 42 | fn get(&self, point: [f64; DIM]) -> f64 { 43 | match self.value.get() { 44 | Some(value) if quick_eq(&self.point.borrow(), &point) => value, 45 | Some(_) | None => { 46 | let value = self.source.get(point); 47 | self.value.set(Some(value)); 48 | 49 | let mut cached_point = self.point.borrow_mut(); 50 | cached_point.clear(); 51 | cached_point.extend_from_slice(&point); 52 | 53 | value 54 | } 55 | } 56 | } 57 | } 58 | 59 | fn quick_eq(a: &[f64], b: &[f64]) -> bool { 60 | assert_eq!(a.len(), b.len()); 61 | 62 | a.iter().eq(b) 63 | } 64 | -------------------------------------------------------------------------------- /src/noise_fns/combiners.rs: -------------------------------------------------------------------------------- 1 | pub use self::{add::*, max::*, min::*, multiply::*, power::*}; 2 | 3 | mod add; 4 | mod max; 5 | mod min; 6 | mod multiply; 7 | mod power; 8 | -------------------------------------------------------------------------------- /src/noise_fns/combiners/add.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that outputs the sum of the two output values from two source 5 | /// functions. 6 | #[derive(Clone, Debug)] 7 | pub struct Add 8 | where 9 | Source1: NoiseFn, 10 | Source2: NoiseFn, 11 | { 12 | /// Outputs a value. 13 | pub source1: Source1, 14 | 15 | /// Outputs a value. 16 | pub source2: Source2, 17 | 18 | phantom: PhantomData, 19 | } 20 | 21 | impl Add 22 | where 23 | Source1: NoiseFn, 24 | Source2: NoiseFn, 25 | { 26 | pub fn new(source1: Source1, source2: Source2) -> Self { 27 | Self { 28 | source1, 29 | source2, 30 | phantom: PhantomData, 31 | } 32 | } 33 | } 34 | 35 | impl NoiseFn for Add 36 | where 37 | T: Copy, 38 | Source1: NoiseFn, 39 | Source2: NoiseFn, 40 | { 41 | fn get(&self, point: [T; DIM]) -> f64 { 42 | self.source1.get(point) + self.source2.get(point) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/noise_fns/combiners/max.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that outputs the larger of the two output values from two source 5 | /// functions. 6 | #[derive(Clone, Debug)] 7 | pub struct Max 8 | where 9 | Source1: NoiseFn, 10 | Source2: NoiseFn, 11 | { 12 | /// Outputs a value. 13 | pub source1: Source1, 14 | 15 | /// Outputs a value. 16 | pub source2: Source2, 17 | 18 | phantom: PhantomData, 19 | } 20 | 21 | impl Max 22 | where 23 | Source1: NoiseFn, 24 | Source2: NoiseFn, 25 | { 26 | pub fn new(source1: Source1, source2: Source2) -> Self { 27 | Self { 28 | source1, 29 | source2, 30 | phantom: PhantomData, 31 | } 32 | } 33 | } 34 | 35 | impl NoiseFn for Max 36 | where 37 | T: Copy, 38 | Source1: NoiseFn, 39 | Source2: NoiseFn, 40 | { 41 | fn get(&self, point: [T; DIM]) -> f64 { 42 | (self.source1.get(point)).max(self.source2.get(point)) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/noise_fns/combiners/min.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that outputs the smaller of the two output values from two source 5 | /// functions. 6 | #[derive(Clone, Debug)] 7 | pub struct Min 8 | where 9 | Source1: NoiseFn, 10 | Source2: NoiseFn, 11 | { 12 | /// Outputs a value. 13 | pub source1: Source1, 14 | 15 | /// Outputs a value. 16 | pub source2: Source2, 17 | 18 | phantom: PhantomData, 19 | } 20 | 21 | impl Min 22 | where 23 | Source1: NoiseFn, 24 | Source2: NoiseFn, 25 | { 26 | pub fn new(source1: Source1, source2: Source2) -> Self { 27 | Self { 28 | source1, 29 | source2, 30 | phantom: PhantomData, 31 | } 32 | } 33 | } 34 | 35 | impl NoiseFn for Min 36 | where 37 | T: Copy, 38 | Source1: NoiseFn, 39 | Source2: NoiseFn, 40 | { 41 | fn get(&self, point: [T; DIM]) -> f64 { 42 | (self.source1.get(point)).min(self.source2.get(point)) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/noise_fns/combiners/multiply.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that outputs the product of the two output values from two source 5 | /// functions. 6 | #[derive(Clone, Debug)] 7 | pub struct Multiply 8 | where 9 | Source1: NoiseFn, 10 | Source2: NoiseFn, 11 | { 12 | /// Outputs a value. 13 | pub source1: Source1, 14 | 15 | /// Outputs a value. 16 | pub source2: Source2, 17 | 18 | phantom: PhantomData, 19 | } 20 | 21 | impl Multiply 22 | where 23 | Source1: NoiseFn, 24 | Source2: NoiseFn, 25 | { 26 | pub fn new(source1: Source1, source2: Source2) -> Self { 27 | Self { 28 | source1, 29 | source2, 30 | phantom: PhantomData, 31 | } 32 | } 33 | } 34 | 35 | impl NoiseFn for Multiply 36 | where 37 | T: Copy, 38 | Source1: NoiseFn, 39 | Source2: NoiseFn, 40 | { 41 | fn get(&self, point: [T; DIM]) -> f64 { 42 | self.source1.get(point) * self.source2.get(point) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/noise_fns/combiners/power.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that raises the output value from the first source function 5 | /// to the power of the output value of the second source function. 6 | #[derive(Clone, Debug)] 7 | pub struct Power 8 | where 9 | Source1: NoiseFn, 10 | Source2: NoiseFn, 11 | { 12 | /// Outputs a value. 13 | pub source1: Source1, 14 | 15 | /// Outputs a value. 16 | pub source2: Source2, 17 | 18 | phantom: PhantomData, 19 | } 20 | 21 | impl Power 22 | where 23 | Source1: NoiseFn, 24 | Source2: NoiseFn, 25 | { 26 | pub fn new(source1: Source1, source2: Source2) -> Self { 27 | Self { 28 | source1, 29 | source2, 30 | phantom: PhantomData, 31 | } 32 | } 33 | } 34 | 35 | impl NoiseFn for Power 36 | where 37 | T: Copy, 38 | Source1: NoiseFn, 39 | Source2: NoiseFn, 40 | { 41 | fn get(&self, point: [T; DIM]) -> f64 { 42 | (self.source1.get(point)).powf(self.source2.get(point)) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/noise_fns/generators.rs: -------------------------------------------------------------------------------- 1 | pub use self::{ 2 | checkerboard::*, constant::*, cylinders::*, fractals::*, open_simplex::*, perlin::*, 3 | perlin_surflet::*, simplex::*, super_simplex::*, value::*, worley::*, 4 | }; 5 | 6 | mod checkerboard; 7 | mod constant; 8 | mod cylinders; 9 | mod fractals; 10 | mod open_simplex; 11 | mod perlin; 12 | mod perlin_surflet; 13 | mod simplex; 14 | mod super_simplex; 15 | mod value; 16 | mod worley; 17 | -------------------------------------------------------------------------------- /src/noise_fns/generators/checkerboard.rs: -------------------------------------------------------------------------------- 1 | use crate::{core::checkerboard::*, noise_fns::NoiseFn}; 2 | 3 | /// Noise function that outputs a checkerboard pattern. 4 | /// 5 | /// This noise function can take one input, size, and outputs 2size-sized 6 | /// blocks of alternating values. The values of these blocks alternate between 7 | /// -1.0 and 1.0. 8 | /// 9 | /// This noise function is not very useful by itself, but it can be used for 10 | /// debugging purposes. 11 | #[derive(Clone, Copy, Debug)] 12 | pub struct Checkerboard { 13 | // Controls the size of the block in 2^(size). 14 | size: usize, 15 | } 16 | 17 | impl Checkerboard { 18 | const DEFAULT_SIZE: usize = 0; 19 | 20 | /// Controls the size of the block in 2^(size) units. 21 | pub fn new(size: usize) -> Self { 22 | Self { size: 1 << size } 23 | } 24 | 25 | pub fn set_size(self, size: usize) -> Self { 26 | Self { size: 1 << size } 27 | } 28 | 29 | pub fn size(self) -> usize { 30 | self.size 31 | } 32 | } 33 | 34 | impl Default for Checkerboard { 35 | fn default() -> Self { 36 | Self { 37 | size: 1 << Checkerboard::DEFAULT_SIZE, 38 | } 39 | } 40 | } 41 | 42 | impl NoiseFn for Checkerboard { 43 | fn get(&self, point: [f64; 2]) -> f64 { 44 | checkerboard_2d(point.into(), self.size as f64) 45 | } 46 | } 47 | 48 | impl NoiseFn for Checkerboard { 49 | fn get(&self, point: [f64; 3]) -> f64 { 50 | checkerboard_3d(point.into(), self.size as f64) 51 | } 52 | } 53 | 54 | impl NoiseFn for Checkerboard { 55 | fn get(&self, point: [f64; 4]) -> f64 { 56 | checkerboard_4d(point.into(), self.size as f64) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/noise_fns/generators/constant.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | 3 | /// Noise function that outputs a constant value. 4 | /// 5 | /// This function takes a input, value, and returns that input for all points, 6 | /// producing a constant-valued field. 7 | /// 8 | /// This function is not very useful by itself, but can be used as a source 9 | /// function for other noise functions. 10 | #[derive(Clone, Copy, Debug)] 11 | pub struct Constant { 12 | /// Constant value. 13 | pub value: f64, 14 | } 15 | 16 | impl Constant { 17 | pub fn new(value: f64) -> Self { 18 | Self { value } 19 | } 20 | } 21 | 22 | impl NoiseFn for Constant { 23 | fn get(&self, _point: [T; N]) -> f64 { 24 | self.value 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/noise_fns/generators/cylinders.rs: -------------------------------------------------------------------------------- 1 | use crate::{core::spheres::*, math::vectors::Vector2, noise_fns::NoiseFn}; 2 | 3 | /// Noise function that outputs concentric cylinders. 4 | /// 5 | /// This noise function outputs concentric cylinders centered on the origin. The 6 | /// cylinders are oriented along the z axis similar to the concentric rings of 7 | /// a tree. Each cylinder extends infinitely along the z axis. 8 | #[derive(Clone, Copy, Debug)] 9 | pub struct Cylinders { 10 | /// Frequency of the concentric objects. 11 | pub frequency: f64, 12 | } 13 | 14 | impl Cylinders { 15 | pub const DEFAULT_FREQUENCY: f64 = 1.0; 16 | 17 | pub fn new() -> Self { 18 | Self { 19 | frequency: Self::DEFAULT_FREQUENCY, 20 | } 21 | } 22 | 23 | pub fn set_frequency(self, frequency: f64) -> Self { 24 | Self { frequency } 25 | } 26 | } 27 | 28 | impl Default for Cylinders { 29 | fn default() -> Self { 30 | Self::new() 31 | } 32 | } 33 | 34 | impl NoiseFn for Cylinders { 35 | fn get(&self, point: [f64; 2]) -> f64 { 36 | spheres_2d(point.into(), self.frequency) 37 | } 38 | } 39 | 40 | impl NoiseFn for Cylinders { 41 | fn get(&self, point: [f64; 3]) -> f64 { 42 | spheres_2d(Vector2::new(point[0], point[1]), self.frequency) 43 | } 44 | } 45 | 46 | impl NoiseFn for Cylinders { 47 | fn get(&self, point: [f64; 4]) -> f64 { 48 | spheres_2d(Vector2::new(point[0], point[1]), self.frequency) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/noise_fns/generators/fractals.rs: -------------------------------------------------------------------------------- 1 | pub use self::{basicmulti::*, billow::*, fbm::*, hybridmulti::*, ridgedmulti::*}; 2 | use alloc::vec::Vec; 3 | 4 | mod basicmulti; 5 | mod billow; 6 | mod fbm; 7 | mod hybridmulti; 8 | mod ridgedmulti; 9 | 10 | use crate::Seedable; 11 | 12 | /// Trait for `MultiFractal` functions 13 | pub trait MultiFractal { 14 | fn set_octaves(self, octaves: usize) -> Self; 15 | 16 | fn set_frequency(self, frequency: f64) -> Self; 17 | 18 | fn set_lacunarity(self, lacunarity: f64) -> Self; 19 | 20 | fn set_persistence(self, persistence: f64) -> Self; 21 | } 22 | 23 | fn build_sources(seed: u32, octaves: usize) -> Vec 24 | where 25 | Source: Default + Seedable, 26 | { 27 | let mut sources = Vec::with_capacity(octaves); 28 | for x in 0..octaves { 29 | let source = Source::default(); 30 | sources.push(source.set_seed(seed + x as u32)); 31 | } 32 | sources 33 | } 34 | -------------------------------------------------------------------------------- /src/noise_fns/generators/open_simplex.rs: -------------------------------------------------------------------------------- 1 | //! Note that this is NOT Ken Perlin's simplex noise, as that is patent encumbered. 2 | //! Instead, these functions use the `OpenSimplex` algorithm, as detailed here: 3 | //! 4 | 5 | use crate::{ 6 | core::open_simplex::{open_simplex_2d, open_simplex_3d, open_simplex_4d}, 7 | noise_fns::{NoiseFn, Seedable}, 8 | permutationtable::PermutationTable, 9 | }; 10 | 11 | /// Noise function that outputs 2/3/4-dimensional Open Simplex noise. 12 | #[derive(Clone, Copy, Debug)] 13 | pub struct OpenSimplex { 14 | seed: u32, 15 | perm_table: PermutationTable, 16 | } 17 | 18 | impl OpenSimplex { 19 | const DEFAULT_SEED: u32 = 0; 20 | 21 | pub fn new(seed: u32) -> Self { 22 | Self { 23 | seed, 24 | perm_table: PermutationTable::new(seed), 25 | } 26 | } 27 | } 28 | 29 | impl Default for OpenSimplex { 30 | fn default() -> Self { 31 | Self::new(Self::DEFAULT_SEED) 32 | } 33 | } 34 | 35 | impl Seedable for OpenSimplex { 36 | /// Sets the seed value for Open Simplex noise 37 | fn set_seed(self, seed: u32) -> Self { 38 | // If the new seed is the same as the current seed, just return self. 39 | if self.seed == seed { 40 | return self; 41 | } 42 | 43 | // Otherwise, regenerate the permutation table based on the new seed. 44 | Self { 45 | seed, 46 | perm_table: PermutationTable::new(seed), 47 | } 48 | } 49 | 50 | fn seed(&self) -> u32 { 51 | self.seed 52 | } 53 | } 54 | 55 | /// 2-dimensional [`OpenSimplex` Noise](http://uniblock.tumblr.com/post/97868843242/noise) 56 | /// 57 | /// This is a slower but higher quality form of gradient noise than `Perlin` 2D. 58 | impl NoiseFn for OpenSimplex { 59 | fn get(&self, point: [f64; 2]) -> f64 { 60 | open_simplex_2d(point.into(), &self.perm_table) 61 | } 62 | } 63 | 64 | /// 3-dimensional [`OpenSimplex` Noise](http://uniblock.tumblr.com/post/97868843242/noise) 65 | /// 66 | /// This is a slower but higher quality form of gradient noise than `Perlin` 3D. 67 | impl NoiseFn for OpenSimplex { 68 | fn get(&self, point: [f64; 3]) -> f64 { 69 | open_simplex_3d(point.into(), &self.perm_table) 70 | } 71 | } 72 | 73 | /// 4-dimensional [`OpenSimplex` Noise](http://uniblock.tumblr.com/post/97868843242/noise) 74 | /// 75 | /// This is a slower but higher quality form of gradient noise than `Perlin` 4D. 76 | impl NoiseFn for OpenSimplex { 77 | fn get(&self, point: [f64; 4]) -> f64 { 78 | open_simplex_4d(point.into(), &self.perm_table) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/noise_fns/generators/perlin.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | core::perlin::*, 3 | noise_fns::{NoiseFn, Seedable}, 4 | permutationtable::PermutationTable, 5 | }; 6 | 7 | /// Noise function that outputs 1/2/3/4-dimensional Perlin noise. 8 | #[derive(Clone, Copy, Debug)] 9 | pub struct Perlin { 10 | seed: u32, 11 | perm_table: PermutationTable, 12 | } 13 | 14 | impl Perlin { 15 | pub const DEFAULT_SEED: u32 = 0; 16 | 17 | pub fn new(seed: u32) -> Self { 18 | Self { 19 | seed, 20 | perm_table: PermutationTable::new(seed), 21 | } 22 | } 23 | } 24 | 25 | impl Default for Perlin { 26 | fn default() -> Self { 27 | Self::new(Self::DEFAULT_SEED) 28 | } 29 | } 30 | 31 | impl Seedable for Perlin { 32 | /// Sets the seed value for Perlin noise 33 | fn set_seed(self, seed: u32) -> Self { 34 | // If the new seed is the same as the current seed, just return self. 35 | if self.seed == seed { 36 | return self; 37 | } 38 | 39 | // Otherwise, regenerate the permutation table based on the new seed. 40 | Self { 41 | seed, 42 | perm_table: PermutationTable::new(seed), 43 | } 44 | } 45 | 46 | fn seed(&self) -> u32 { 47 | self.seed 48 | } 49 | } 50 | 51 | /// 1-dimensional perlin noise 52 | impl NoiseFn for Perlin { 53 | fn get(&self, point: [f64; 1]) -> f64 { 54 | perlin_1d(point[0], &self.perm_table) 55 | } 56 | } 57 | 58 | /// 2-dimensional perlin noise 59 | impl NoiseFn for Perlin { 60 | fn get(&self, point: [f64; 2]) -> f64 { 61 | perlin_2d(point.into(), &self.perm_table) 62 | } 63 | } 64 | 65 | /// 3-dimensional perlin noise 66 | impl NoiseFn for Perlin { 67 | fn get(&self, point: [f64; 3]) -> f64 { 68 | perlin_3d(point.into(), &self.perm_table) 69 | } 70 | } 71 | 72 | /// 4-dimensional perlin noise 73 | impl NoiseFn for Perlin { 74 | fn get(&self, point: [f64; 4]) -> f64 { 75 | perlin_4d(point.into(), &self.perm_table) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/noise_fns/generators/perlin_surflet.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | core::perlin_surflet::*, 3 | noise_fns::{NoiseFn, Seedable}, 4 | permutationtable::PermutationTable, 5 | }; 6 | 7 | /// Noise function that outputs 2/3/4-dimensional Perlin noise. 8 | /// 9 | /// THis is a variant of original perlin noise, based on the principles of simplex noise to 10 | /// calculate the values at a point using wavelets instead of interpolated gradients. 11 | #[derive(Clone, Copy, Debug)] 12 | pub struct PerlinSurflet { 13 | seed: u32, 14 | perm_table: PermutationTable, 15 | } 16 | 17 | impl PerlinSurflet { 18 | pub const DEFAULT_SEED: u32 = 0; 19 | 20 | pub fn new(seed: u32) -> Self { 21 | Self { 22 | seed, 23 | perm_table: PermutationTable::new(seed), 24 | } 25 | } 26 | } 27 | 28 | impl Default for PerlinSurflet { 29 | fn default() -> Self { 30 | Self::new(Self::DEFAULT_SEED) 31 | } 32 | } 33 | 34 | impl Seedable for PerlinSurflet { 35 | /// Sets the seed value for Perlin noise 36 | fn set_seed(self, seed: u32) -> Self { 37 | // If the new seed is the same as the current seed, just return self. 38 | if self.seed == seed { 39 | return self; 40 | } 41 | 42 | // Otherwise, regenerate the permutation table based on the new seed. 43 | Self { 44 | seed, 45 | perm_table: PermutationTable::new(seed), 46 | } 47 | } 48 | 49 | fn seed(&self) -> u32 { 50 | self.seed 51 | } 52 | } 53 | 54 | /// 2-dimensional perlin noise 55 | impl NoiseFn for PerlinSurflet { 56 | fn get(&self, point: [f64; 2]) -> f64 { 57 | perlin_surflet_2d(point.into(), &self.perm_table) 58 | } 59 | } 60 | 61 | /// 3-dimensional perlin noise 62 | impl NoiseFn for PerlinSurflet { 63 | fn get(&self, point: [f64; 3]) -> f64 { 64 | perlin_surflet_3d(point.into(), &self.perm_table) 65 | } 66 | } 67 | 68 | /// 4-dimensional perlin noise 69 | impl NoiseFn for PerlinSurflet { 70 | fn get(&self, point: [f64; 4]) -> f64 { 71 | perlin_surflet_4d(point.into(), &self.perm_table) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/noise_fns/generators/simplex.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | core::simplex::*, 3 | noise_fns::{NoiseFn, Seedable}, 4 | permutationtable::PermutationTable, 5 | }; 6 | 7 | /// Noise function that outputs N-dimensional Simplex noise. 8 | /// 9 | #[derive(Clone, Copy, Debug)] 10 | pub struct Simplex { 11 | seed: u32, 12 | hasher: PermutationTable, 13 | } 14 | 15 | impl Simplex { 16 | pub const DEFAULT_SEED: u32 = 0; 17 | 18 | pub fn new(seed: u32) -> Self { 19 | Simplex { 20 | seed, 21 | hasher: PermutationTable::new(seed), 22 | } 23 | } 24 | } 25 | 26 | impl Default for Simplex { 27 | fn default() -> Self { 28 | Self::new(Self::DEFAULT_SEED) 29 | } 30 | } 31 | 32 | impl Seedable for Simplex { 33 | /// Sets the seed value for Simplex noise 34 | fn set_seed(self, seed: u32) -> Self { 35 | // If the new seed is the same as the current seed, just return self. 36 | if self.seed == seed { 37 | return self; 38 | } 39 | 40 | // Otherwise, regenerate the permutation table based on the new seed. 41 | Simplex { 42 | seed, 43 | hasher: PermutationTable::new(seed), 44 | } 45 | } 46 | 47 | fn seed(&self) -> u32 { 48 | self.seed 49 | } 50 | } 51 | 52 | /// 2-dimensional Simplex noise 53 | impl NoiseFn for Simplex { 54 | fn get(&self, point: [f64; 2]) -> f64 { 55 | let (result, _) = simplex_2d(point.into(), &self.hasher); 56 | 57 | result 58 | } 59 | } 60 | 61 | /// 3-dimensional Simplex noise 62 | impl NoiseFn for Simplex { 63 | fn get(&self, point: [f64; 3]) -> f64 { 64 | let (result, _) = simplex_3d(point.into(), &self.hasher); 65 | 66 | result 67 | } 68 | } 69 | 70 | /// 4-dimensional Simplex noise 71 | impl NoiseFn for Simplex { 72 | fn get(&self, point: [f64; 4]) -> f64 { 73 | let (result, _) = simplex_4d(point.into(), &self.hasher); 74 | 75 | result 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/noise_fns/generators/super_simplex.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | core::super_simplex::*, 3 | noise_fns::{NoiseFn, Seedable}, 4 | permutationtable::PermutationTable, 5 | }; 6 | 7 | /// Noise function that outputs 2/3-dimensional Super Simplex noise. 8 | #[derive(Clone, Copy, Debug)] 9 | pub struct SuperSimplex { 10 | seed: u32, 11 | perm_table: PermutationTable, 12 | } 13 | 14 | impl SuperSimplex { 15 | pub const DEFAULT_SEED: u32 = 0; 16 | 17 | pub fn new(seed: u32) -> Self { 18 | Self { 19 | seed, 20 | perm_table: PermutationTable::new(seed), 21 | } 22 | } 23 | } 24 | 25 | impl Default for SuperSimplex { 26 | fn default() -> Self { 27 | Self::new(Self::DEFAULT_SEED) 28 | } 29 | } 30 | 31 | impl Seedable for SuperSimplex { 32 | /// Sets the seed value for Super Simplex noise 33 | fn set_seed(self, seed: u32) -> Self { 34 | // If the new seed is the same as the current seed, just return self. 35 | if self.seed == seed { 36 | return self; 37 | } 38 | 39 | // Otherwise, regenerate the permutation table based on the new seed. 40 | Self { 41 | seed, 42 | perm_table: PermutationTable::new(seed), 43 | } 44 | } 45 | 46 | fn seed(&self) -> u32 { 47 | self.seed 48 | } 49 | } 50 | 51 | /// 2-dimensional Super Simplex noise 52 | impl NoiseFn for SuperSimplex { 53 | fn get(&self, point: [f64; 2]) -> f64 { 54 | super_simplex_2d(point.into(), &self.perm_table) 55 | } 56 | } 57 | 58 | /// 3-dimensional Super Simplex noise 59 | impl NoiseFn for SuperSimplex { 60 | fn get(&self, point: [f64; 3]) -> f64 { 61 | super_simplex_3d(point.into(), &self.perm_table) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/noise_fns/generators/value.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | core::value::{value_2d, value_3d, value_4d}, 3 | noise_fns::{NoiseFn, Seedable}, 4 | permutationtable::PermutationTable, 5 | }; 6 | 7 | /// Noise function that outputs 2/3/4-dimensional Value noise. 8 | #[derive(Clone, Copy, Debug)] 9 | pub struct Value { 10 | seed: u32, 11 | perm_table: PermutationTable, 12 | } 13 | 14 | impl Value { 15 | pub const DEFAULT_SEED: u32 = 0; 16 | 17 | pub fn new(seed: u32) -> Self { 18 | Self { 19 | seed, 20 | perm_table: PermutationTable::new(seed), 21 | } 22 | } 23 | } 24 | 25 | impl Default for Value { 26 | fn default() -> Self { 27 | Self::new(Self::DEFAULT_SEED) 28 | } 29 | } 30 | 31 | impl Seedable for Value { 32 | /// Sets the seed value for Value noise 33 | fn set_seed(self, seed: u32) -> Self { 34 | // If the new seed is the same as the current seed, just return self. 35 | if self.seed == seed { 36 | return self; 37 | } 38 | 39 | // Otherwise, regenerate the permutation table based on the new seed. 40 | Self { 41 | seed, 42 | perm_table: PermutationTable::new(seed), 43 | } 44 | } 45 | 46 | fn seed(&self) -> u32 { 47 | self.seed 48 | } 49 | } 50 | 51 | /// 2-dimensional value noise 52 | impl NoiseFn for Value { 53 | fn get(&self, point: [f64; 2]) -> f64 { 54 | value_2d(point.into(), &self.perm_table) 55 | } 56 | } 57 | 58 | /// 3-dimensional value noise 59 | impl NoiseFn for Value { 60 | fn get(&self, point: [f64; 3]) -> f64 { 61 | value_3d(point.into(), &self.perm_table) 62 | } 63 | } 64 | 65 | /// 4-dimensional value noise 66 | impl NoiseFn for Value { 67 | fn get(&self, point: [f64; 4]) -> f64 { 68 | value_4d(point.into(), &self.perm_table) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/noise_fns/generators/worley.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | core::worley::*, 3 | math::vectors::*, 4 | noise_fns::{NoiseFn, Seedable}, 5 | permutationtable::PermutationTable, 6 | }; 7 | use alloc::rc::Rc; 8 | 9 | /// Noise function that outputs Worley noise. 10 | #[derive(Clone)] 11 | pub struct Worley { 12 | /// Specifies the distance function to use when calculating the boundaries of 13 | /// the cell. 14 | pub distance_function: Rc, 15 | 16 | /// Signifies whether the distance from the borders of the cell should be returned, or the 17 | /// value for the cell. 18 | pub return_type: ReturnType, 19 | 20 | /// Frequency of the seed points. 21 | pub frequency: f64, 22 | 23 | seed: u32, 24 | perm_table: PermutationTable, 25 | } 26 | 27 | type DistanceFunction = dyn Fn(&[f64], &[f64]) -> f64; 28 | 29 | impl Worley { 30 | pub const DEFAULT_SEED: u32 = 0; 31 | pub const DEFAULT_FREQUENCY: f64 = 1.0; 32 | 33 | pub fn new(seed: u32) -> Self { 34 | Self { 35 | perm_table: PermutationTable::new(seed), 36 | seed, 37 | distance_function: Rc::new(distance_functions::euclidean), 38 | return_type: ReturnType::Value, 39 | frequency: Self::DEFAULT_FREQUENCY, 40 | } 41 | } 42 | 43 | /// Sets the distance function used by the Worley cells. 44 | pub fn set_distance_function(self, function: F) -> Self 45 | where 46 | F: Fn(&[f64], &[f64]) -> f64 + 'static, 47 | { 48 | Self { 49 | distance_function: Rc::new(function), 50 | ..self 51 | } 52 | } 53 | 54 | /// Enables or disables applying the distance from the nearest seed point 55 | /// to the output value. 56 | pub fn set_return_type(self, return_type: ReturnType) -> Self { 57 | Self { 58 | return_type, 59 | ..self 60 | } 61 | } 62 | 63 | /// Sets the frequency of the seed points. 64 | pub fn set_frequency(self, frequency: f64) -> Self { 65 | Self { frequency, ..self } 66 | } 67 | } 68 | 69 | impl Default for Worley { 70 | fn default() -> Self { 71 | Self::new(0) 72 | } 73 | } 74 | 75 | impl Seedable for Worley { 76 | /// Sets the seed value used by the Worley cells. 77 | fn set_seed(self, seed: u32) -> Self { 78 | // If the new seed is the same as the current seed, just return self. 79 | if self.seed == seed { 80 | return self; 81 | } 82 | 83 | // Otherwise, regenerate the permutation table based on the new seed. 84 | Self { 85 | perm_table: PermutationTable::new(seed), 86 | seed, 87 | ..self 88 | } 89 | } 90 | 91 | fn seed(&self) -> u32 { 92 | self.seed 93 | } 94 | } 95 | 96 | impl NoiseFn for Worley { 97 | fn get(&self, point: [f64; 2]) -> f64 { 98 | worley_2d( 99 | &self.perm_table, 100 | &*self.distance_function, 101 | self.return_type, 102 | Vector2::from(point) * self.frequency, 103 | ) 104 | } 105 | } 106 | 107 | impl NoiseFn for Worley { 108 | fn get(&self, point: [f64; 3]) -> f64 { 109 | worley_3d( 110 | &self.perm_table, 111 | &*self.distance_function, 112 | self.return_type, 113 | Vector3::from(point) * self.frequency, 114 | ) 115 | } 116 | } 117 | 118 | #[allow(clippy::cognitive_complexity)] 119 | impl NoiseFn for Worley { 120 | fn get(&self, point: [f64; 4]) -> f64 { 121 | worley_4d( 122 | &self.perm_table, 123 | &*self.distance_function, 124 | self.return_type, 125 | Vector4::from(point) * self.frequency, 126 | ) 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/noise_fns/modifiers.rs: -------------------------------------------------------------------------------- 1 | pub use self::{abs::*, clamp::*, curve::*, exponent::*, negate::*, scale_bias::*, terrace::*}; 2 | 3 | mod abs; 4 | mod clamp; 5 | mod curve; 6 | mod exponent; 7 | mod negate; 8 | mod scale_bias; 9 | mod terrace; 10 | -------------------------------------------------------------------------------- /src/noise_fns/modifiers/abs.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that outputs the absolute value of the output value from the 5 | /// source function. 6 | #[derive(Clone, Debug)] 7 | pub struct Abs 8 | where 9 | Source: NoiseFn, 10 | { 11 | /// Outputs a value. 12 | pub source: Source, 13 | 14 | phantom: PhantomData, 15 | } 16 | 17 | impl Abs 18 | where 19 | Source: NoiseFn, 20 | { 21 | pub fn new(source: Source) -> Self { 22 | Self { 23 | source, 24 | phantom: PhantomData, 25 | } 26 | } 27 | } 28 | 29 | impl NoiseFn for Abs 30 | where 31 | Source: NoiseFn, 32 | { 33 | fn get(&self, point: [T; DIM]) -> f64 { 34 | (self.source.get(point)).abs() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/noise_fns/modifiers/clamp.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that clamps the output value from the source function to a 5 | /// range of values. 6 | #[derive(Clone, Debug)] 7 | pub struct Clamp 8 | where 9 | Source: NoiseFn, 10 | { 11 | /// Outputs a value. 12 | pub source: Source, 13 | 14 | /// Bound of the clamping range. Default is -1.0 to 1.0. 15 | pub bounds: (f64, f64), 16 | 17 | phantom: PhantomData, 18 | } 19 | 20 | impl Clamp 21 | where 22 | Source: NoiseFn, 23 | { 24 | pub fn new(source: Source) -> Self { 25 | Self { 26 | source, 27 | bounds: (-1.0, 1.0), 28 | phantom: PhantomData, 29 | } 30 | } 31 | 32 | pub fn set_lower_bound(self, lower_bound: f64) -> Self { 33 | Self { 34 | bounds: (lower_bound, self.bounds.1), 35 | ..self 36 | } 37 | } 38 | 39 | pub fn set_upper_bound(self, upper_bound: f64) -> Self { 40 | Self { 41 | bounds: (self.bounds.0, upper_bound), 42 | ..self 43 | } 44 | } 45 | 46 | pub fn set_bounds(self, lower_bound: f64, upper_bound: f64) -> Self { 47 | Self { 48 | bounds: (lower_bound, upper_bound), 49 | ..self 50 | } 51 | } 52 | } 53 | 54 | impl NoiseFn for Clamp 55 | where 56 | Source: NoiseFn, 57 | { 58 | fn get(&self, point: [T; DIM]) -> f64 { 59 | let value = self.source.get(point); 60 | 61 | value.clamp(self.bounds.0, self.bounds.1) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/noise_fns/modifiers/curve.rs: -------------------------------------------------------------------------------- 1 | use crate::{math::interpolate, noise_fns::NoiseFn}; 2 | use alloc::vec::Vec; 3 | use core::marker::PhantomData; 4 | 5 | /// Noise function that maps the output value from the source function onto an 6 | /// arbitrary function curve. 7 | /// 8 | /// This noise function maps the output value from the source function onto an 9 | /// application-defined curve. The curve is defined by a number of _control 10 | /// points_; each control point has an _input value_ that maps to an _output 11 | /// value_. 12 | /// 13 | /// To add control points to the curve, use the `add_control_point` method. 14 | /// 15 | /// Since the curve is a cubic spline, an application must have a minimum of 16 | /// four control points to the curve. If there is less than four control 17 | /// points, the get() method panics. Each control point can have any input 18 | /// and output value, although no two control points can have the same input. 19 | #[derive(Clone, Debug)] 20 | pub struct Curve 21 | where 22 | Source: NoiseFn, 23 | { 24 | /// Outputs a value. 25 | pub source: Source, 26 | 27 | /// Vec that stores the control points. 28 | control_points: Vec>, 29 | 30 | phantom: PhantomData, 31 | } 32 | 33 | #[derive(Clone, Debug)] 34 | struct ControlPoint { 35 | input: T, 36 | output: T, 37 | } 38 | 39 | impl Curve 40 | where 41 | Source: NoiseFn, 42 | { 43 | pub fn new(source: Source) -> Self { 44 | Self { 45 | source, 46 | control_points: Vec::with_capacity(4), 47 | phantom: PhantomData, 48 | } 49 | } 50 | 51 | pub fn add_control_point(mut self, input_value: f64, output_value: f64) -> Self { 52 | // check to see if the vector already contains the input point. 53 | if !self 54 | .control_points 55 | .iter() 56 | .any(|x| (x.input - input_value).abs() < f64::EPSILON) 57 | { 58 | // it doesn't, so find the correct position to insert the new 59 | // control point. 60 | let insertion_point = self 61 | .control_points 62 | .iter() 63 | .position(|x| x.input >= input_value) 64 | .unwrap_or(self.control_points.len()); 65 | 66 | // add the new control point at the correct position. 67 | self.control_points.insert( 68 | insertion_point, 69 | ControlPoint { 70 | input: input_value, 71 | output: output_value, 72 | }, 73 | ); 74 | } 75 | 76 | self 77 | } 78 | } 79 | 80 | impl NoiseFn for Curve 81 | where 82 | Source: NoiseFn, 83 | { 84 | fn get(&self, point: [T; DIM]) -> f64 { 85 | // confirm that there's at least 4 control points in the vector. 86 | assert!(self.control_points.len() >= 4); 87 | 88 | // get output value from the source function 89 | let source_value = self.source.get(point); 90 | 91 | // Find the first element in the control point array that has a input 92 | // value larger than the output value from the source function 93 | let index_pos = self 94 | .control_points 95 | .iter() 96 | .position(|x| x.input > source_value) 97 | .unwrap_or(self.control_points.len()); 98 | 99 | // if index_pos < 2 { 100 | // println!( 101 | // "index_pos in curve was less than 2! source value was {}", 102 | // source_value 103 | // ); 104 | // } 105 | 106 | // ensure that the index is at least 2 and less than control_points.len() 107 | let index_pos = index_pos.clamp(2, self.control_points.len()); 108 | 109 | // Find the four nearest control points so that we can perform cubic 110 | // interpolation. 111 | let index0 = (index_pos - 2).clamp(0, self.control_points.len() - 1); 112 | let index1 = (index_pos - 1).clamp(0, self.control_points.len() - 1); 113 | let index2 = index_pos.clamp(0, self.control_points.len() - 1); 114 | let index3 = (index_pos + 1).clamp(0, self.control_points.len() - 1); 115 | 116 | // If some control points are missing (which occurs if the value from 117 | // the source function is greater than the largest input value or less 118 | // than the smallest input value of the control point array), get the 119 | // corresponding output value of the nearest control point and exit. 120 | if index1 == index2 { 121 | return self.control_points[index1].output; 122 | } 123 | 124 | // Compute the alpha value used for cubic interpolation 125 | let input0 = self.control_points[index1].input; 126 | let input1 = self.control_points[index2].input; 127 | let alpha = (source_value - input0) / (input1 - input0); 128 | 129 | // Now perform the cubic interpolation and return. 130 | interpolate::cubic( 131 | self.control_points[index0].output, 132 | self.control_points[index1].output, 133 | self.control_points[index2].output, 134 | self.control_points[index3].output, 135 | alpha, 136 | ) 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/noise_fns/modifiers/exponent.rs: -------------------------------------------------------------------------------- 1 | use crate::{math::scale_shift, noise_fns::NoiseFn}; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that maps the output value from the source function onto an 5 | /// exponential curve. 6 | /// 7 | /// Because most noise functions will output values that range from -1.0 to 1.0, 8 | /// this noise function first normalizes the output value (the range becomes 0.0 9 | /// to 1.0), maps that value onto an exponential curve, then rescales that 10 | /// value back to the original range. 11 | #[derive(Clone, Debug)] 12 | pub struct Exponent 13 | where 14 | Source: NoiseFn, 15 | { 16 | /// Outputs a value. 17 | pub source: Source, 18 | 19 | /// Exponent to apply to the output value from the source function. Default 20 | /// is 1.0. 21 | pub exponent: f64, 22 | 23 | phantom: PhantomData, 24 | } 25 | 26 | impl Exponent 27 | where 28 | Source: NoiseFn, 29 | { 30 | pub fn new(source: Source) -> Self { 31 | Self { 32 | source, 33 | exponent: 1.0, 34 | phantom: PhantomData, 35 | } 36 | } 37 | 38 | pub fn set_exponent(self, exponent: f64) -> Self { 39 | Self { exponent, ..self } 40 | } 41 | } 42 | 43 | impl NoiseFn for Exponent 44 | where 45 | Source: NoiseFn, 46 | { 47 | fn get(&self, point: [T; DIM]) -> f64 { 48 | let mut value = self.source.get(point); 49 | value = (value + 1.0) / 2.0; 50 | value = value.abs(); 51 | value = value.powf(self.exponent); 52 | scale_shift(value, 2.0) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/noise_fns/modifiers/negate.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that negates the output value from the source function. 5 | #[derive(Clone, Debug)] 6 | pub struct Negate 7 | where 8 | Source: NoiseFn, 9 | { 10 | /// Outputs a value. 11 | pub source: Source, 12 | 13 | phantom: PhantomData, 14 | } 15 | 16 | impl Negate 17 | where 18 | Source: NoiseFn, 19 | { 20 | pub fn new(source: Source) -> Self { 21 | Negate { 22 | source, 23 | phantom: PhantomData, 24 | } 25 | } 26 | } 27 | 28 | impl NoiseFn for Negate 29 | where 30 | Source: NoiseFn, 31 | { 32 | fn get(&self, point: [T; DIM]) -> f64 { 33 | -self.source.get(point) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/noise_fns/modifiers/scale_bias.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that applies a scaling factor and a bias to the output value 5 | /// from the source function. 6 | /// 7 | /// The function retrieves the output value from the source function, multiplies 8 | /// it with the scaling factor, adds the bias to it, then outputs the value. 9 | #[derive(Clone, Debug)] 10 | pub struct ScaleBias { 11 | /// Outputs a value. 12 | pub source: Source, 13 | 14 | /// Scaling factor to apply to the output value from the source function. 15 | /// The default value is 1.0. 16 | pub scale: f64, 17 | 18 | /// Bias to apply to the scaled output value from the source function. 19 | /// The default value is 0.0. 20 | pub bias: f64, 21 | 22 | phantom: PhantomData, 23 | } 24 | 25 | impl ScaleBias 26 | where 27 | Source: NoiseFn, 28 | { 29 | pub fn new(source: Source) -> Self { 30 | Self { 31 | source, 32 | scale: 1.0, 33 | bias: 0.0, 34 | phantom: PhantomData, 35 | } 36 | } 37 | 38 | pub fn set_scale(self, scale: f64) -> Self { 39 | Self { scale, ..self } 40 | } 41 | 42 | pub fn set_bias(self, bias: f64) -> Self { 43 | Self { bias, ..self } 44 | } 45 | } 46 | 47 | impl NoiseFn for ScaleBias 48 | where 49 | Source: NoiseFn, 50 | { 51 | #[cfg(not(target_os = "emscripten"))] 52 | fn get(&self, point: [T; DIM]) -> f64 { 53 | (self.source.get(point)).mul_add(self.scale, self.bias) 54 | } 55 | 56 | #[cfg(target_os = "emscripten")] 57 | fn get(&self, point: [T; DIM]) -> f64 { 58 | (self.source.get(point) * self.scale) + self.bias 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/noise_fns/selectors.rs: -------------------------------------------------------------------------------- 1 | pub use self::{blend::*, select::*}; 2 | 3 | mod blend; 4 | mod select; 5 | -------------------------------------------------------------------------------- /src/noise_fns/selectors/blend.rs: -------------------------------------------------------------------------------- 1 | use crate::{math::interpolate, noise_fns::NoiseFn}; 2 | use core::marker::PhantomData; 3 | 4 | /// Noise function that outputs a weighted blend of the output values from two 5 | /// source functions given the output value supplied by a control function. 6 | /// 7 | /// This noise function uses linear interpolation to perform the blending 8 | /// operation. 9 | #[derive(Clone, Debug)] 10 | pub struct Blend 11 | where 12 | Source1: NoiseFn, 13 | Source2: NoiseFn, 14 | Control: NoiseFn, 15 | { 16 | /// Outputs one of the values to blend. 17 | pub source1: Source1, 18 | 19 | /// Outputs one of the values to blend. 20 | pub source2: Source2, 21 | 22 | /// Determines the weight of the blending operation. Negative values weight 23 | /// the blend towards the output value from the `source1` function. Positive 24 | /// values weight the blend towards the output value from the `source2` 25 | /// function. 26 | pub control: Control, 27 | 28 | phantom: PhantomData, 29 | } 30 | 31 | impl Blend 32 | where 33 | Source1: NoiseFn, 34 | Source2: NoiseFn, 35 | Control: NoiseFn, 36 | { 37 | pub fn new(source1: Source1, source2: Source2, control: Control) -> Self { 38 | Blend { 39 | source1, 40 | source2, 41 | control, 42 | phantom: PhantomData, 43 | } 44 | } 45 | } 46 | 47 | impl NoiseFn 48 | for Blend 49 | where 50 | T: Copy, 51 | Source1: NoiseFn, 52 | Source2: NoiseFn, 53 | Control: NoiseFn, 54 | { 55 | fn get(&self, point: [T; DIM]) -> f64 { 56 | let lower = self.source1.get(point); 57 | let upper = self.source2.get(point); 58 | let control = self.control.get(point); 59 | 60 | interpolate::linear(lower, upper, control) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/noise_fns/selectors/select.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | math::{interpolate, s_curve::cubic::Cubic}, 3 | noise_fns::NoiseFn, 4 | }; 5 | use core::marker::PhantomData; 6 | 7 | /// Noise function that outputs the value selected from one of two source 8 | /// functions chosen by the output value from a control function. 9 | #[derive(Clone, Debug)] 10 | pub struct Select 11 | where 12 | Source1: NoiseFn, 13 | Source2: NoiseFn, 14 | Control: NoiseFn, 15 | { 16 | /// Outputs a value. 17 | pub source1: Source1, 18 | 19 | /// Outputs a value. 20 | pub source2: Source2, 21 | 22 | /// Determines the value to select. If the output value from 23 | /// the control function is within a range of values know as the _selection 24 | /// range_, this noise function outputs the value from `source2`. 25 | /// Otherwise, this noise function outputs the value from `source1`. 26 | pub control: Control, 27 | 28 | /// Bounds of the selection range. Default is 0.0 to 1.0. 29 | pub bounds: (f64, f64), 30 | 31 | /// Edge falloff value. Default is 0.0. 32 | pub falloff: f64, 33 | 34 | phantom: PhantomData, 35 | } 36 | 37 | impl Select 38 | where 39 | Source1: NoiseFn, 40 | Source2: NoiseFn, 41 | Control: NoiseFn, 42 | { 43 | pub fn new(source1: Source1, source2: Source2, control: Control) -> Self { 44 | Select { 45 | source1, 46 | source2, 47 | control, 48 | bounds: (0.0, 1.0), 49 | falloff: 0.0, 50 | phantom: PhantomData, 51 | } 52 | } 53 | 54 | pub fn set_bounds(self, lower_bound: f64, upper_bound: f64) -> Self { 55 | Select { 56 | bounds: (lower_bound, upper_bound), 57 | ..self 58 | } 59 | } 60 | 61 | pub fn set_falloff(self, falloff: f64) -> Self { 62 | Select { falloff, ..self } 63 | } 64 | } 65 | 66 | impl NoiseFn 67 | for Select 68 | where 69 | T: Copy, 70 | Source1: NoiseFn, 71 | Source2: NoiseFn, 72 | Control: NoiseFn, 73 | { 74 | fn get(&self, point: [T; DIM]) -> f64 { 75 | let control_value = self.control.get(point); 76 | let (lower, upper) = self.bounds; 77 | 78 | if self.falloff > 0.0 { 79 | match () { 80 | _ if control_value < (lower - self.falloff) => self.source1.get(point), 81 | _ if control_value < (lower + self.falloff) => { 82 | let lower_curve = lower - self.falloff; 83 | let upper_curve = lower + self.falloff; 84 | let alpha = 85 | ((control_value - lower_curve) / (upper_curve - lower_curve)).map_cubic(); 86 | 87 | interpolate::linear(self.source1.get(point), self.source2.get(point), alpha) 88 | } 89 | _ if control_value < (upper - self.falloff) => self.source2.get(point), 90 | _ if control_value < (upper + self.falloff) => { 91 | let lower_curve = upper - self.falloff; 92 | let upper_curve = upper + self.falloff; 93 | let alpha = 94 | ((control_value - lower_curve) / (upper_curve - lower_curve)).map_cubic(); 95 | 96 | interpolate::linear(self.source2.get(point), self.source1.get(point), alpha) 97 | } 98 | _ => self.source1.get(point), 99 | } 100 | } else if control_value < lower || control_value > upper { 101 | self.source1.get(point) 102 | } else { 103 | self.source2.get(point) 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/noise_fns/transformers.rs: -------------------------------------------------------------------------------- 1 | pub use self::{displace::*, rotate_point::*, scale_point::*, translate_point::*, turbulence::*}; 2 | 3 | mod displace; 4 | mod rotate_point; 5 | mod scale_point; 6 | mod translate_point; 7 | mod turbulence; 8 | -------------------------------------------------------------------------------- /src/noise_fns/transformers/displace.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | 3 | /// Noise function that uses multiple source functions to displace each coordinate 4 | /// of the input value before returning the output value from the `source` function. 5 | #[derive(Clone)] 6 | pub struct Displace { 7 | /// Source function that outputs a value 8 | pub source: Source, 9 | 10 | /// Displacement function that displaces the _x_ coordinate of the input 11 | /// value. 12 | pub x_displace: XDisplace, 13 | 14 | /// Displacement function that displaces the _y_ coordinate of the input 15 | /// value. 16 | pub y_displace: YDisplace, 17 | 18 | /// Displacement function that displaces the _z_ coordinate of the input 19 | /// value. Only needed for 3d or higher noise. 20 | pub z_displace: ZDisplace, 21 | 22 | /// Displacement function that displaces the _u_ coordinate of the input 23 | /// value. Only needed for 4d or higher noise. 24 | pub u_displace: UDisplace, 25 | } 26 | 27 | impl 28 | Displace 29 | { 30 | pub fn new( 31 | source: Source, 32 | x_displace: XDisplace, 33 | y_displace: YDisplace, 34 | z_displace: ZDisplace, 35 | u_displace: UDisplace, 36 | ) -> Self { 37 | Self { 38 | source, 39 | x_displace, 40 | y_displace, 41 | z_displace, 42 | u_displace, 43 | } 44 | } 45 | } 46 | 47 | impl NoiseFn 48 | for Displace 49 | where 50 | Source: NoiseFn, 51 | XDisplace: NoiseFn, 52 | YDisplace: NoiseFn, 53 | { 54 | fn get(&self, point: [f64; 2]) -> f64 { 55 | // Get the output values from the displacement functions and add them to 56 | // the corresponding coordinate in the input value. Since this is a 2d 57 | // function, we only need the x_displace and y_displace functions. 58 | let x = point[0] + self.x_displace.get(point); 59 | let y = point[1] + self.y_displace.get(point); 60 | 61 | // get the output value using the offset input value instead of the 62 | // original input value. 63 | self.source.get([x, y]) 64 | } 65 | } 66 | 67 | impl NoiseFn 68 | for Displace 69 | where 70 | Source: NoiseFn, 71 | XDisplace: NoiseFn, 72 | YDisplace: NoiseFn, 73 | ZDisplace: NoiseFn, 74 | { 75 | fn get(&self, point: [f64; 3]) -> f64 { 76 | // Get the output values from the displacement functions and add them to 77 | // the corresponding coordinate in the input value. Since this is a 3d 78 | // function, we only need the x_displace, y_displace, and z_displace 79 | // functions. Also, panic if there is no z_displace function defined. 80 | let x = point[0] + self.x_displace.get(point); 81 | let y = point[1] + self.y_displace.get(point); 82 | let z = point[2] + self.z_displace.get(point); 83 | 84 | // get the output value using the offset input value instead of the 85 | // original input value. 86 | self.source.get([x, y, z]) 87 | } 88 | } 89 | 90 | impl NoiseFn 91 | for Displace 92 | where 93 | Source: NoiseFn, 94 | XDisplace: NoiseFn, 95 | YDisplace: NoiseFn, 96 | ZDisplace: NoiseFn, 97 | UDisplace: NoiseFn, 98 | { 99 | fn get(&self, point: [f64; 4]) -> f64 { 100 | // Get the output values from the displacement functions and add them to 101 | // the corresponding coordinate in the input value. Since this is a 4d 102 | // function, we need all of the displace functions. Panic if there is no z- 103 | // or u-displace function defined. 104 | let x = point[0] + self.x_displace.get(point); 105 | let y = point[1] + self.y_displace.get(point); 106 | let z = point[2] + self.z_displace.get(point); 107 | let u = point[3] + self.u_displace.get(point); 108 | 109 | // get the output value using the offset input value instead of the 110 | // original input value. 111 | self.source.get([x, y, z, u]) 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/noise_fns/transformers/rotate_point.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | 3 | /// Noise function that rotates the input value around the origin before 4 | /// returning the output value from the source function. 5 | /// 6 | /// The get() method rotates the coordinates of the input value around the 7 | /// origin before returning the output value from the source function. 8 | /// 9 | /// The coordinate system of the input value is assumed to be "right-handed" 10 | /// (_x_ increases to the right, _y_ increases upward, and _z_ increases inward). 11 | #[derive(Clone)] 12 | pub struct RotatePoint { 13 | /// Source function that outputs a value 14 | pub source: Source, 15 | 16 | /// _x_ rotation angle applied to the input value, in degrees. The 17 | /// default angle is set to 0.0 degrees. 18 | pub x_angle: f64, 19 | 20 | /// _y_ rotation angle applied to the input value, in degrees. The 21 | /// default angle is set to 0.0 degrees. 22 | pub y_angle: f64, 23 | 24 | /// _z_ rotation angle applied to the input value, in degrees. The 25 | /// default angle is set to 0.0 degrees. 26 | pub z_angle: f64, 27 | 28 | /// _u_ rotation angle applied to the input value, in degrees. The 29 | /// default angle is set to 0.0 degrees. 30 | pub u_angle: f64, 31 | } 32 | 33 | impl RotatePoint { 34 | pub fn new(source: Source) -> Self { 35 | Self { 36 | source, 37 | x_angle: 0.0, 38 | y_angle: 0.0, 39 | z_angle: 0.0, 40 | u_angle: 0.0, 41 | } 42 | } 43 | 44 | /// Sets the rotation angle around the _x_ axis to apply to the input 45 | /// value. 46 | pub fn set_x_angle(self, x_angle: f64) -> Self { 47 | Self { x_angle, ..self } 48 | } 49 | 50 | /// Sets the rotation angle around the _y_ axis to apply to the input 51 | /// value. 52 | pub fn set_y_angle(self, y_angle: f64) -> Self { 53 | Self { y_angle, ..self } 54 | } 55 | 56 | /// Sets the rotation angle around the _z_ axis to apply to the input 57 | /// value. 58 | pub fn set_z_angle(self, z_angle: f64) -> Self { 59 | Self { z_angle, ..self } 60 | } 61 | 62 | /// Sets the rotation angle around the _u_ axis to apply to the input 63 | /// value. 64 | pub fn set_u_angle(self, u_angle: f64) -> Self { 65 | Self { u_angle, ..self } 66 | } 67 | 68 | /// Sets the rotation angles around all of the axes to apply to the input 69 | /// value. 70 | pub fn set_angles(self, x_angle: f64, y_angle: f64, z_angle: f64, u_angle: f64) -> Self { 71 | Self { 72 | x_angle, 73 | y_angle, 74 | z_angle, 75 | u_angle, 76 | ..self 77 | } 78 | } 79 | } 80 | 81 | impl NoiseFn for RotatePoint 82 | where 83 | Source: NoiseFn, 84 | { 85 | fn get(&self, point: [f64; 2]) -> f64 { 86 | // In two dimensions, the plane is _xy_, and we rotate around the 87 | // z-axis. 88 | let x = point[0]; 89 | let y = point[1]; 90 | let theta = self.z_angle.to_radians(); 91 | 92 | let x2 = x * theta.cos() - y * theta.sin(); 93 | let y2 = x * theta.sin() + y * theta.cos(); 94 | 95 | // get the output value using the offset input value instead of the 96 | // original input value. 97 | self.source.get([x2, y2]) 98 | } 99 | } 100 | 101 | impl NoiseFn for RotatePoint 102 | where 103 | Source: NoiseFn, 104 | { 105 | fn get(&self, point: [f64; 3]) -> f64 { 106 | // In three dimensions, we could rotate around any of the x, y, or z 107 | // axes. Need a more complicated function to handle this case. 108 | let x_cos = self.x_angle.to_radians().cos(); 109 | let y_cos = self.y_angle.to_radians().cos(); 110 | let z_cos = self.z_angle.to_radians().cos(); 111 | let x_sin = self.x_angle.to_radians().sin(); 112 | let y_sin = self.y_angle.to_radians().sin(); 113 | let z_sin = self.z_angle.to_radians().sin(); 114 | 115 | let x1 = x_sin * y_sin * z_sin + y_cos * z_cos; 116 | let y1 = x_cos * z_sin; 117 | let z1 = y_sin * z_cos - y_cos * x_sin * z_sin; 118 | let x2 = y_sin * x_sin * z_cos - y_cos * z_sin; 119 | let y2 = x_cos * z_cos; 120 | let z2 = -y_cos * x_sin * z_cos - y_sin * z_sin; 121 | let x3 = -y_sin * x_cos; 122 | let y3 = x_sin; 123 | let z3 = y_cos * x_cos; 124 | 125 | let x = (x1 * point[0]) + (y1 * point[1]) + (z1 * point[2]); 126 | let y = (x2 * point[0]) + (y2 * point[1]) + (z2 * point[2]); 127 | let z = (x3 * point[0]) + (y3 * point[1]) + (z3 * point[2]); 128 | 129 | // get the output value using the offset input value instead of the 130 | // original input value. 131 | self.source.get([x, y, z]) 132 | } 133 | } 134 | 135 | impl NoiseFn for RotatePoint 136 | where 137 | Source: NoiseFn, 138 | { 139 | fn get(&self, _point: [f64; 4]) -> f64 { 140 | // 4d rotations are hard. 141 | unimplemented!(); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/noise_fns/transformers/scale_point.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | 3 | /// Noise function that scales the coordinates of the input value before 4 | /// returning the output value from the source function. 5 | /// 6 | /// The get() method multiplies the coordinates of the input value with a 7 | /// scaling factor before returning the output value from the source function. 8 | #[derive(Clone)] 9 | pub struct ScalePoint { 10 | /// Source function that outputs a value 11 | pub source: Source, 12 | 13 | /// Scaling factor applied to the _x_ coordinate of the input value. The 14 | /// default scaling factor is set to 1.0. 15 | pub x_scale: f64, 16 | 17 | /// Scaling factor applied to the _y_ coordinate of the input value. The 18 | /// default scaling factor is set to 1.0. 19 | pub y_scale: f64, 20 | 21 | /// Scaling factor applied to the _z_ coordinate of the input value. The 22 | /// default scaling factor is set to 1.0. 23 | pub z_scale: f64, 24 | 25 | /// Scaling factor applied to the _u_ coordinate of the input value. The 26 | /// default scaling factor is set to 1.0. 27 | pub u_scale: f64, 28 | } 29 | 30 | impl ScalePoint { 31 | pub fn new(source: Source) -> Self { 32 | Self { 33 | source, 34 | x_scale: 1.0, 35 | y_scale: 1.0, 36 | z_scale: 1.0, 37 | u_scale: 1.0, 38 | } 39 | } 40 | 41 | /// Sets the scaling factor to apply to the _x_ coordinate of the input 42 | /// value. 43 | pub fn set_x_scale(self, x_scale: f64) -> Self { 44 | Self { x_scale, ..self } 45 | } 46 | 47 | /// Sets the scaling factor to apply to the _x_ coordinate of the input 48 | /// value. 49 | pub fn set_y_scale(self, y_scale: f64) -> Self { 50 | Self { y_scale, ..self } 51 | } 52 | 53 | /// Sets the scaling factor to apply to the _x_ coordinate of the input 54 | /// value. 55 | pub fn set_z_scale(self, z_scale: f64) -> Self { 56 | Self { z_scale, ..self } 57 | } 58 | 59 | /// Sets the scaling factor to apply to the _x_ coordinate of the input 60 | /// value. 61 | pub fn set_u_scale(self, u_scale: f64) -> Self { 62 | Self { u_scale, ..self } 63 | } 64 | 65 | /// Sets the scaling factor to apply to all coordinates of the input value. 66 | pub fn set_scale(self, scale: f64) -> Self { 67 | Self { 68 | x_scale: scale, 69 | y_scale: scale, 70 | z_scale: scale, 71 | u_scale: scale, 72 | ..self 73 | } 74 | } 75 | 76 | /// Sets the individual scaling factors to apply to each coordinate of the 77 | /// input value. 78 | pub fn set_all_scales(self, x_scale: f64, y_scale: f64, z_scale: f64, u_scale: f64) -> Self { 79 | Self { 80 | x_scale, 81 | y_scale, 82 | z_scale, 83 | u_scale, 84 | ..self 85 | } 86 | } 87 | } 88 | 89 | impl NoiseFn for ScalePoint 90 | where 91 | Source: NoiseFn, 92 | { 93 | fn get(&self, point: [f64; 2]) -> f64 { 94 | self.source 95 | .get([point[0] * self.x_scale, point[1] * self.y_scale]) 96 | } 97 | } 98 | 99 | impl NoiseFn for ScalePoint 100 | where 101 | Source: NoiseFn, 102 | { 103 | fn get(&self, point: [f64; 3]) -> f64 { 104 | self.source.get([ 105 | point[0] * self.x_scale, 106 | point[1] * self.y_scale, 107 | point[2] * self.z_scale, 108 | ]) 109 | } 110 | } 111 | 112 | impl NoiseFn for ScalePoint 113 | where 114 | Source: NoiseFn, 115 | { 116 | fn get(&self, point: [f64; 4]) -> f64 { 117 | self.source.get([ 118 | point[0] * self.x_scale, 119 | point[1] * self.y_scale, 120 | point[2] * self.z_scale, 121 | point[3] * self.u_scale, 122 | ]) 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/noise_fns/transformers/translate_point.rs: -------------------------------------------------------------------------------- 1 | use crate::noise_fns::NoiseFn; 2 | 3 | /// Noise function that moves the coordinates of the input value before 4 | /// returning the output value from the source function. 5 | /// 6 | /// The get() method moves the coordinates of the input value by a translation 7 | /// amount before returning the output value from the source function. 8 | #[derive(Clone)] 9 | pub struct TranslatePoint { 10 | /// Source function that outputs a value 11 | pub source: Source, 12 | 13 | /// Translation amount applied to the _x_ coordinate of the input value. 14 | /// The default translation amount is set to 0.0. 15 | pub x_translation: f64, 16 | 17 | /// Translation amount applied to the _y_ coordinate of the input value. 18 | /// The default translation amount is set to 0.0. 19 | pub y_translation: f64, 20 | 21 | /// Translation amount applied to the _z_ coordinate of the input value. 22 | /// The default translation amount is set to 0.0. 23 | pub z_translation: f64, 24 | 25 | /// Translation amount applied to the _u_ coordinate of the input value. 26 | /// The default translation amount is set to 0.0. 27 | pub u_translation: f64, 28 | } 29 | 30 | impl TranslatePoint { 31 | pub fn new(source: Source) -> Self { 32 | Self { 33 | source, 34 | x_translation: 0.0, 35 | y_translation: 0.0, 36 | z_translation: 0.0, 37 | u_translation: 0.0, 38 | } 39 | } 40 | 41 | /// Sets the scaling factor to apply to the _x_ coordinate of the input 42 | /// value. 43 | pub fn set_x_translation(self, x_translation: f64) -> Self { 44 | Self { 45 | x_translation, 46 | ..self 47 | } 48 | } 49 | 50 | /// Sets the scaling factor to apply to the _y_ coordinate of the input 51 | /// value. 52 | pub fn set_y_translation(self, y_translation: f64) -> Self { 53 | Self { 54 | y_translation, 55 | ..self 56 | } 57 | } 58 | 59 | /// Sets the scaling factor to apply to the _z_ coordinate of the input 60 | /// value. 61 | pub fn set_z_translation(self, z_translation: f64) -> Self { 62 | Self { 63 | z_translation, 64 | ..self 65 | } 66 | } 67 | 68 | /// Sets the scaling factor to apply to the _u_ coordinate of the input 69 | /// value. 70 | pub fn set_u_translation(self, u_translation: f64) -> Self { 71 | Self { 72 | u_translation, 73 | ..self 74 | } 75 | } 76 | 77 | /// Sets the translation amount to apply to all coordinates of the input value. 78 | pub fn set_translation(self, scale: f64) -> Self { 79 | Self { 80 | x_translation: scale, 81 | y_translation: scale, 82 | z_translation: scale, 83 | u_translation: scale, 84 | ..self 85 | } 86 | } 87 | 88 | /// Sets the individual translation amounts to apply to each coordinate of 89 | /// the input value. 90 | pub fn set_all_translations( 91 | self, 92 | x_translation: f64, 93 | y_translation: f64, 94 | z_translation: f64, 95 | u_translation: f64, 96 | ) -> Self { 97 | Self { 98 | x_translation, 99 | y_translation, 100 | z_translation, 101 | u_translation, 102 | ..self 103 | } 104 | } 105 | } 106 | 107 | impl NoiseFn for TranslatePoint 108 | where 109 | Source: NoiseFn, 110 | { 111 | fn get(&self, point: [f64; 2]) -> f64 { 112 | self.source 113 | .get([point[0] + self.x_translation, point[1] + self.y_translation]) 114 | } 115 | } 116 | 117 | impl NoiseFn for TranslatePoint 118 | where 119 | Source: NoiseFn, 120 | { 121 | fn get(&self, point: [f64; 3]) -> f64 { 122 | self.source.get([ 123 | point[0] + self.x_translation, 124 | point[1] + self.y_translation, 125 | point[2] + self.z_translation, 126 | ]) 127 | } 128 | } 129 | 130 | impl NoiseFn for TranslatePoint 131 | where 132 | Source: NoiseFn, 133 | { 134 | fn get(&self, point: [f64; 4]) -> f64 { 135 | self.source.get([ 136 | point[0] + self.x_translation, 137 | point[1] + self.y_translation, 138 | point[2] + self.z_translation, 139 | point[3] + self.u_translation, 140 | ]) 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/permutationtable.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | use rand::{ 3 | distr::{Distribution, StandardUniform}, 4 | seq::SliceRandom, 5 | Rng, SeedableRng, 6 | }; 7 | use rand_xorshift::XorShiftRng; 8 | 9 | const TABLE_SIZE: usize = 256; 10 | 11 | pub trait NoiseHasher: Send + Sync { 12 | fn hash(&self, to_hash: &[isize]) -> usize; 13 | } 14 | 15 | /// A seed table, required by all noise functions. 16 | /// 17 | /// Table creation is expensive, so in most circumstances you'll only want to 18 | /// create one of these per generator. 19 | #[derive(Copy, Clone)] 20 | pub struct PermutationTable { 21 | values: [u8; TABLE_SIZE], 22 | } 23 | 24 | impl Distribution for StandardUniform { 25 | /// Generates a PermutationTable using a random seed. 26 | fn sample(&self, rng: &mut R) -> PermutationTable { 27 | let mut perm_table = PermutationTable { 28 | values: core::array::from_fn(|x| x as u8), 29 | }; 30 | perm_table.values.shuffle(rng); 31 | 32 | perm_table 33 | } 34 | } 35 | 36 | impl PermutationTable { 37 | /// Deterministically generates a new permutation table based on a `u32` seed value. 38 | /// 39 | /// Internally this uses a `XorShiftRng`, but we don't really need to worry 40 | /// about cryptographic security when working with procedural noise. 41 | pub fn new(seed: u32) -> Self { 42 | let mut real = [0; 16]; 43 | real[0] = 1; 44 | for i in 1..4 { 45 | real[i * 4] = seed as u8; 46 | real[(i * 4) + 1] = (seed >> 8) as u8; 47 | real[(i * 4) + 2] = (seed >> 16) as u8; 48 | real[(i * 4) + 3] = (seed >> 24) as u8; 49 | } 50 | let mut rng: XorShiftRng = SeedableRng::from_seed(real); 51 | rng.random() 52 | } 53 | } 54 | 55 | impl NoiseHasher for PermutationTable { 56 | fn hash(&self, to_hash: &[isize]) -> usize { 57 | let index = to_hash 58 | .iter() 59 | .map(|&a| (a & 0xff) as usize) 60 | .reduce(|a, b| self.values[a] as usize ^ b) 61 | .unwrap(); 62 | self.values[index] as usize 63 | } 64 | } 65 | 66 | impl fmt::Debug for PermutationTable { 67 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 68 | write!(f, "PermutationTable {{ .. }}") 69 | } 70 | } 71 | 72 | #[cfg(test)] 73 | mod tests { 74 | use crate::{NoiseFn, Perlin, Seedable}; 75 | use rand::random; 76 | 77 | #[test] 78 | fn test_random_seed() { 79 | let perlin = Perlin::default().set_seed(random()); 80 | let _ = perlin.get([1.0, 2.0, 3.0]); 81 | } 82 | 83 | #[test] 84 | fn test_negative_params() { 85 | let perlin = Perlin::default(); 86 | let _ = perlin.get([-1.0, 2.0, 3.0]); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "image")] 2 | pub use self::image_renderer::*; 3 | pub use self::{color_gradient::*, noise_image::*, noise_map::*, noise_map_builder::*}; 4 | 5 | mod color_gradient; 6 | #[cfg(feature = "image")] 7 | mod image_renderer; 8 | mod noise_image; 9 | mod noise_map; 10 | mod noise_map_builder; 11 | -------------------------------------------------------------------------------- /src/utils/noise_map_builder.rs: -------------------------------------------------------------------------------- 1 | use crate::{noise_fns::NoiseFn, utils::noise_map::NoiseMap}; 2 | 3 | pub struct NoiseFnWrapper 4 | where 5 | SourceFn: Fn([f64; DIM]) -> f64, 6 | { 7 | source_fn: SourceFn, 8 | } 9 | 10 | impl NoiseFn for NoiseFnWrapper 11 | where 12 | F: Fn([f64; DIM]) -> f64, 13 | { 14 | fn get(&self, point: [f64; DIM]) -> f64 { 15 | (self.source_fn)(point) 16 | } 17 | } 18 | 19 | pub trait NoiseMapBuilder { 20 | fn set_size(self, width: usize, height: usize) -> Self; 21 | 22 | fn set_source_module(self, source_module: SourceModule) -> Self; 23 | 24 | fn size(&self) -> (usize, usize); 25 | 26 | fn build(&self) -> NoiseMap; 27 | } 28 | 29 | mod cylinder_map; 30 | mod plane_map; 31 | mod sphere_map; 32 | 33 | pub use cylinder_map::*; 34 | pub use plane_map::*; 35 | pub use sphere_map::*; 36 | -------------------------------------------------------------------------------- /src/utils/noise_map_builder/cylinder_map.rs: -------------------------------------------------------------------------------- 1 | use crate::{utils::NoiseMap, NoiseFn}; 2 | 3 | use super::NoiseMapBuilder; 4 | 5 | pub struct CylinderMapBuilder 6 | where 7 | SourceModule: NoiseFn, 8 | { 9 | angle_bounds: (f64, f64), 10 | height_bounds: (f64, f64), 11 | size: (usize, usize), 12 | source_module: SourceModule, 13 | } 14 | 15 | impl CylinderMapBuilder 16 | where 17 | SourceModule: NoiseFn, 18 | { 19 | pub fn new(source_module: SourceModule) -> Self { 20 | CylinderMapBuilder { 21 | angle_bounds: (-90.0, 90.0), 22 | height_bounds: (-1.0, 1.0), 23 | size: (100, 100), 24 | source_module, 25 | } 26 | } 27 | 28 | pub fn set_angle_bounds(self, lower_bound: f64, upper_bound: f64) -> Self { 29 | let angle_bounds = if lower_bound >= upper_bound { 30 | (upper_bound, lower_bound) 31 | } else { 32 | (lower_bound, upper_bound) 33 | }; 34 | 35 | CylinderMapBuilder { 36 | angle_bounds, 37 | ..self 38 | } 39 | } 40 | 41 | pub fn set_height_bounds(self, lower_bound: f64, upper_bound: f64) -> Self { 42 | let height_bounds = if lower_bound >= upper_bound { 43 | (upper_bound, lower_bound) 44 | } else { 45 | (lower_bound, upper_bound) 46 | }; 47 | 48 | CylinderMapBuilder { 49 | height_bounds, 50 | ..self 51 | } 52 | } 53 | 54 | pub fn angle_bounds(&self) -> (f64, f64) { 55 | self.angle_bounds 56 | } 57 | 58 | pub fn height_bounds(&self) -> (f64, f64) { 59 | self.height_bounds 60 | } 61 | } 62 | 63 | impl NoiseMapBuilder for CylinderMapBuilder 64 | where 65 | SourceModule: NoiseFn, 66 | { 67 | fn set_size(self, width: usize, height: usize) -> Self { 68 | CylinderMapBuilder { 69 | size: (width, height), 70 | ..self 71 | } 72 | } 73 | 74 | fn set_source_module(self, source_module: SourceModule) -> Self { 75 | CylinderMapBuilder { 76 | source_module, 77 | ..self 78 | } 79 | } 80 | 81 | fn size(&self) -> (usize, usize) { 82 | self.size 83 | } 84 | 85 | fn build(&self) -> NoiseMap { 86 | let mut result_map = NoiseMap::new(self.size.0, self.size.1); 87 | 88 | let (width, height) = self.size; 89 | 90 | let angle_extent = self.angle_bounds.1 - self.angle_bounds.0; 91 | let height_extent = self.height_bounds.1 - self.height_bounds.0; 92 | 93 | let x_step = angle_extent / width as f64; 94 | let y_step = height_extent / height as f64; 95 | 96 | for y in 0..height { 97 | let current_height = self.height_bounds.0 + y_step * y as f64; 98 | 99 | for x in 0..width { 100 | let current_angle = self.angle_bounds.0 + x_step * x as f64; 101 | 102 | let point_x = current_angle.to_radians().cos(); 103 | let point_z = current_angle.to_radians().sin(); 104 | 105 | let value = self.source_module.get([point_x, current_height, point_z]); 106 | 107 | result_map[(x, y)] = value; 108 | } 109 | } 110 | 111 | result_map 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/utils/noise_map_builder/sphere_map.rs: -------------------------------------------------------------------------------- 1 | use crate::{utils::NoiseMap, NoiseFn}; 2 | 3 | use super::NoiseMapBuilder; 4 | 5 | pub struct SphereMapBuilder 6 | where 7 | SourceModule: NoiseFn, 8 | { 9 | latitude_bounds: (f64, f64), 10 | longitude_bounds: (f64, f64), 11 | size: (usize, usize), 12 | source_module: SourceModule, 13 | } 14 | 15 | impl SphereMapBuilder 16 | where 17 | SourceModule: NoiseFn, 18 | { 19 | pub fn new(source_module: SourceModule) -> Self { 20 | SphereMapBuilder { 21 | latitude_bounds: (-1.0, 1.0), 22 | longitude_bounds: (-1.0, 1.0), 23 | size: (100, 100), 24 | source_module, 25 | } 26 | } 27 | 28 | pub fn set_latitude_bounds(self, min_lat_bound: f64, max_lat_bound: f64) -> Self { 29 | SphereMapBuilder { 30 | latitude_bounds: (min_lat_bound, max_lat_bound), 31 | ..self 32 | } 33 | } 34 | 35 | pub fn set_longitude_bounds(self, min_lon_bound: f64, max_lon_bound: f64) -> Self { 36 | SphereMapBuilder { 37 | longitude_bounds: (min_lon_bound, max_lon_bound), 38 | ..self 39 | } 40 | } 41 | 42 | pub fn set_bounds( 43 | self, 44 | min_lat_bound: f64, 45 | max_lat_bound: f64, 46 | min_lon_bound: f64, 47 | max_lon_bound: f64, 48 | ) -> Self { 49 | SphereMapBuilder { 50 | latitude_bounds: (min_lat_bound, max_lat_bound), 51 | longitude_bounds: (min_lon_bound, max_lon_bound), 52 | ..self 53 | } 54 | } 55 | 56 | pub fn latitude_bounds(&self) -> (f64, f64) { 57 | self.latitude_bounds 58 | } 59 | 60 | pub fn longitude_bounds(&self) -> (f64, f64) { 61 | self.longitude_bounds 62 | } 63 | } 64 | 65 | impl NoiseMapBuilder for SphereMapBuilder 66 | where 67 | SourceModule: NoiseFn, 68 | { 69 | fn set_size(self, width: usize, height: usize) -> Self { 70 | SphereMapBuilder { 71 | size: (width, height), 72 | ..self 73 | } 74 | } 75 | 76 | fn set_source_module(self, source_module: SourceModule) -> Self { 77 | SphereMapBuilder { 78 | source_module, 79 | ..self 80 | } 81 | } 82 | 83 | fn size(&self) -> (usize, usize) { 84 | self.size 85 | } 86 | 87 | fn build(&self) -> NoiseMap { 88 | let (width, height) = self.size; 89 | 90 | let mut result_map = NoiseMap::new(width, height); 91 | 92 | let lon_extent = self.longitude_bounds.1 - self.longitude_bounds.0; 93 | let lat_extent = self.latitude_bounds.1 - self.latitude_bounds.0; 94 | 95 | let x_step = lon_extent / width as f64; 96 | let y_step = lat_extent / height as f64; 97 | 98 | for y in 0..height { 99 | let current_lat = self.latitude_bounds.0 + y_step * y as f64; 100 | 101 | for x in 0..width { 102 | let current_lon = self.longitude_bounds.0 + x_step * x as f64; 103 | 104 | let point = lat_lon_to_xyz(current_lat, current_lon); 105 | 106 | result_map[(x, y)] = self.source_module.get(point); 107 | } 108 | } 109 | 110 | result_map 111 | } 112 | } 113 | 114 | fn lat_lon_to_xyz(lat: f64, lon: f64) -> [f64; 3] { 115 | let r = lat.to_radians().cos(); 116 | let x = r * lon.to_radians().cos(); 117 | let y = lat.to_radians().sin(); 118 | let z = r * lon.to_radians().sin(); 119 | 120 | [x, y, z] 121 | } 122 | --------------------------------------------------------------------------------