├── .cargo
└── config.toml
├── .github
└── workflows
│ ├── format.yaml
│ ├── lint.yaml
│ └── test.yaml
├── .gitignore
├── Cargo.toml
├── LICENSE.md
├── README.md
├── benches
├── billow.rs
├── checkerboard.rs
├── fbm.rs
├── improved_perlin.rs
├── perlin.rs
├── ridgedmulti.rs
├── simplex.rs
├── value.rs
└── worley.rs
├── examples
├── README.md
├── assets
│ ├── billow_simplex_1d.png
│ ├── billow_simplex_2d.png
│ ├── billow_simplex_3d.png
│ ├── billow_simplex_4d.gif
│ ├── chaining.png
│ ├── checkerboard_1d.png
│ ├── checkerboard_2d.png
│ ├── checkerboard_3d.png
│ ├── checkerboard_4d.gif
│ ├── custom_1d.png
│ ├── custom_2d.png
│ ├── custom_3d.png
│ ├── custom_4d.gif
│ ├── fbm_simplex_1d.png
│ ├── fbm_simplex_2d.png
│ ├── fbm_simplex_3d.png
│ ├── fbm_simplex_4d.gif
│ ├── improved_perlin_1d.png
│ ├── improved_perlin_2d.png
│ ├── improved_perlin_3d.png
│ ├── improved_perlin_4d.gif
│ ├── perlin_1d.png
│ ├── perlin_2d.png
│ ├── perlin_3d.png
│ ├── perlin_4d.gif
│ ├── ridgedmulti_simplex_1d.png
│ ├── ridgedmulti_simplex_2d.png
│ ├── ridgedmulti_simplex_3d.png
│ ├── ridgedmulti_simplex_4d.gif
│ ├── simplex_1d.png
│ ├── simplex_2d.png
│ ├── simplex_3d.png
│ ├── simplex_4d.gif
│ ├── value_1d.png
│ ├── value_2d.png
│ ├── value_3d.png
│ ├── value_4d.gif
│ ├── worley_1d.png
│ ├── worley_2d.png
│ ├── worley_3d.png
│ └── worley_4d.gif
├── billow.rs
├── chaining.rs
├── checkerboard.rs
├── custom.rs
├── fbm.rs
├── improved_perlin.rs
├── perlin.rs
├── ridgedmulti.rs
├── simplex.rs
├── value.rs
└── worley.rs
├── images
├── doc_image_000_f7049b4.png
└── doc_image_001_f7049b4.gif
├── src
├── core
│ ├── adapters
│ │ ├── abs.rs
│ │ ├── add.rs
│ │ ├── billow.rs
│ │ ├── blend.rs
│ │ ├── clamp.rs
│ │ ├── displace.rs
│ │ ├── exp.rs
│ │ ├── fbm.rs
│ │ ├── lambda.rs
│ │ ├── max.rs
│ │ ├── min.rs
│ │ ├── mod.rs
│ │ ├── mul.rs
│ │ ├── neg.rs
│ │ ├── pow.rs
│ │ ├── power.rs
│ │ ├── product.rs
│ │ ├── ridgedmulti.rs
│ │ ├── rotate.rs
│ │ ├── scale.rs
│ │ ├── select.rs
│ │ ├── spline.rs
│ │ ├── sum.rs
│ │ └── translate.rs
│ ├── devtools
│ │ ├── benchtools.rs
│ │ └── mod.rs
│ ├── generator.rs
│ ├── mod.rs
│ ├── source.rs
│ ├── sources
│ │ ├── checkerboard.rs
│ │ ├── constant.rs
│ │ ├── custom.rs
│ │ ├── functional
│ │ │ ├── checkerboard.rs
│ │ │ ├── constants.rs
│ │ │ ├── improved_perlin.rs
│ │ │ ├── mod.rs
│ │ │ ├── perlin.rs
│ │ │ ├── simplex.rs
│ │ │ ├── value.rs
│ │ │ └── worley.rs
│ │ ├── improved_perlin.rs
│ │ ├── mod.rs
│ │ ├── perlin.rs
│ │ ├── simplex.rs
│ │ ├── value.rs
│ │ └── worley.rs
│ └── utils
│ │ ├── math
│ │ ├── mod.rs
│ │ └── vector.rs
│ │ ├── mod.rs
│ │ ├── noisebuf.rs
│ │ ├── ptable.rs
│ │ └── visualizer.rs
├── lib.rs
└── prelude.rs
└── tests
├── test_adapters.rs
├── test_other.rs
├── test_sources.rs
└── test_utils.rs
/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | rustflags = ["-C", "target-cpu=native", "-C", "opt-level=3"]
3 |
--------------------------------------------------------------------------------
/.github/workflows/format.yaml:
--------------------------------------------------------------------------------
1 | name: format
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | push:
8 | branches:
9 | - master
10 |
11 | env:
12 | CARGO_TERM_COLOR: always
13 |
14 | jobs:
15 | format:
16 | name: format
17 | runs-on: ubuntu-latest
18 | steps:
19 | - name: checkout repository
20 | uses: actions/checkout@v3
21 | - name: install toolchain
22 | uses: actions-rs/toolchain@v1
23 | with:
24 | profile: minimal
25 | toolchain: stable
26 | components: rustfmt
27 | override: true
28 | - name: run rustfmt
29 | uses: actions-rs/cargo@v1
30 | with:
31 | command: fmt
32 | args: --all -- --check
33 |
--------------------------------------------------------------------------------
/.github/workflows/lint.yaml:
--------------------------------------------------------------------------------
1 | name: lint
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | push:
8 | branches:
9 | - master
10 |
11 | env:
12 | CARGO_TERM_COLOR: always
13 |
14 | jobs:
15 | clippy:
16 | name: clippy
17 | runs-on: ubuntu-latest
18 | permissions:
19 | checks: write
20 | steps:
21 | - name: checkout repository
22 | uses: actions/checkout@v3
23 | - name: install toolchain
24 | uses: actions-rs/toolchain@v1
25 | with:
26 | profile: minimal
27 | toolchain: stable
28 | components: clippy
29 | override: true
30 | - name: run clippy
31 | uses: actions-rs/clippy-check@v1
32 | with:
33 | token: ${{ secrets.GITHUB_TOKEN }}
34 | args: --all-features
35 | name: clippy output
36 |
--------------------------------------------------------------------------------
/.github/workflows/test.yaml:
--------------------------------------------------------------------------------
1 | name: test
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | push:
8 | branches:
9 | - master
10 |
11 | env:
12 | CARGO_TERM_COLOR: always
13 |
14 | jobs:
15 | test:
16 | name: test
17 | runs-on: ubuntu-latest
18 | env:
19 | COVERALLS_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
20 | steps:
21 | - name: checkout repository
22 | uses: actions/checkout@v3
23 |
24 | - name: install system dependencies
25 | run: sudo apt-get update && sudo apt-get install -y libfontconfig1-dev
26 |
27 | - name: cache
28 | uses: actions/cache@v3
29 | with:
30 | path: |
31 | ~/.cargo/registry
32 | ~/.cargo/git
33 | target
34 | target_cov
35 | key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }}
36 |
37 | - name: install toolchain
38 | uses: actions-rs/toolchain@v1
39 | with:
40 | profile: minimal
41 | toolchain: stable
42 | override: true
43 |
44 | - name: install binstall
45 | run: curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
46 |
47 | - name: bininstall tarpaulin
48 | uses: actions-rs/cargo@v1
49 | with:
50 | command: binstall
51 | args: cargo-tarpaulin --no-confirm
52 |
53 | - name: try tarpaulin with coveralls
54 | if: ${{ env.COVERALLS_TOKEN != '' }}
55 | uses: actions-rs/cargo@v1
56 | with:
57 | command: tarpaulin
58 | args: --coveralls ${{ secrets.COVERALLS_TOKEN }} --target-dir target_cov --engine llvm --skip-clean
59 |
60 | - name: try tarpaulin without coveralls
61 | if: ${{ env.COVERALLS_TOKEN == '' }}
62 | uses: actions-rs/cargo@v1
63 | with:
64 | command: tarpaulin
65 | args: --target-dir target_cov --engine llvm --skip-clean
66 |
67 | - name: run doctests
68 | uses: actions-rs/cargo@v1
69 | with:
70 | command: test
71 | args: --doc
72 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | .vscode/
3 |
4 | Cargo.lock
5 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "libnoise"
3 | version = "1.2.0"
4 | authors = ["Contributors to the libnoise-rs Repository"]
5 | edition = "2024"
6 | license = "MIT"
7 | readme = "README.md"
8 | documentation = "https://docs.rs/libnoise"
9 | repository = "https://github.com/cookiephone/libnoise-rs"
10 | homepage = "https://github.com/cookiephone/libnoise-rs"
11 | description = "A simple, performant, and customizable procedural noise generation library."
12 | keywords = ["noise", "procedural", "perlin", "simplex", "worley"]
13 | categories = ["algorithms", "mathematics", "game-development", "graphics"]
14 |
15 | [package.metadata.docs.rs]
16 | all-features = true
17 |
18 | [features]
19 | dev-tools = ["dep:criterion"]
20 | image = ["dep:image"]
21 |
22 | [dependencies]
23 | num-traits = "0.2.16"
24 | rand_chacha = { version = "0.3.1" }
25 | rand = { version = "0.8.5", features = [], default-features = false }
26 | itertools = "0.10.5"
27 | image = { version = "0.24.6", features = ["gif"], optional = true }
28 | criterion = { version = "0.5.1", optional = true }
29 |
30 | [dev-dependencies]
31 | libnoise = { path = ".", features = ["dev-tools", "image"] }
32 | criterion = "0.5.1"
33 | plotters = "0.3.5"
34 | itertools = "0.10.5"
35 | proptest = "1.2.0"
36 | tempdir = "0.3.7"
37 |
38 | [profile.dev]
39 | opt-level = 1
40 |
41 | [profile.bench]
42 | opt-level = 3
43 | lto = true
44 | codegen-units = 1
45 | strip = true
46 |
47 | [profile.release]
48 | opt-level = 3
49 | lto = true
50 | codegen-units = 1
51 | strip = true
52 |
53 | [profile.release-with-debug]
54 | inherits = "release"
55 | debug = true
56 | strip = false
57 |
58 | [[test]]
59 | name = "test_sources"
60 |
61 | [[test]]
62 | name = "test_other"
63 |
64 | [[test]]
65 | name = "test_adapters"
66 |
67 | [[test]]
68 | name = "test_utils"
69 |
70 | [[bench]]
71 | name = "billow"
72 | harness = false
73 |
74 | [[bench]]
75 | name = "checkerboard"
76 | harness = false
77 |
78 | [[bench]]
79 | name = "fbm"
80 | harness = false
81 |
82 | [[bench]]
83 | name = "improved_perlin"
84 | harness = false
85 |
86 | [[bench]]
87 | name = "perlin"
88 | harness = false
89 |
90 | [[bench]]
91 | name = "ridgedmulti"
92 | harness = false
93 |
94 | [[bench]]
95 | name = "simplex"
96 | harness = false
97 |
98 | [[bench]]
99 | name = "value"
100 | harness = false
101 |
102 | [[bench]]
103 | name = "worley"
104 | harness = false
105 |
106 | [[example]]
107 | name = "billow"
108 |
109 | [[example]]
110 | name = "chaining"
111 |
112 | [[example]]
113 | name = "checkerboard"
114 |
115 | [[example]]
116 | name = "custom"
117 |
118 | [[example]]
119 | name = "fbm"
120 |
121 | [[example]]
122 | name = "improved_perlin"
123 |
124 | [[example]]
125 | name = "perlin"
126 |
127 | [[example]]
128 | name = "ridgedmulti"
129 |
130 | [[example]]
131 | name = "simplex"
132 |
133 | [[example]]
134 | name = "value"
135 |
136 | [[example]]
137 | name = "worley"
138 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 SpoogieOogie
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # libnoise
2 |
3 | 
4 | 
5 | 
6 | [](https://coveralls.io/github/cookiephone/libnoise-rs?branch=master)
7 | [](https://docs.rs/libnoise)
8 | [](https://crates.io/crates/libnoise)
9 |
10 | A simple, performant, and customizable procedural noise generation library
11 | inspired by [libnoise for C++](https://libnoise.sourceforge.net/) featuring:
12 |
13 | - Easy coherent noise generation through sources provided via `Source`
14 | - Modular generator creation by chaining adapters to modify and combine
15 | generator inputs and outputs, and the ability to flexibly create
16 | custom generators and adapters, all through the `Generator` trait
17 | - Efficient and cache friendly sampling of generators through
18 | `NoiseBuffer` and much of the generator complexity resolving at
19 | compile time
20 | - Easy visualization of generator outputs for debugging through
21 | `Visualizer`
22 |
23 | Libnoise provides utilities to generate coherent noise and customize them
24 | by applying a variety of operations which modify and combine generators.
25 | With a focus on customizability, the library allows users to create custom
26 | generators and modifiers.
27 |
28 | Most immediately relevant [documentation](https://docs.rs/libnoise) can be found in
29 | [`Source`](https://docs.rs/libnoise/latest/libnoise/struct.Source.html) and
30 | [`Generator`](https://docs.rs/libnoise/latest/libnoise/trait.Generator.html) docs.
31 |
32 | ## Usage
33 |
34 | First, add the dependency to your project by editing your `Cargo.toml`:
35 | ```toml
36 | [dependencies]
37 | libnoise = "1.2"
38 | ```
39 |
40 | To get started easily, create a source generator using one of the many
41 | sources found in [`Source`](https://docs.rs/libnoise/latest/libnoise/struct.Source.html),
42 | and apply adapters documented in [`Generator`](https://docs.rs/libnoise/latest/libnoise/trait.Generator.html).
43 | For a more detailed introduction, see the [quickstart guide](https://docs.rs/libnoise/latest/libnoise/).
44 |
45 |
46 | ```rs
47 | use libnoise::prelude::*;
48 |
49 | // build a simplex noise generator seeded with 42
50 | let generator = Source::simplex(42);
51 |
52 | // sample the generator for input point [0.2, 0.5]
53 | let value = generator.sample([0.2, 0.5]);
54 | ```
55 |
56 | Note how the dimensionality, which is internally represented as a constant
57 | generic argument, is automatically inferred by sampling the generator with
58 | a 2-dimensional input point.
59 |
60 | Naturally, we can create more interesting complex generators:
61 |
62 | ```rs
63 | use libnoise::prelude::*;
64 |
65 | // build a generator
66 | let generator = Source::simplex(42) // start with simplex noise
67 | .fbm(5, 0.013, 2.0, 0.5) // apply fractal brownian motion
68 | .blend( // apply blending...
69 | Source::worley(43).scale([0.05, 0.05]), // ...with scaled worley noise
70 | Source::worley(44).scale([0.02, 0.02])) // ...controlled by other worley noise
71 | .lambda(|f| (f * 2.0).sin() * 0.3 + f * 0.7); // apply a closure to the noise
72 |
73 | // sample the generator for input point [0.2, 0.5]
74 | let value = generator.sample([0.2, 0.5]);
75 | ```
76 |
77 | We can also use [`NoiseBuffer`](https://docs.rs/libnoise/latest/libnoise/struct.NoiseBuffer.html) for efficiently filling n-dimensional arrays
78 | with noise, and [`Visualizer`](https://docs.rs/libnoise/latest/libnoise/struct.Visualizer.html) to get a visual representation of a given
79 | generator. The above generator produces the following image, when sampled for
80 | every pixel position:
81 |
82 | 
83 |
84 | It is common to interpret the 3rd or 4th dimension as time, allowing us to
85 | produce space-time noise such as:
86 |
87 | 
88 |
89 | ## Contributing
90 |
91 | Contributors and feature suggestions are welcome!
92 |
93 | Should you want to contact me directly, it is best via discord (username: oogie).
94 |
95 | ## License
96 |
97 | Libnoise is distributed under the terms of the MIT license.
98 |
99 | See [LICENSE-MIT](LICENSE.md) for details.
100 |
--------------------------------------------------------------------------------
/benches/billow.rs:
--------------------------------------------------------------------------------
1 | use criterion::{Criterion, PlottingBackend, criterion_group, criterion_main};
2 | use libnoise::prelude::*;
3 |
4 | const SCALE: f64 = 0.033;
5 | const SHAPE_1D: &[usize] = &[1000000];
6 | const SHAPE_2D: &[usize] = &[1000, 1000];
7 | const SHAPE_3D: &[usize] = &[100, 100, 100];
8 | const SHAPE_4D: &[usize] = &[30, 30, 30, 30];
9 |
10 | macro_rules! impl_generator {
11 | () => {
12 | Source::simplex(42).billow(3, 0.013, 2.0, 0.5)
13 | };
14 | }
15 |
16 | fn bench(c: &mut Criterion) {
17 | devtools::benchtools::bench_noise1d(c, "billow_1d", SHAPE_1D, SCALE, &impl_generator!());
18 | devtools::benchtools::bench_noise2d(c, "billow_2d", SHAPE_2D, SCALE, &impl_generator!());
19 | devtools::benchtools::bench_noise3d(c, "billow_3d", SHAPE_3D, SCALE, &impl_generator!());
20 | devtools::benchtools::bench_noise4d(c, "billow_4d", SHAPE_4D, SCALE, &impl_generator!());
21 | }
22 |
23 | criterion_group! {
24 | name = benches;
25 | config = Criterion::default()
26 | .plotting_backend(PlottingBackend::Plotters);
27 | targets = bench
28 | }
29 |
30 | criterion_main!(benches);
31 |
--------------------------------------------------------------------------------
/benches/checkerboard.rs:
--------------------------------------------------------------------------------
1 | use criterion::{Criterion, PlottingBackend, criterion_group, criterion_main};
2 | use libnoise::prelude::*;
3 |
4 | const SCALE: f64 = 0.033;
5 | const SHAPE_1D: &[usize] = &[1000000];
6 | const SHAPE_2D: &[usize] = &[1000, 1000];
7 | const SHAPE_3D: &[usize] = &[100, 100, 100];
8 | const SHAPE_4D: &[usize] = &[30, 30, 30, 30];
9 |
10 | macro_rules! impl_generator {
11 | () => {
12 | Source::checkerboard()
13 | };
14 | }
15 |
16 | fn bench(c: &mut Criterion) {
17 | devtools::benchtools::bench_noise1d(c, "checkerboard_1d", SHAPE_1D, SCALE, &impl_generator!());
18 | devtools::benchtools::bench_noise2d(c, "checkerboard_2d", SHAPE_2D, SCALE, &impl_generator!());
19 | devtools::benchtools::bench_noise3d(c, "checkerboard_3d", SHAPE_3D, SCALE, &impl_generator!());
20 | devtools::benchtools::bench_noise4d(c, "checkerboard_4d", SHAPE_4D, SCALE, &impl_generator!());
21 | }
22 |
23 | criterion_group! {
24 | name = benches;
25 | config = Criterion::default()
26 | .plotting_backend(PlottingBackend::Plotters);
27 | targets = bench
28 | }
29 |
30 | criterion_main!(benches);
31 |
--------------------------------------------------------------------------------
/benches/fbm.rs:
--------------------------------------------------------------------------------
1 | use criterion::{Criterion, PlottingBackend, criterion_group, criterion_main};
2 | use libnoise::prelude::*;
3 |
4 | const SCALE: f64 = 0.033;
5 | const SHAPE_1D: &[usize] = &[1000000];
6 | const SHAPE_2D: &[usize] = &[1000, 1000];
7 | const SHAPE_3D: &[usize] = &[100, 100, 100];
8 | const SHAPE_4D: &[usize] = &[30, 30, 30, 30];
9 |
10 | macro_rules! impl_generator {
11 | () => {
12 | Source::simplex(42).fbm(3, 0.013, 2.0, 0.5)
13 | };
14 | }
15 |
16 | fn bench(c: &mut Criterion) {
17 | devtools::benchtools::bench_noise1d(c, "fbm_1d", SHAPE_1D, SCALE, &impl_generator!());
18 | devtools::benchtools::bench_noise2d(c, "fbm_2d", SHAPE_2D, SCALE, &impl_generator!());
19 | devtools::benchtools::bench_noise3d(c, "fbm_3d", SHAPE_3D, SCALE, &impl_generator!());
20 | devtools::benchtools::bench_noise4d(c, "fbm_4d", SHAPE_4D, SCALE, &impl_generator!());
21 | }
22 |
23 | criterion_group! {
24 | name = benches;
25 | config = Criterion::default()
26 | .plotting_backend(PlottingBackend::Plotters);
27 | targets = bench
28 | }
29 |
30 | criterion_main!(benches);
31 |
--------------------------------------------------------------------------------
/benches/improved_perlin.rs:
--------------------------------------------------------------------------------
1 | use criterion::{Criterion, PlottingBackend, criterion_group, criterion_main};
2 | use libnoise::prelude::*;
3 |
4 | const SCALE: f64 = 0.033;
5 | const SHAPE_1D: &[usize] = &[1000000];
6 | const SHAPE_2D: &[usize] = &[1000, 1000];
7 | const SHAPE_3D: &[usize] = &[100, 100, 100];
8 | const SHAPE_4D: &[usize] = &[30, 30, 30, 30];
9 |
10 | macro_rules! impl_generator {
11 | () => {
12 | Source::improved_perlin(42)
13 | };
14 | }
15 |
16 | fn bench(c: &mut Criterion) {
17 | devtools::benchtools::bench_noise1d(
18 | c,
19 | "improved_perlin_1d",
20 | SHAPE_1D,
21 | SCALE,
22 | &impl_generator!(),
23 | );
24 | devtools::benchtools::bench_noise2d(
25 | c,
26 | "improved_perlin_2d",
27 | SHAPE_2D,
28 | SCALE,
29 | &impl_generator!(),
30 | );
31 | devtools::benchtools::bench_noise3d(
32 | c,
33 | "improved_perlin_3d",
34 | SHAPE_3D,
35 | SCALE,
36 | &impl_generator!(),
37 | );
38 | devtools::benchtools::bench_noise4d(
39 | c,
40 | "improved_perlin_4d",
41 | SHAPE_4D,
42 | SCALE,
43 | &impl_generator!(),
44 | );
45 | }
46 |
47 | criterion_group! {
48 | name = benches;
49 | config = Criterion::default()
50 | .plotting_backend(PlottingBackend::Plotters);
51 | targets = bench
52 | }
53 |
54 | criterion_main!(benches);
55 |
--------------------------------------------------------------------------------
/benches/perlin.rs:
--------------------------------------------------------------------------------
1 | use criterion::{Criterion, PlottingBackend, criterion_group, criterion_main};
2 | use libnoise::prelude::*;
3 |
4 | const SCALE: f64 = 0.033;
5 | const SHAPE_1D: &[usize] = &[1000000];
6 | const SHAPE_2D: &[usize] = &[1000, 1000];
7 | const SHAPE_3D: &[usize] = &[100, 100, 100];
8 | const SHAPE_4D: &[usize] = &[30, 30, 30, 30];
9 |
10 | macro_rules! impl_generator {
11 | () => {
12 | Source::perlin(42)
13 | };
14 | }
15 |
16 | fn bench(c: &mut Criterion) {
17 | devtools::benchtools::bench_noise1d(c, "perlin_1d", SHAPE_1D, SCALE, &impl_generator!());
18 | devtools::benchtools::bench_noise2d(c, "perlin_2d", SHAPE_2D, SCALE, &impl_generator!());
19 | devtools::benchtools::bench_noise3d(c, "perlin_3d", SHAPE_3D, SCALE, &impl_generator!());
20 | devtools::benchtools::bench_noise4d(c, "perlin_4d", SHAPE_4D, SCALE, &impl_generator!());
21 | }
22 |
23 | criterion_group! {
24 | name = benches;
25 | config = Criterion::default()
26 | .plotting_backend(PlottingBackend::Plotters);
27 | targets = bench
28 | }
29 |
30 | criterion_main!(benches);
31 |
--------------------------------------------------------------------------------
/benches/ridgedmulti.rs:
--------------------------------------------------------------------------------
1 | use criterion::{Criterion, PlottingBackend, criterion_group, criterion_main};
2 | use libnoise::prelude::*;
3 |
4 | const SCALE: f64 = 0.033;
5 | const SHAPE_1D: &[usize] = &[1000000];
6 | const SHAPE_2D: &[usize] = &[1000, 1000];
7 | const SHAPE_3D: &[usize] = &[100, 100, 100];
8 | const SHAPE_4D: &[usize] = &[30, 30, 30, 30];
9 |
10 | macro_rules! impl_generator {
11 | () => {
12 | Source::simplex(42).ridgedmulti(3, 0.013, 2.0, 2.0)
13 | };
14 | }
15 |
16 | fn bench(c: &mut Criterion) {
17 | devtools::benchtools::bench_noise1d(c, "ridgedmulti_1d", SHAPE_1D, SCALE, &impl_generator!());
18 | devtools::benchtools::bench_noise2d(c, "ridgedmulti_2d", SHAPE_2D, SCALE, &impl_generator!());
19 | devtools::benchtools::bench_noise3d(c, "ridgedmulti_3d", SHAPE_3D, SCALE, &impl_generator!());
20 | devtools::benchtools::bench_noise4d(c, "ridgedmulti_4d", SHAPE_4D, SCALE, &impl_generator!());
21 | }
22 |
23 | criterion_group! {
24 | name = benches;
25 | config = Criterion::default()
26 | .plotting_backend(PlottingBackend::Plotters);
27 | targets = bench
28 | }
29 |
30 | criterion_main!(benches);
31 |
--------------------------------------------------------------------------------
/benches/simplex.rs:
--------------------------------------------------------------------------------
1 | use criterion::{Criterion, PlottingBackend, criterion_group, criterion_main};
2 | use libnoise::prelude::*;
3 |
4 | const SCALE: f64 = 0.033;
5 | const SHAPE_1D: &[usize] = &[1000000];
6 | const SHAPE_2D: &[usize] = &[1000, 1000];
7 | const SHAPE_3D: &[usize] = &[100, 100, 100];
8 | const SHAPE_4D: &[usize] = &[30, 30, 30, 30];
9 |
10 | macro_rules! impl_generator {
11 | () => {
12 | Source::simplex(42)
13 | };
14 | }
15 |
16 | fn bench(c: &mut Criterion) {
17 | devtools::benchtools::bench_noise1d(c, "simplex_1d", SHAPE_1D, SCALE, &impl_generator!());
18 | devtools::benchtools::bench_noise2d(c, "simplex_2d", SHAPE_2D, SCALE, &impl_generator!());
19 | devtools::benchtools::bench_noise3d(c, "simplex_3d", SHAPE_3D, SCALE, &impl_generator!());
20 | devtools::benchtools::bench_noise4d(c, "simplex_4d", SHAPE_4D, SCALE, &impl_generator!());
21 | }
22 |
23 | criterion_group! {
24 | name = benches;
25 | config = Criterion::default()
26 | .plotting_backend(PlottingBackend::Plotters);
27 | targets = bench
28 | }
29 |
30 | criterion_main!(benches);
31 |
--------------------------------------------------------------------------------
/benches/value.rs:
--------------------------------------------------------------------------------
1 | use criterion::{Criterion, PlottingBackend, criterion_group, criterion_main};
2 | use libnoise::prelude::*;
3 |
4 | const SCALE: f64 = 0.033;
5 | const SHAPE_1D: &[usize] = &[1000000];
6 | const SHAPE_2D: &[usize] = &[1000, 1000];
7 | const SHAPE_3D: &[usize] = &[100, 100, 100];
8 | const SHAPE_4D: &[usize] = &[30, 30, 30, 30];
9 |
10 | macro_rules! impl_generator {
11 | () => {
12 | Source::value(42)
13 | };
14 | }
15 |
16 | fn bench(c: &mut Criterion) {
17 | devtools::benchtools::bench_noise1d(c, "value_1d", SHAPE_1D, SCALE, &impl_generator!());
18 | devtools::benchtools::bench_noise2d(c, "value_2d", SHAPE_2D, SCALE, &impl_generator!());
19 | devtools::benchtools::bench_noise3d(c, "value_3d", SHAPE_3D, SCALE, &impl_generator!());
20 | devtools::benchtools::bench_noise4d(c, "value_4d", SHAPE_4D, SCALE, &impl_generator!());
21 | }
22 |
23 | criterion_group! {
24 | name = benches;
25 | config = Criterion::default()
26 | .plotting_backend(PlottingBackend::Plotters);
27 | targets = bench
28 | }
29 |
30 | criterion_main!(benches);
31 |
--------------------------------------------------------------------------------
/benches/worley.rs:
--------------------------------------------------------------------------------
1 | use criterion::{Criterion, PlottingBackend, criterion_group, criterion_main};
2 | use libnoise::prelude::*;
3 |
4 | const SCALE: f64 = 0.033;
5 | const SHAPE_1D: &[usize] = &[1000000];
6 | const SHAPE_2D: &[usize] = &[1000, 1000];
7 | const SHAPE_3D: &[usize] = &[100, 100, 100];
8 | const SHAPE_4D: &[usize] = &[30, 30, 30, 30];
9 |
10 | macro_rules! impl_generator {
11 | () => {
12 | Source::worley(42)
13 | };
14 | }
15 |
16 | fn bench(c: &mut Criterion) {
17 | devtools::benchtools::bench_noise1d(c, "worley_1d", SHAPE_1D, SCALE, &impl_generator!());
18 | devtools::benchtools::bench_noise2d(c, "worley_2d", SHAPE_2D, SCALE, &impl_generator!());
19 | devtools::benchtools::bench_noise3d(c, "worley_3d", SHAPE_3D, SCALE, &impl_generator!());
20 | devtools::benchtools::bench_noise4d(c, "worley_4d", SHAPE_4D, SCALE, &impl_generator!());
21 | }
22 |
23 | criterion_group! {
24 | name = benches;
25 | config = Criterion::default()
26 | .plotting_backend(PlottingBackend::Plotters);
27 | targets = bench
28 | }
29 |
30 | criterion_main!(benches);
31 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 |
4 |
5 |
6 | Example |
7 | Measurement |
8 | Image |
9 |
10 |
11 |
12 |
13 |
14 | billow |
15 | 1D |
16 |  |
17 |
18 |
19 | 2D |
20 |  |
21 |
22 |
23 | 3D |
24 |  |
25 |
26 |
27 | 4D |
28 |  |
29 |
30 |
31 |
32 | chaining |
33 | 2D |
34 |  |
35 |
36 |
37 |
38 | checkerboard |
39 | 1D |
40 |  |
41 |
42 |
43 | 2D |
44 |  |
45 |
46 |
47 | 3D |
48 |  |
49 |
50 |
51 | 4D |
52 |  |
53 |
54 |
55 |
56 | custom |
57 | 1D |
58 |  |
59 |
60 |
61 | 2D |
62 |  |
63 |
64 |
65 | 3D |
66 |  |
67 |
68 |
69 | 4D |
70 |  |
71 |
72 |
73 |
74 | fbm |
75 | 1D |
76 |  |
77 |
78 |
79 | 2D |
80 |  |
81 |
82 |
83 | 3D |
84 |  |
85 |
86 |
87 | 4D |
88 |  |
89 |
90 |
91 |
92 | improved_perlin |
93 | 1D |
94 |  |
95 |
96 |
97 | 2D |
98 |  |
99 |
100 |
101 | 3D |
102 |  |
103 |
104 |
105 | 4D |
106 |  |
107 |
108 |
109 |
110 | perlin |
111 | 1D |
112 |  |
113 |
114 |
115 | 2D |
116 |  |
117 |
118 |
119 | 3D |
120 |  |
121 |
122 |
123 | 4D |
124 |  |
125 |
126 |
127 |
128 | ridgedmulti |
129 | 1D |
130 |  |
131 |
132 |
133 | 2D |
134 |  |
135 |
136 |
137 | 3D |
138 |  |
139 |
140 |
141 | 4D |
142 |  |
143 |
144 |
145 |
146 | simplex |
147 | 1D |
148 |  |
149 |
150 |
151 | 2D |
152 |  |
153 |
154 |
155 | 3D |
156 |  |
157 |
158 |
159 | 4D |
160 |  |
161 |
162 |
163 |
164 | value |
165 | 1D |
166 |  |
167 |
168 |
169 | 2D |
170 |  |
171 |
172 |
173 | 3D |
174 |  |
175 |
176 |
177 | 4D |
178 |  |
179 |
180 |
181 |
182 | worley |
183 | 1D |
184 |  |
185 |
186 |
187 | 2D |
188 |  |
189 |
190 |
191 | 3D |
192 |  |
193 |
194 |
195 | 4D |
196 |  |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/examples/assets/billow_simplex_1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/billow_simplex_1d.png
--------------------------------------------------------------------------------
/examples/assets/billow_simplex_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/billow_simplex_2d.png
--------------------------------------------------------------------------------
/examples/assets/billow_simplex_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/billow_simplex_3d.png
--------------------------------------------------------------------------------
/examples/assets/billow_simplex_4d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/billow_simplex_4d.gif
--------------------------------------------------------------------------------
/examples/assets/chaining.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/chaining.png
--------------------------------------------------------------------------------
/examples/assets/checkerboard_1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/checkerboard_1d.png
--------------------------------------------------------------------------------
/examples/assets/checkerboard_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/checkerboard_2d.png
--------------------------------------------------------------------------------
/examples/assets/checkerboard_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/checkerboard_3d.png
--------------------------------------------------------------------------------
/examples/assets/checkerboard_4d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/checkerboard_4d.gif
--------------------------------------------------------------------------------
/examples/assets/custom_1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/custom_1d.png
--------------------------------------------------------------------------------
/examples/assets/custom_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/custom_2d.png
--------------------------------------------------------------------------------
/examples/assets/custom_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/custom_3d.png
--------------------------------------------------------------------------------
/examples/assets/custom_4d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/custom_4d.gif
--------------------------------------------------------------------------------
/examples/assets/fbm_simplex_1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/fbm_simplex_1d.png
--------------------------------------------------------------------------------
/examples/assets/fbm_simplex_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/fbm_simplex_2d.png
--------------------------------------------------------------------------------
/examples/assets/fbm_simplex_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/fbm_simplex_3d.png
--------------------------------------------------------------------------------
/examples/assets/fbm_simplex_4d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/fbm_simplex_4d.gif
--------------------------------------------------------------------------------
/examples/assets/improved_perlin_1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/improved_perlin_1d.png
--------------------------------------------------------------------------------
/examples/assets/improved_perlin_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/improved_perlin_2d.png
--------------------------------------------------------------------------------
/examples/assets/improved_perlin_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/improved_perlin_3d.png
--------------------------------------------------------------------------------
/examples/assets/improved_perlin_4d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/improved_perlin_4d.gif
--------------------------------------------------------------------------------
/examples/assets/perlin_1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/perlin_1d.png
--------------------------------------------------------------------------------
/examples/assets/perlin_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/perlin_2d.png
--------------------------------------------------------------------------------
/examples/assets/perlin_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/perlin_3d.png
--------------------------------------------------------------------------------
/examples/assets/perlin_4d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/perlin_4d.gif
--------------------------------------------------------------------------------
/examples/assets/ridgedmulti_simplex_1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/ridgedmulti_simplex_1d.png
--------------------------------------------------------------------------------
/examples/assets/ridgedmulti_simplex_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/ridgedmulti_simplex_2d.png
--------------------------------------------------------------------------------
/examples/assets/ridgedmulti_simplex_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/ridgedmulti_simplex_3d.png
--------------------------------------------------------------------------------
/examples/assets/ridgedmulti_simplex_4d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/ridgedmulti_simplex_4d.gif
--------------------------------------------------------------------------------
/examples/assets/simplex_1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/simplex_1d.png
--------------------------------------------------------------------------------
/examples/assets/simplex_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/simplex_2d.png
--------------------------------------------------------------------------------
/examples/assets/simplex_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/simplex_3d.png
--------------------------------------------------------------------------------
/examples/assets/simplex_4d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/simplex_4d.gif
--------------------------------------------------------------------------------
/examples/assets/value_1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/value_1d.png
--------------------------------------------------------------------------------
/examples/assets/value_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/value_2d.png
--------------------------------------------------------------------------------
/examples/assets/value_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/value_3d.png
--------------------------------------------------------------------------------
/examples/assets/value_4d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/value_4d.gif
--------------------------------------------------------------------------------
/examples/assets/worley_1d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/worley_1d.png
--------------------------------------------------------------------------------
/examples/assets/worley_2d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/worley_2d.png
--------------------------------------------------------------------------------
/examples/assets/worley_3d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/worley_3d.png
--------------------------------------------------------------------------------
/examples/assets/worley_4d.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/examples/assets/worley_4d.gif
--------------------------------------------------------------------------------
/examples/billow.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_billow_simplex_noise1d();
5 | example_billow_simplex_noise2d();
6 | example_billow_simplex_noise3d();
7 | example_billow_simplex_noise4d();
8 | }
9 |
10 | fn example_billow_simplex_noise1d() {
11 | let generator = Source::simplex(42).billow(3, 0.013, 2.0, 0.5);
12 | Visualizer::<1>::new([100], &generator)
13 | .write_to_file("billow_simplex_1d.png")
14 | .unwrap();
15 | }
16 |
17 | fn example_billow_simplex_noise2d() {
18 | let generator = Source::simplex(42).billow(3, 0.013, 2.0, 0.5);
19 | Visualizer::<2>::new([1000, 1000], &generator)
20 | .write_to_file("billow_simplex_2d.png")
21 | .unwrap();
22 | }
23 |
24 | fn example_billow_simplex_noise3d() {
25 | let generator = Source::simplex(42).billow(3, 0.013, 2.0, 0.5);
26 | Visualizer::<3>::new([200, 200, 200], &generator)
27 | .write_to_file("billow_simplex_3d.png")
28 | .unwrap();
29 | }
30 |
31 | fn example_billow_simplex_noise4d() {
32 | let generator = Source::simplex(42).billow(3, 0.033, 2.0, 0.5);
33 | Visualizer::<4>::new([60, 60, 60, 60], &generator)
34 | .write_to_file("billow_simplex_4d.gif")
35 | .unwrap();
36 | }
37 |
--------------------------------------------------------------------------------
/examples/chaining.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_chaining();
5 | }
6 |
7 | fn example_chaining() {
8 | let generator = Source::<2>::simplex(42)
9 | .fbm(3, 0.013, 2.0, 0.5)
10 | .abs()
11 | .mul(2.0)
12 | .lambda(|x| 1.0 - x.exp() / 2.8)
13 | .displace_x(
14 | Source::worley(43)
15 | .scale([0.005, 0.005])
16 | .fbm(3, 1.0, 2.0, 0.5)
17 | .mul(5.0),
18 | )
19 | .rotate([0.5])
20 | .blend(
21 | Source::worley(45).scale([0.033, 0.033]),
22 | Source::perlin(45).scale([0.033, 0.033]).add(0.3),
23 | );
24 | Visualizer::<2>::new([1000, 1000], &generator)
25 | .write_to_file("chaining.png")
26 | .unwrap();
27 | }
28 |
--------------------------------------------------------------------------------
/examples/checkerboard.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_checkerboard_noise1d();
5 | example_checkerboard_noise2d();
6 | example_checkerboard_noise3d();
7 | example_checkerboard_noise4d();
8 | }
9 |
10 | fn example_checkerboard_noise1d() {
11 | let generator = Source::checkerboard().scale([0.013; 1]);
12 | Visualizer::<1>::new([100], &generator)
13 | .write_to_file("checkerboard_1d.png")
14 | .unwrap();
15 | }
16 |
17 | fn example_checkerboard_noise2d() {
18 | let generator = Source::checkerboard().scale([0.013; 2]);
19 | Visualizer::<2>::new([1000, 1000], &generator)
20 | .write_to_file("checkerboard_2d.png")
21 | .unwrap();
22 | }
23 |
24 | fn example_checkerboard_noise3d() {
25 | let generator = Source::checkerboard().scale([0.013; 3]);
26 | Visualizer::<3>::new([200, 200, 200], &generator)
27 | .write_to_file("checkerboard_3d.png")
28 | .unwrap();
29 | }
30 |
31 | fn example_checkerboard_noise4d() {
32 | let generator = Source::checkerboard().scale([0.033; 4]);
33 | Visualizer::<4>::new([60, 60, 60, 60], &generator)
34 | .write_to_file("checkerboard_4d.gif")
35 | .unwrap();
36 | }
37 |
--------------------------------------------------------------------------------
/examples/custom.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_custom_noise1d();
5 | example_custom_noise2d();
6 | example_custom_noise3d();
7 | example_custom_noise4d();
8 | }
9 |
10 | fn example_custom_noise1d() {
11 | let generator = Source::custom(|[x]| (-(x * x)).exp() * 2.0 - 1.0).scale([0.003; 1]);
12 | Visualizer::<1>::new([100], &generator)
13 | .write_to_file("custom_1d.png")
14 | .unwrap();
15 | }
16 |
17 | fn example_custom_noise2d() {
18 | let generator =
19 | Source::custom(|[x, y]| (-(x * x) - (y * y)).exp() * 2.0 - 1.0).scale([0.003; 2]);
20 | Visualizer::<2>::new([1000, 1000], &generator)
21 | .write_to_file("custom_2d.png")
22 | .unwrap();
23 | }
24 |
25 | fn example_custom_noise3d() {
26 | let generator = Source::custom(|[x, y, z]| (-(x * x) - (y * y) - (z * z)).exp() * 2.0 - 1.0)
27 | .scale([0.007; 3]);
28 | Visualizer::<3>::new([200, 200, 200], &generator)
29 | .write_to_file("custom_3d.png")
30 | .unwrap();
31 | }
32 |
33 | fn example_custom_noise4d() {
34 | let generator = Source::custom(|[x, y, z, w]| {
35 | (-(x * x) - (y * y) - (z * z) - (w * w) * 2.0 - 1.0).exp() * 2.0 - 1.0
36 | })
37 | .scale([0.021; 4]);
38 | Visualizer::<4>::new([60, 60, 60, 60], &generator)
39 | .write_to_file("custom_4d.gif")
40 | .unwrap();
41 | }
42 |
--------------------------------------------------------------------------------
/examples/fbm.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_fbm_simplex_noise1d();
5 | example_fbm_simplex_noise2d();
6 | example_fbm_simplex_noise3d();
7 | example_fbm_simplex_noise4d();
8 | }
9 |
10 | fn example_fbm_simplex_noise1d() {
11 | let generator = Source::simplex(42).fbm(3, 0.013, 2.0, 0.5);
12 | Visualizer::<1>::new([100], &generator)
13 | .write_to_file("fbm_simplex_1d.png")
14 | .unwrap();
15 | }
16 |
17 | fn example_fbm_simplex_noise2d() {
18 | let generator = Source::simplex(42).fbm(3, 0.013, 2.0, 0.5);
19 | Visualizer::<2>::new([1000, 1000], &generator)
20 | .write_to_file("fbm_simplex_2d.png")
21 | .unwrap();
22 | }
23 |
24 | fn example_fbm_simplex_noise3d() {
25 | let generator = Source::simplex(42).fbm(3, 0.013, 2.0, 0.5);
26 | Visualizer::<3>::new([200, 200, 200], &generator)
27 | .write_to_file("fbm_simplex_3d.png")
28 | .unwrap();
29 | }
30 |
31 | fn example_fbm_simplex_noise4d() {
32 | let generator = Source::simplex(42).fbm(3, 0.033, 2.0, 0.5);
33 | Visualizer::<4>::new([60, 60, 60, 60], &generator)
34 | .write_to_file("fbm_simplex_4d.gif")
35 | .unwrap();
36 | }
37 |
--------------------------------------------------------------------------------
/examples/improved_perlin.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_improved_perlin_noise1d();
5 | example_improved_perlin_noise2d();
6 | example_improved_perlin_noise3d();
7 | example_improved_perlin_noise4d();
8 | }
9 |
10 | fn example_improved_perlin_noise1d() {
11 | let generator = Source::improved_perlin(42).scale([0.013; 1]);
12 | Visualizer::<1>::new([100], &generator)
13 | .write_to_file("improved_perlin_1d.png")
14 | .unwrap();
15 | }
16 |
17 | fn example_improved_perlin_noise2d() {
18 | let generator = Source::improved_perlin(42).scale([0.013; 2]);
19 | Visualizer::<2>::new([1000, 1000], &generator)
20 | .write_to_file("improved_perlin_2d.png")
21 | .unwrap();
22 | }
23 |
24 | fn example_improved_perlin_noise3d() {
25 | let generator = Source::improved_perlin(42).scale([0.013; 3]);
26 | Visualizer::<3>::new([200, 200, 200], &generator)
27 | .write_to_file("improved_perlin_3d.png")
28 | .unwrap();
29 | }
30 |
31 | fn example_improved_perlin_noise4d() {
32 | let generator = Source::improved_perlin(42).scale([0.033; 4]);
33 | Visualizer::<4>::new([60, 60, 60, 60], &generator)
34 | .write_to_file("improved_perlin_4d.gif")
35 | .unwrap();
36 | }
37 |
--------------------------------------------------------------------------------
/examples/perlin.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_perlin_noise1d();
5 | example_perlin_noise2d();
6 | example_perlin_noise3d();
7 | example_perlin_noise4d();
8 | }
9 |
10 | fn example_perlin_noise1d() {
11 | let generator = Source::perlin(42).scale([0.013; 1]);
12 | Visualizer::<1>::new([100], &generator)
13 | .write_to_file("perlin_1d.png")
14 | .unwrap();
15 | }
16 |
17 | fn example_perlin_noise2d() {
18 | let generator = Source::perlin(42).scale([0.013; 2]);
19 | Visualizer::<2>::new([1000, 1000], &generator)
20 | .write_to_file("perlin_2d.png")
21 | .unwrap();
22 | }
23 |
24 | fn example_perlin_noise3d() {
25 | let generator = Source::perlin(42).scale([0.013; 3]);
26 | Visualizer::<3>::new([200, 200, 200], &generator)
27 | .write_to_file("perlin_3d.png")
28 | .unwrap();
29 | }
30 |
31 | fn example_perlin_noise4d() {
32 | let generator = Source::perlin(42).scale([0.033; 4]);
33 | Visualizer::<4>::new([60, 60, 60, 60], &generator)
34 | .write_to_file("perlin_4d.gif")
35 | .unwrap();
36 | }
37 |
--------------------------------------------------------------------------------
/examples/ridgedmulti.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_ridgedmulti_simplex_noise1d();
5 | example_ridgedmulti_simplex_noise2d();
6 | example_ridgedmulti_simplex_noise3d();
7 | example_ridgedmulti_simplex_noise4d();
8 | }
9 |
10 | fn example_ridgedmulti_simplex_noise1d() {
11 | let generator = Source::simplex(42).ridgedmulti(3, 0.013, 2.0, 2.0);
12 | Visualizer::<1>::new([100], &generator)
13 | .write_to_file("ridgedmulti_simplex_1d.png")
14 | .unwrap();
15 | }
16 |
17 | fn example_ridgedmulti_simplex_noise2d() {
18 | let generator = Source::simplex(42).ridgedmulti(3, 0.013, 2.0, 2.0);
19 | Visualizer::<2>::new([1000, 1000], &generator)
20 | .write_to_file("ridgedmulti_simplex_2d.png")
21 | .unwrap();
22 | }
23 |
24 | fn example_ridgedmulti_simplex_noise3d() {
25 | let generator = Source::simplex(42).ridgedmulti(3, 0.013, 2.0, 2.0);
26 | Visualizer::<3>::new([200, 200, 200], &generator)
27 | .write_to_file("ridgedmulti_simplex_3d.png")
28 | .unwrap();
29 | }
30 |
31 | fn example_ridgedmulti_simplex_noise4d() {
32 | let generator = Source::simplex(42).ridgedmulti(3, 0.033, 2.0, 2.0);
33 | Visualizer::<4>::new([60, 60, 60, 60], &generator)
34 | .write_to_file("ridgedmulti_simplex_4d.gif")
35 | .unwrap();
36 | }
37 |
--------------------------------------------------------------------------------
/examples/simplex.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_simplex_noise1d();
5 | example_simplex_noise2d();
6 | example_simplex_noise3d();
7 | example_simplex_noise4d();
8 | }
9 |
10 | fn example_simplex_noise1d() {
11 | let generator = Source::simplex(42).scale([0.013; 1]);
12 | Visualizer::<1>::new([100], &generator)
13 | .write_to_file("simplex_1d.png")
14 | .unwrap();
15 | }
16 |
17 | fn example_simplex_noise2d() {
18 | let generator = Source::simplex(42).scale([0.013; 2]);
19 | Visualizer::<2>::new([1000, 1000], &generator)
20 | .write_to_file("simplex_2d.png")
21 | .unwrap();
22 | }
23 |
24 | fn example_simplex_noise3d() {
25 | let generator = Source::simplex(42).scale([0.013; 3]);
26 | Visualizer::<3>::new([200, 200, 200], &generator)
27 | .write_to_file("simplex_3d.png")
28 | .unwrap();
29 | }
30 |
31 | fn example_simplex_noise4d() {
32 | let generator = Source::simplex(42).scale([0.033; 4]);
33 | Visualizer::<4>::new([60, 60, 60, 60], &generator)
34 | .write_to_file("simplex_4d.gif")
35 | .unwrap();
36 | }
37 |
--------------------------------------------------------------------------------
/examples/value.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_value_noise1d();
5 | example_value_noise2d();
6 | example_value_noise3d();
7 | example_value_noise4d();
8 | }
9 |
10 | fn example_value_noise1d() {
11 | let generator = Source::value(42).scale([0.013; 1]);
12 | Visualizer::<1>::new([100], &generator)
13 | .write_to_file("value_1d.png")
14 | .unwrap();
15 | }
16 |
17 | fn example_value_noise2d() {
18 | let generator = Source::value(42).scale([0.013; 2]);
19 | Visualizer::<2>::new([1000, 1000], &generator)
20 | .write_to_file("value_2d.png")
21 | .unwrap();
22 | }
23 |
24 | fn example_value_noise3d() {
25 | let generator = Source::value(42).scale([0.013; 3]);
26 | Visualizer::<3>::new([200, 200, 200], &generator)
27 | .write_to_file("value_3d.png")
28 | .unwrap();
29 | }
30 |
31 | fn example_value_noise4d() {
32 | let generator = Source::value(42).scale([0.033; 4]);
33 | Visualizer::<4>::new([60, 60, 60, 60], &generator)
34 | .write_to_file("value_4d.gif")
35 | .unwrap();
36 | }
37 |
--------------------------------------------------------------------------------
/examples/worley.rs:
--------------------------------------------------------------------------------
1 | use libnoise::prelude::*;
2 |
3 | fn main() {
4 | example_worley_noise1d();
5 | example_worley_noise2d();
6 | example_worley_noise3d();
7 | example_worley_noise4d();
8 | }
9 |
10 | fn example_worley_noise1d() {
11 | let generator = Source::worley(42).scale([0.013; 1]);
12 | Visualizer::<1>::new([100], &generator)
13 | .write_to_file("worley_1d.png")
14 | .unwrap();
15 | }
16 |
17 | fn example_worley_noise2d() {
18 | let generator = Source::worley(42).scale([0.013; 2]);
19 | Visualizer::<2>::new([1000, 1000], &generator)
20 | .write_to_file("worley_2d.png")
21 | .unwrap();
22 | }
23 |
24 | fn example_worley_noise3d() {
25 | let generator = Source::worley(42).scale([0.013; 3]);
26 | Visualizer::<3>::new([200, 200, 200], &generator)
27 | .write_to_file("worley_3d.png")
28 | .unwrap();
29 | }
30 |
31 | fn example_worley_noise4d() {
32 | let generator = Source::worley(42).scale([0.033; 4]);
33 | Visualizer::<4>::new([60, 60, 60, 60], &generator)
34 | .write_to_file("worley_4d.gif")
35 | .unwrap();
36 | }
37 |
--------------------------------------------------------------------------------
/images/doc_image_000_f7049b4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/images/doc_image_000_f7049b4.png
--------------------------------------------------------------------------------
/images/doc_image_001_f7049b4.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cookiephone/libnoise-rs/41ac16c660afaffa09466e87aab74a1dcec544d7/images/doc_image_001_f7049b4.gif
--------------------------------------------------------------------------------
/src/core/adapters/abs.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator returning the absolute value of the results of the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`abs()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`abs()`] implemented by [`Generator`], should be used
7 | /// to create [`Abs`].
8 | ///
9 | /// [`abs()`]: Generator::abs
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Abs {
12 | generator: G,
13 | }
14 |
15 | impl> Generator1D for Abs<1, G> {}
16 | impl> Generator2D for Abs<2, G> {}
17 | impl> Generator3D for Abs<3, G> {}
18 | impl> Generator4D for Abs<4, G> {}
19 |
20 | impl Abs
21 | where
22 | G: Generator,
23 | {
24 | #[inline]
25 | pub fn new(generator: G) -> Self {
26 | Self { generator }
27 | }
28 | }
29 |
30 | impl Generator for Abs
31 | where
32 | G: Generator,
33 | {
34 | #[inline]
35 | fn sample(&self, point: [f64; D]) -> f64 {
36 | self.generator.sample(point).abs()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/core/adapters/add.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator adding `offset` to results of the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`add()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`add()`] implemented by [`Generator`], should be used
7 | /// to create [`Add`].
8 | ///
9 | /// [`add()`]: Generator::add
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Add {
12 | generator: G,
13 | offset: f64,
14 | }
15 |
16 | impl> Generator1D for Add<1, G> {}
17 | impl> Generator2D for Add<2, G> {}
18 | impl> Generator3D for Add<3, G> {}
19 | impl> Generator4D for Add<4, G> {}
20 |
21 | impl Add
22 | where
23 | G: Generator,
24 | {
25 | #[inline]
26 | pub fn new(generator: G, offset: f64) -> Self {
27 | Self { generator, offset }
28 | }
29 | }
30 |
31 | impl Generator for Add
32 | where
33 | G: Generator,
34 | {
35 | #[inline]
36 | fn sample(&self, point: [f64; D]) -> f64 {
37 | self.generator.sample(point) + self.offset
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/core/adapters/billow.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// Create a generator applying an `fbm()`-like effect on the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`billow()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`billow()`] implemented by [`Generator`], should be used
7 | /// to create [`Billow`].
8 | ///
9 | /// [`billow()`]: Generator::billow
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Billow {
12 | generator: G,
13 | octaves: u32,
14 | frequency: f64,
15 | lacunarity: f64,
16 | persistence: f64,
17 | normalization_factor: f64,
18 | }
19 |
20 | impl> Generator1D for Billow<1, G> {}
21 | impl> Generator2D for Billow<2, G> {}
22 | impl> Generator3D for Billow<3, G> {}
23 | impl> Generator4D for Billow<4, G> {}
24 |
25 | impl Billow
26 | where
27 | G: Generator,
28 | {
29 | #[inline]
30 | pub fn new(
31 | generator: G,
32 | octaves: u32,
33 | frequency: f64,
34 | lacunarity: f64,
35 | persistence: f64,
36 | ) -> Self {
37 | let normalization_factor = compute_normalization_factor(octaves, persistence);
38 | Self {
39 | generator,
40 | octaves,
41 | frequency,
42 | lacunarity,
43 | persistence,
44 | normalization_factor,
45 | }
46 | }
47 | }
48 |
49 | macro_rules! impl_generator {
50 | ($dim:literal) => {
51 | impl> Generator<$dim> for Billow<$dim, G> {
52 | fn sample(&self, point: [f64; $dim]) -> f64 {
53 | let mut noise = 0.0;
54 | let mut amp = 1.0;
55 | let mut freq = self.frequency;
56 | for _ in 0..self.octaves {
57 | noise += amp
58 | * self
59 | .generator
60 | .sample(point.map(|x| x * freq))
61 | .abs()
62 | .mul_add(2.0, -1.0);
63 | freq *= self.lacunarity;
64 | amp *= self.persistence;
65 | }
66 | noise * self.normalization_factor
67 | }
68 | }
69 | };
70 | }
71 |
72 | impl_generator!(1);
73 | impl_generator!(2);
74 | impl_generator!(3);
75 | impl_generator!(4);
76 |
77 | #[inline]
78 | fn compute_normalization_factor(octaves: u32, persistence: f64) -> f64 {
79 | 1.0 / (0..octaves).fold(0.0, |acc, octave| acc + persistence.powi(octave as i32))
80 | }
81 |
--------------------------------------------------------------------------------
/src/core/adapters/blend.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator blending the underlying generator with a given other generator based on the
4 | /// value supplied by a control-generator.
5 | ///
6 | /// For details, see the documentation of [`blend()`]. Typically, this struct is not meant
7 | /// to be used directly. Instead, [`blend()`] implemented by [`Generator`], should be used
8 | /// to create [`Blend`].
9 | ///
10 | /// [`blend()`]: Generator::blend
11 | #[derive(Clone, Copy, Debug)]
12 | pub struct Blend {
13 | generator_a: GA,
14 | generator_b: GB,
15 | generator_control: GC,
16 | }
17 |
18 | impl, GB: Generator<1>, GC: Generator<1>> Generator1D for Blend<1, GA, GB, GC> {}
19 | impl, GB: Generator<2>, GC: Generator<2>> Generator2D for Blend<2, GA, GB, GC> {}
20 | impl, GB: Generator<3>, GC: Generator<3>> Generator3D for Blend<3, GA, GB, GC> {}
21 | impl, GB: Generator<4>, GC: Generator<4>> Generator4D for Blend<4, GA, GB, GC> {}
22 |
23 | impl Blend
24 | where
25 | GA: Generator,
26 | GB: Generator,
27 | GC: Generator,
28 | {
29 | #[inline]
30 | pub fn new(generator_a: GA, generator_b: GB, generator_control: GC) -> Self {
31 | Self {
32 | generator_a,
33 | generator_b,
34 | generator_control,
35 | }
36 | }
37 | }
38 |
39 | impl Generator for Blend
40 | where
41 | GA: Generator,
42 | GB: Generator,
43 | GC: Generator,
44 | {
45 | #[inline]
46 | fn sample(&self, point: [f64; D]) -> f64 {
47 | let a = self.generator_a.sample(point);
48 | let b = self.generator_b.sample(point);
49 | let t = self.generator_control.sample(point) * 0.5 + 0.5;
50 | a + t * (b - a)
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/core/adapters/clamp.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator clamping results of the underlying generator to a given interval.
4 | ///
5 | /// For details, see the documentation of [`clamp()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`clamp()`] implemented by [`Generator`], should be used
7 | /// to create [`Clamp`].
8 | ///
9 | /// [`clamp()`]: Generator::clamp
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Clamp {
12 | generator: G,
13 | min: f64,
14 | max: f64,
15 | }
16 |
17 | impl> Generator1D for Clamp<1, G> {}
18 | impl> Generator2D for Clamp<2, G> {}
19 | impl> Generator3D for Clamp<3, G> {}
20 | impl> Generator4D for Clamp<4, G> {}
21 |
22 | impl Clamp
23 | where
24 | G: Generator,
25 | {
26 | #[inline]
27 | pub fn new(generator: G, min: f64, max: f64) -> Self
28 | where
29 | G: Generator,
30 | {
31 | Self {
32 | generator,
33 | min,
34 | max,
35 | }
36 | }
37 | }
38 |
39 | impl Generator for Clamp
40 | where
41 | G: Generator,
42 | {
43 | #[inline]
44 | fn sample(&self, point: [f64; D]) -> f64 {
45 | self.generator.sample(point).clamp(self.min, self.max)
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/core/adapters/displace.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator producing the maximum of results of the underlying generator and results of
4 | /// a given other generator.
5 | ///
6 | /// For details, see the documentation of [`displace_x()`] and analogously for other axes.
7 | /// Typically, this struct is not meant to be used directly. Instead, [`displace_x()`]
8 | /// implemented by [`Generator`], should be used to create [`Displace`].
9 | ///
10 | /// [`displace_x()`]: Generator2D::displace_x
11 | #[derive(Clone, Copy, Debug)]
12 | pub struct Displace {
13 | generator: G,
14 | displacement_generator: GA,
15 | }
16 |
17 | impl, GA: Generator<1>> Generator1D for Displace<1, A, G, GA> {}
18 | impl, GA: Generator<2>> Generator2D for Displace<2, A, G, GA> {}
19 | impl, GA: Generator<3>> Generator3D for Displace<3, A, G, GA> {}
20 | impl, GA: Generator<4>> Generator4D for Displace<4, A, G, GA> {}
21 |
22 | impl Displace
23 | where
24 | G: Generator,
25 | GA: Generator,
26 | {
27 | #[inline]
28 | pub fn new(generator: G, displacement_generator: GA) -> Self {
29 | Self {
30 | generator,
31 | displacement_generator,
32 | }
33 | }
34 | }
35 |
36 | impl Generator for Displace
37 | where
38 | G: Generator,
39 | GA: Generator,
40 | {
41 | #[inline]
42 | fn sample(&self, mut point: [f64; D]) -> f64 {
43 | point[A] += self.displacement_generator.sample(point);
44 | self.generator.sample(point)
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/core/adapters/exp.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator applying the exponential function on results of the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`exp()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`exp()`] implemented by [`Generator`], should be used
7 | /// to create [`Exp`].
8 | ///
9 | /// [`exp()`]: Generator::exp
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Exp {
12 | generator: G,
13 | }
14 |
15 | impl> Generator1D for Exp<1, G> {}
16 | impl> Generator2D for Exp<2, G> {}
17 | impl> Generator3D for Exp<3, G> {}
18 | impl> Generator4D for Exp<4, G> {}
19 |
20 | impl Exp
21 | where
22 | G: Generator,
23 | {
24 | #[inline]
25 | pub fn new(generator: G) -> Self {
26 | Self { generator }
27 | }
28 | }
29 |
30 | impl Generator for Exp
31 | where
32 | G: Generator,
33 | {
34 | #[inline]
35 | fn sample(&self, point: [f64; D]) -> f64 {
36 | self.generator.sample(point).exp()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/core/adapters/fbm.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator applying fractal brownian motion on the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`fbm()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`fbm()`] implemented by [`Generator`], should be used
7 | /// to create [`Fbm`].
8 | ///
9 | /// [`fbm()`]: Generator::fbm
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Fbm {
12 | generator: G,
13 | octaves: u32,
14 | frequency: f64,
15 | lacunarity: f64,
16 | persistence: f64,
17 | normalization_factor: f64,
18 | }
19 |
20 | impl> Generator1D for Fbm<1, G> {}
21 | impl> Generator2D for Fbm<2, G> {}
22 | impl> Generator3D for Fbm<3, G> {}
23 | impl> Generator4D for Fbm<4, G> {}
24 |
25 | impl Fbm
26 | where
27 | G: Generator,
28 | {
29 | #[inline]
30 | pub fn new(
31 | generator: G,
32 | octaves: u32,
33 | frequency: f64,
34 | lacunarity: f64,
35 | persistence: f64,
36 | ) -> Self {
37 | let normalization_factor = compute_normalization_factor(octaves, persistence);
38 | Self {
39 | generator,
40 | octaves,
41 | frequency,
42 | lacunarity,
43 | persistence,
44 | normalization_factor,
45 | }
46 | }
47 | }
48 |
49 | macro_rules! impl_generator {
50 | ($dim:literal) => {
51 | impl> Generator<$dim> for Fbm<$dim, G> {
52 | fn sample(&self, point: [f64; $dim]) -> f64 {
53 | let mut noise = 0.0;
54 | let mut amp = 1.0;
55 | let mut freq = self.frequency;
56 | for _ in 0..self.octaves {
57 | noise += amp * self.generator.sample(point.map(|x| x * freq));
58 | freq *= self.lacunarity;
59 | amp *= self.persistence;
60 | }
61 | noise * self.normalization_factor
62 | }
63 | }
64 | };
65 | }
66 |
67 | impl_generator!(1);
68 | impl_generator!(2);
69 | impl_generator!(3);
70 | impl_generator!(4);
71 |
72 | #[inline]
73 | fn compute_normalization_factor(octaves: u32, persistence: f64) -> f64 {
74 | 1.0 / (0..octaves).fold(0.0, |acc, octave| acc + persistence.powi(octave as i32))
75 | }
76 |
--------------------------------------------------------------------------------
/src/core/adapters/lambda.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator applying the supplied closure to results of the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`lambda()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`lambda()`] implemented by [`Generator`], should be used
7 | /// to create [`Lambda`].
8 | ///
9 | /// [`lambda()`]: Generator::lambda
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Lambda {
12 | generator: G,
13 | lambda: L,
14 | }
15 |
16 | impl, L: Fn(f64) -> f64 + Copy> Generator1D for Lambda<1, G, L> {}
17 | impl, L: Fn(f64) -> f64 + Copy> Generator2D for Lambda<2, G, L> {}
18 | impl, L: Fn(f64) -> f64 + Copy> Generator3D for Lambda<3, G, L> {}
19 | impl, L: Fn(f64) -> f64 + Copy> Generator4D for Lambda<4, G, L> {}
20 |
21 | impl Lambda
22 | where
23 | G: Generator,
24 | L: Fn(f64) -> f64,
25 | {
26 | #[inline]
27 | pub fn new(generator: G, lambda: L) -> Self {
28 | Self { generator, lambda }
29 | }
30 | }
31 |
32 | impl Generator for Lambda
33 | where
34 | G: Generator,
35 | L: Copy + Fn(f64) -> f64,
36 | {
37 | #[inline]
38 | fn sample(&self, point: [f64; D]) -> f64 {
39 | (self.lambda)(self.generator.sample(point))
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/core/adapters/max.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator producing the maximum of results of the underlying generator and results of
4 | /// a given other generator.
5 | ///
6 | /// For details, see the documentation of [`max()`]. Typically, this struct is not meant
7 | /// to be used directly. Instead, [`max()`] implemented by [`Generator`], should be used
8 | /// to create [`Max`].
9 | ///
10 | /// [`max()`]: Generator::max
11 | #[derive(Clone, Copy, Debug)]
12 | pub struct Max {
13 | generator_a: GA,
14 | generator_b: GB,
15 | }
16 |
17 | impl, GB: Generator<1>> Generator1D for Max<1, GA, GB> {}
18 | impl, GB: Generator<2>> Generator2D for Max<2, GA, GB> {}
19 | impl, GB: Generator<3>> Generator3D for Max<3, GA, GB> {}
20 | impl, GB: Generator<4>> Generator4D for Max<4, GA, GB> {}
21 |
22 | impl Max
23 | where
24 | GA: Generator,
25 | GB: Generator,
26 | {
27 | #[inline]
28 | pub fn new(generator_a: GA, generator_b: GB) -> Self {
29 | Self {
30 | generator_a,
31 | generator_b,
32 | }
33 | }
34 | }
35 |
36 | impl Generator for Max
37 | where
38 | GA: Generator,
39 | GB: Generator,
40 | {
41 | #[inline]
42 | fn sample(&self, point: [f64; D]) -> f64 {
43 | self.generator_a
44 | .sample(point)
45 | .max(self.generator_b.sample(point))
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/core/adapters/min.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator producing the minimum of results of the underlying generator and results of
4 | /// a given other generator.
5 | ///
6 | /// For details, see the documentation of [`min()`]. Typically, this struct is not meant
7 | /// to be used directly. Instead, [`min()`] implemented by [`Generator`], should be used
8 | /// to create [`Min`].
9 | ///
10 | /// [`min()`]: Generator::min
11 | #[derive(Clone, Copy, Debug)]
12 | pub struct Min {
13 | generator_a: GA,
14 | generator_b: GB,
15 | }
16 |
17 | impl, GB: Generator<1>> Generator1D for Min<1, GA, GB> {}
18 | impl, GB: Generator<2>> Generator2D for Min<2, GA, GB> {}
19 | impl, GB: Generator<3>> Generator3D for Min<3, GA, GB> {}
20 | impl, GB: Generator<4>> Generator4D for Min<4, GA, GB> {}
21 |
22 | impl Min
23 | where
24 | GA: Generator,
25 | GB: Generator,
26 | {
27 | #[inline]
28 | pub fn new(generator_a: GA, generator_b: GB) -> Self {
29 | Self {
30 | generator_a,
31 | generator_b,
32 | }
33 | }
34 | }
35 |
36 | impl Generator for Min
37 | where
38 | GA: Generator,
39 | GB: Generator,
40 | {
41 | #[inline]
42 | fn sample(&self, point: [f64; D]) -> f64 {
43 | self.generator_a
44 | .sample(point)
45 | .min(self.generator_b.sample(point))
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/core/adapters/mod.rs:
--------------------------------------------------------------------------------
1 | mod abs;
2 | mod add;
3 | mod billow;
4 | mod blend;
5 | mod clamp;
6 | mod displace;
7 | mod exp;
8 | mod fbm;
9 | mod lambda;
10 | mod max;
11 | mod min;
12 | mod mul;
13 | mod neg;
14 | mod pow;
15 | mod power;
16 | mod product;
17 | mod ridgedmulti;
18 | mod rotate;
19 | mod scale;
20 | mod select;
21 | mod spline;
22 | mod sum;
23 | mod translate;
24 | pub use abs::Abs;
25 | pub use add::Add;
26 | pub use billow::Billow;
27 | pub use blend::Blend;
28 | pub use clamp::Clamp;
29 | pub use displace::Displace;
30 | pub use exp::Exp;
31 | pub use fbm::Fbm;
32 | pub use lambda::Lambda;
33 | pub use max::Max;
34 | pub use min::Min;
35 | pub use mul::Mul;
36 | pub use neg::Neg;
37 | pub use pow::Pow;
38 | pub use power::Power;
39 | pub use product::Product;
40 | pub use ridgedmulti::RidgedMulti;
41 | pub use rotate::Rotate;
42 | pub use scale::Scale;
43 | pub use select::Select;
44 | pub use sum::Sum;
45 | pub use translate::Translate;
46 | pub use {spline::NaturalCubicSpline, spline::Spline, spline::SplineImpl};
47 |
--------------------------------------------------------------------------------
/src/core/adapters/mul.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator multiplying `scale` to results of the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`mul()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`mul()`] implemented by [`Generator`], should be used
7 | /// to create [`Mul`].
8 | ///
9 | /// [`mul()`]: Generator::mul
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Mul {
12 | generator: G,
13 | scale: f64,
14 | }
15 |
16 | impl> Generator1D for Mul<1, G> {}
17 | impl> Generator2D for Mul<2, G> {}
18 | impl> Generator3D for Mul<3, G> {}
19 | impl> Generator4D for Mul<4, G> {}
20 |
21 | impl Mul
22 | where
23 | G: Generator,
24 | {
25 | #[inline]
26 | pub fn new(generator: G, scale: f64) -> Self {
27 | Self { generator, scale }
28 | }
29 | }
30 |
31 | impl Generator for Mul
32 | where
33 | G: Generator,
34 | {
35 | #[inline]
36 | fn sample(&self, point: [f64; D]) -> f64 {
37 | self.generator.sample(point) * self.scale
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/core/adapters/neg.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator which negates the results of the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`neg()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`neg()`] implemented by [`Generator`], should be used
7 | /// to create [`Neg`].
8 | ///
9 | /// [`neg()`]: Generator::neg
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Neg {
12 | generator: G,
13 | }
14 |
15 | impl> Generator1D for Neg<1, G> {}
16 | impl> Generator2D for Neg<2, G> {}
17 | impl> Generator3D for Neg<3, G> {}
18 | impl> Generator4D for Neg<4, G> {}
19 |
20 | impl Neg
21 | where
22 | G: Generator,
23 | {
24 | #[inline]
25 | pub fn new(generator: G) -> Self {
26 | Self { generator }
27 | }
28 | }
29 |
30 | impl Generator for Neg
31 | where
32 | G: Generator,
33 | {
34 | #[inline]
35 | fn sample(&self, point: [f64; D]) -> f64 {
36 | -self.generator.sample(point)
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/core/adapters/pow.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator raising results of the underlying generator to the power of `exponent`.
4 | ///
5 | /// For details, see the documentation of [`powi()`] and [`powf()`]. Typically, this
6 | /// struct is not meant to be used directly. Instead, [`powi()`] or [`powf()`]
7 | /// implemented by [`Generator`], should be used to create [`Pow`].
8 | ///
9 | /// [`powi()`]: Generator::powi
10 | /// [`powf()`]: Generator::powf
11 | #[derive(Clone, Copy, Debug)]
12 | pub struct Pow {
13 | generator: G,
14 | exponent: T,
15 | }
16 |
17 | impl> Generator1D for Pow<1, G, i32> {}
18 | impl> Generator2D for Pow<2, G, i32> {}
19 | impl> Generator3D for Pow<3, G, i32> {}
20 | impl> Generator4D for Pow<4, G, i32> {}
21 |
22 | impl> Generator1D for Pow<1, G, f64> {}
23 | impl> Generator2D for Pow<2, G, f64> {}
24 | impl> Generator3D for Pow<3, G, f64> {}
25 | impl> Generator4D for Pow<4, G, f64> {}
26 |
27 | impl Pow
28 | where
29 | G: Generator,
30 | {
31 | #[inline]
32 | pub fn new(generator: G, exponent: T) -> Self {
33 | Self {
34 | generator,
35 | exponent,
36 | }
37 | }
38 | }
39 |
40 | impl Generator for Pow
41 | where
42 | G: Generator,
43 | {
44 | #[inline]
45 | fn sample(&self, point: [f64; D]) -> f64 {
46 | self.generator.sample(point).powi(self.exponent)
47 | }
48 | }
49 |
50 | impl> Generator for Pow
51 | where
52 | G: Generator,
53 | {
54 | #[inline]
55 | fn sample(&self, point: [f64; D]) -> f64 {
56 | self.generator.sample(point).powf(self.exponent)
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/core/adapters/power.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator raising results of the underlying generator to the power of results of a
4 | /// given other generator.
5 | ///
6 | /// For details, see the documentation of [`power()`]. Typically, this struct is not meant
7 | /// to be used directly. Instead, [`power()`] implemented by [`Generator`], should be used
8 | /// to create [`Power`].
9 | ///
10 | /// [`power()`]: Generator::power
11 | #[derive(Clone, Copy, Debug)]
12 | pub struct Power {
13 | generator_a: GA,
14 | generator_b: GB,
15 | }
16 |
17 | impl, GB: Generator<1>> Generator1D for Power<1, GA, GB> {}
18 | impl, GB: Generator<2>> Generator2D for Power<2, GA, GB> {}
19 | impl, GB: Generator<3>> Generator3D for Power<3, GA, GB> {}
20 | impl, GB: Generator<4>> Generator4D for Power<4, GA, GB> {}
21 |
22 | impl Power
23 | where
24 | GA: Generator,
25 | GB: Generator,
26 | {
27 | #[inline]
28 | pub fn new(generator_a: GA, generator_b: GB) -> Self {
29 | Self {
30 | generator_a,
31 | generator_b,
32 | }
33 | }
34 | }
35 |
36 | impl Generator for Power
37 | where
38 | GA: Generator,
39 | GB: Generator,
40 | {
41 | #[inline]
42 | fn sample(&self, point: [f64; D]) -> f64 {
43 | self.generator_a
44 | .sample(point)
45 | .powf(self.generator_b.sample(point))
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/core/adapters/product.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator multiplying results of the underlying generator to results of a given other
4 | /// generator.
5 | ///
6 | /// For details, see the documentation of [`product()`]. Typically, this struct is not meant
7 | /// to be used directly. Instead, [`product()`] implemented by [`Generator`], should be used
8 | /// to create [`Product`].
9 | ///
10 | /// [`product()`]: Generator::product
11 | #[derive(Clone, Copy, Debug)]
12 | pub struct Product {
13 | generator_a: GA,
14 | generator_b: GB,
15 | }
16 |
17 | impl, GB: Generator<1>> Generator1D for Product<1, GA, GB> {}
18 | impl, GB: Generator<2>> Generator2D for Product<2, GA, GB> {}
19 | impl, GB: Generator<3>> Generator3D for Product<3, GA, GB> {}
20 | impl, GB: Generator<4>> Generator4D for Product<4, GA, GB> {}
21 |
22 | impl Product
23 | where
24 | GA: Generator,
25 | GB: Generator,
26 | {
27 | #[inline]
28 | pub fn new(generator_a: GA, generator_b: GB) -> Self {
29 | Self {
30 | generator_a,
31 | generator_b,
32 | }
33 | }
34 | }
35 |
36 | impl Generator for Product
37 | where
38 | GA: Generator,
39 | GB: Generator,
40 | {
41 | #[inline]
42 | fn sample(&self, point: [f64; D]) -> f64 {
43 | self.generator_a.sample(point) * self.generator_b.sample(point)
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/core/adapters/ridgedmulti.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// Create a generator applying an `fbm()`-like effect on the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`ridgedmulti()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`ridgedmulti()`] implemented by [`Generator`], should be used
7 | /// to create [`RidgedMulti`].
8 | ///
9 | /// [`fbm()`]: Generator:fbm
10 | /// [`ridgedmulti()`]: Generator::ridgedmulti
11 | #[derive(Clone, Copy, Debug)]
12 | pub struct RidgedMulti {
13 | generator: G,
14 | octaves: u32,
15 | frequency: f64,
16 | lacunarity: f64,
17 | attenuation: f64,
18 | normalization_factor: f64,
19 | }
20 |
21 | impl> Generator1D for RidgedMulti<1, G> {}
22 | impl> Generator2D for RidgedMulti<2, G> {}
23 | impl> Generator3D for RidgedMulti<3, G> {}
24 | impl> Generator4D for RidgedMulti<4, G> {}
25 |
26 | impl RidgedMulti
27 | where
28 | G: Generator,
29 | {
30 | #[inline]
31 | pub fn new(
32 | generator: G,
33 | octaves: u32,
34 | frequency: f64,
35 | lacunarity: f64,
36 | attenuation: f64,
37 | ) -> Self {
38 | let normalization_factor = compute_normalization_factor(octaves, attenuation);
39 | Self {
40 | generator,
41 | octaves,
42 | frequency,
43 | lacunarity,
44 | attenuation,
45 | normalization_factor,
46 | }
47 | }
48 | }
49 |
50 | macro_rules! impl_generator {
51 | ($dim:literal) => {
52 | impl> Generator<$dim> for RidgedMulti<$dim, G> {
53 | fn sample(&self, point: [f64; $dim]) -> f64 {
54 | let mut noise = 0.0;
55 | let mut amp = 1.0;
56 | let mut freq = self.frequency;
57 | for _ in 0..self.octaves {
58 | let mut layer = 1.0 - self.generator.sample(point.map(|x| x * freq)).abs();
59 | layer *= layer;
60 | layer *= amp;
61 | noise += layer;
62 | freq *= self.lacunarity;
63 | amp = (layer / self.attenuation).clamp(0.0, 1.0);
64 | }
65 | (noise * self.normalization_factor).mul_add(2.0, -1.0)
66 | }
67 | }
68 | };
69 | }
70 |
71 | impl_generator!(1);
72 | impl_generator!(2);
73 | impl_generator!(3);
74 | impl_generator!(4);
75 |
76 | #[inline]
77 | fn compute_normalization_factor(octaves: u32, attenuation: f64) -> f64 {
78 | 1.0 / (0..octaves).fold(0.0, |acc, octave| {
79 | acc + (1.0 / attenuation).powi(octave as i32)
80 | })
81 | }
82 |
--------------------------------------------------------------------------------
/src/core/adapters/rotate.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator which rotates input points before passing them to the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`rotate()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`rotate()`] implemented by [`Rotate`], should be used
7 | /// to create [`Rotate`].
8 | ///
9 | /// [`rotate()`]: Generator2D::rotate
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Rotate {
12 | generator: G,
13 | rotation: [f64; P],
14 | }
15 |
16 | impl> Generator2D for Rotate<2, 1, G> {}
17 | impl> Generator3D for Rotate<3, 3, G> {}
18 | impl> Generator4D for Rotate<4, 6, G> {}
19 |
20 | impl Rotate
21 | where
22 | G: Generator,
23 | {
24 | #[inline]
25 | pub fn new(generator: G, rotation: [f64; P]) -> Self {
26 | Self {
27 | generator,
28 | rotation,
29 | }
30 | }
31 | }
32 |
33 | impl> Generator<2> for Rotate<2, 1, G> {
34 | fn sample(&self, point: [f64; 2]) -> f64 {
35 | let x = point[0];
36 | let y = point[1];
37 |
38 | let sin_theta = self.rotation[0].sin();
39 | let cos_theta = self.rotation[0].cos();
40 |
41 | let xr = x * cos_theta - y * sin_theta;
42 | let yr = x * sin_theta + y * cos_theta;
43 |
44 | self.generator.sample([xr, yr])
45 | }
46 | }
47 |
48 | impl> Generator<3> for Rotate<3, 3, G> {
49 | fn sample(&self, point: [f64; 3]) -> f64 {
50 | let x = point[0];
51 | let y = point[1];
52 | let z = point[2];
53 |
54 | let sin_a = self.rotation[0].sin();
55 | let cos_a = self.rotation[0].cos();
56 |
57 | let sin_b = self.rotation[1].sin();
58 | let cos_b = self.rotation[1].cos();
59 |
60 | let sin_g = self.rotation[2].sin();
61 | let cos_g = self.rotation[2].cos();
62 |
63 | let xr = cos_b * (x * cos_g + y * sin_g) + z * (-sin_b);
64 | let yr =
65 | sin_a * (sin_b * (x * cos_g + y * sin_g) + z * cos_b) - cos_a * (x * sin_g - y * cos_g);
66 | let zr =
67 | cos_a * (sin_b * (x * cos_g + y * sin_g) + z * cos_b) + sin_a * (x * sin_g - y * cos_g);
68 |
69 | self.generator.sample([xr, yr, zr])
70 | }
71 | }
72 |
73 | impl> Generator<4> for Rotate<4, 6, G> {
74 | fn sample(&self, point: [f64; 4]) -> f64 {
75 | let x = point[0];
76 | let y = point[1];
77 | let z = point[2];
78 | let w = point[3];
79 | let sin_alpha = self.rotation[0].sin();
80 | let cos_alpha = self.rotation[0].cos();
81 | let sin_beta = self.rotation[1].sin();
82 | let cos_beta = self.rotation[1].cos();
83 | let sin_gamma = self.rotation[2].sin();
84 | let cos_gamma = self.rotation[2].cos();
85 | let sin_delta = self.rotation[3].sin();
86 | let cos_delta = self.rotation[3].cos();
87 | let sin_epsilon = self.rotation[4].sin();
88 | let cos_epsilon = self.rotation[4].cos();
89 | let sin_digamma = self.rotation[5].sin();
90 | let cos_digamma = self.rotation[5].cos();
91 |
92 | let xr = cos_alpha
93 | * (x * cos_beta * cos_gamma
94 | + sin_beta
95 | * (sin_delta
96 | * (sin_epsilon * (z * sin_digamma + w * cos_digamma) - y * cos_epsilon)
97 | + cos_delta * (-z * cos_digamma + w * sin_digamma))
98 | + sin_gamma
99 | * (cos_beta
100 | * (cos_epsilon * (-z * sin_digamma - w * cos_digamma) - y * sin_epsilon)))
101 | + sin_alpha
102 | * (cos_delta
103 | * (sin_epsilon * (z * sin_digamma + w * cos_digamma) - y * cos_epsilon)
104 | + sin_delta * (z * cos_digamma - w * sin_digamma));
105 |
106 | let yr = sin_alpha
107 | * (cos_beta
108 | * (sin_gamma
109 | * (cos_epsilon * (-z * sin_digamma - w * cos_digamma) - y * sin_epsilon)
110 | + x * cos_gamma)
111 | + sin_beta
112 | * (sin_delta
113 | * (sin_epsilon * (z * sin_digamma + w * cos_digamma) - y * cos_epsilon)
114 | + cos_delta * (-z * cos_digamma + w * sin_digamma)))
115 | + cos_alpha
116 | * (cos_delta
117 | * (sin_epsilon * (-z * sin_digamma - w * cos_digamma) + y * cos_epsilon)
118 | + sin_delta * (-z * cos_digamma + w * sin_digamma));
119 |
120 | let zr = cos_beta
121 | * (sin_epsilon * (sin_delta * (-z * sin_digamma - w * cos_digamma))
122 | + cos_delta * (z * cos_digamma - w * sin_digamma)
123 | + y * sin_gamma * cos_epsilon)
124 | + sin_beta
125 | * (sin_gamma
126 | * (sin_epsilon * (-y - z * sin_digamma) - w * cos_digamma * cos_epsilon)
127 | + x * cos_gamma);
128 |
129 | let wr = cos_gamma * (cos_epsilon * (z * sin_digamma + w * cos_digamma) + y * sin_epsilon)
130 | + x * sin_gamma;
131 |
132 | self.generator.sample([xr, yr, zr, wr])
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/core/adapters/scale.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// A generator which scales input points before passing them to the underlying generator.
4 | ///
5 | /// For details, see the documentation of [`scale()`]. Typically, this struct is not meant
6 | /// to be used directly. Instead, [`scale()`] implemented by [`Generator`], should be used
7 | /// to create [`Scale`].
8 | ///
9 | /// [`scale()`]: Generator::scale
10 | #[derive(Clone, Copy, Debug)]
11 | pub struct Scale {
12 | generator: G,
13 | scale: [f64; D],
14 | }
15 |
16 | impl> Generator1D for Scale<1, G> {}
17 | impl> Generator2D for Scale<2, G> {}
18 | impl> Generator3D for Scale<3, G> {}
19 | impl> Generator4D for Scale<4, G> {}
20 |
21 | impl Scale
22 | where
23 | G: Generator,
24 | {
25 | #[inline]
26 | pub fn new(generator: G, scale: [f64; D]) -> Self {
27 | Self { generator, scale }
28 | }
29 | }
30 |
31 | impl Generator for Scale
32 | where
33 | G: Generator,
34 | {
35 | #[inline]
36 | fn sample(&self, point: [f64; D]) -> f64 {
37 | self.generator
38 | .sample(std::array::from_fn(|i| point[i] * self.scale[i]))
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/core/adapters/select.rs:
--------------------------------------------------------------------------------
1 | use crate::core::generator::{Generator, Generator1D, Generator2D, Generator3D, Generator4D};
2 |
3 | /// Create a generator selecting the result of either the underlying generator or that of a given
4 | /// other generator based on whether the value supplied by a control-generator lies within the
5 | /// provided interval.
6 | ///
7 | /// For details, see the documentation of [`select()`]. Typically, this struct is not meant
8 | /// to be used directly. Instead, [`select()`] implemented by [`Generator`], should be used
9 | /// to create [`Select`].
10 | ///
11 | /// [`select()`]: Generator::select
12 | #[derive(Clone, Copy, Debug)]
13 | pub struct Select {
14 | generator_a: GA,
15 | generator_b: GB,
16 | generator_control: GC,
17 | selection_min: f64,
18 | selection_max: f64,
19 | }
20 |
21 | impl, GB: Generator<1>, GC: Generator<1>> Generator1D for Select<1, GA, GB, GC> {}
22 | impl, GB: Generator<2>, GC: Generator<2>> Generator2D for Select<2, GA, GB, GC> {}
23 | impl, GB: Generator<3>, GC: Generator<3>> Generator3D for Select<3, GA, GB, GC> {}
24 | impl, GB: Generator<4>, GC: Generator<4>> Generator4D for Select<4, GA, GB, GC> {}
25 |
26 | impl Select
27 | where
28 | GA: Generator,
29 | GB: Generator,
30 | GC: Generator,
31 | {
32 | #[inline]
33 | pub fn new(
34 | generator_a: GA,
35 | generator_b: GB,
36 | generator_control: GC,
37 | selection_min: f64,
38 | selection_max: f64,
39 | ) -> Self {
40 | Self {
41 | generator_a,
42 | generator_b,
43 | generator_control,
44 | selection_min,
45 | selection_max,
46 | }
47 | }
48 | }
49 |
50 | impl Generator for Select
51 | where
52 | GA: Generator