libnoise/core/source.rs
1use super::utils::ptable::Seed;
2use crate::core::sources::{
3 Checkerboard, Constant, Custom, ImprovedPerlin, Perlin, Simplex, Value, Worley,
4};
5
6/// A struct serving as entry point for building generators.
7///
8/// This structs only purpose is to be used as an entry point for building generators. This is done by
9/// calling the functions of this struct, all of which return objects implementing [`Generator<D>`].
10/// These objects are called a source, because unlike adapters, they do not require at least one other
11/// generator to be created.
12///
13/// # Sources for creating a generator
14///
15/// In the following example, we create a generator using the [`Simplex<D>`] source. While it could be
16/// constructed directly, we suggest using the [`simplex()`] function instead for convenience. The
17/// dimensionality of the input, represented by the constant generic parameter `D`, must be known at
18/// compile time. Here it is inferred due to the call to [`sample()`] with an argument of size 2:
19///
20/// ```
21/// # use libnoise::{Source, Generator};
22/// // create a 2-dimensional simplex noise generator
23/// let generator = Source::simplex(42);
24///
25/// // use the generatore to sample the function at a specific point
26/// let value = generator.sample([0.2, 0.5]);
27/// ```
28///
29/// The dimensionality can also be specified explicitly by providing a value for the constant generic
30/// parameter `D`:
31///
32/// ```
33/// // create a 4-dimensional simplex noise generator
34/// # use libnoise::Source;
35/// let generator = Source::<4>::simplex(42);
36/// ```
37///
38/// [`Generator<D>`]: crate::Generator
39/// [`simplex()`]: Source::simplex
40/// [`sample()`]: crate::Generator::sample
41pub struct Source<const D: usize>;
42
43impl<const D: usize> Source<D> {
44 /// Create a generator which produces the supplied value for every input point.
45 ///
46 /// The created generator returns `value` for every input.
47 ///
48 /// # Examples
49 ///
50 /// Basic usage:
51 ///
52 /// ```
53 /// # use libnoise::{Source, Generator};
54 /// // create the generator
55 /// let generator = Source::constant(6.9);
56 ///
57 /// assert_eq!(generator.sample([0.4, 0.5]), generator.sample([0.7, 0.3]))
58 /// ```
59 pub fn constant(value: f64) -> Constant<D> {
60 Constant::new(value)
61 }
62
63 /// Create a generator which produces n-dimensional simplex noise.
64 ///
65 /// The created generator returns n-dimensional simplex noise. Simplex noise is a commonly used
66 /// type of gradient noise. It is computed by dividing the input space into a simplicial lattice
67 /// with each point being assigned a pseudorandom n-dimensional gradient. This randomness is
68 /// solely derived from the value of `seed`. The actual noise value is determined from the
69 /// relative position of the input point in the simplex it resides in as well as the gradients
70 /// assigned to the simplex corners.
71 ///
72 /// <p style="background:rgba(122,186,255,0.16);padding:0.75em;">
73 /// <strong>Note:</strong>
74 /// Simplex noise is expected to return a value in the range [-1, 1]. However, for sufficiently
75 /// large inputs (which typically are unreasonable), certain computations may overflow, resulting
76 /// in the generator returning NaN instead.
77 /// </p>
78 ///
79 /// # Examples
80 ///
81 /// Basic usage:
82 ///
83 /// ```
84 /// # use libnoise::{Source, Generator};
85 /// let generator = Source::simplex(42);
86 /// let value = generator.sample([0.2, 0.5]);
87 /// ```
88 pub fn simplex(seed: impl Seed) -> Simplex<D> {
89 Simplex::new(seed)
90 }
91
92 /// Create a generator which produces n-dimensional value noise.
93 ///
94 /// The created generator returns n-dimensional value noise. Value noise subdivides the input
95 /// space into a grid lattice and assigns each point a pseudorandom value. This randomness is
96 /// solely derived from the value of `seed`. the value for the input point is determined by
97 /// smoothed interpolating the values of the corners of the hypercube in which the input lies
98 /// accordingly.
99 ///
100 /// <p style="background:rgba(122,186,255,0.16);padding:0.75em;">
101 /// <strong>Note:</strong>
102 /// Value noise is expected to return a value in the range [-1, 1].
103 /// </p>
104 ///
105 /// # Examples
106 ///
107 /// Basic usage:
108 ///
109 /// ```
110 /// # use libnoise::{Source, Generator};
111 /// let generator = Source::value(42);
112 /// let value = generator.sample([0.2, 0.5]);
113 /// ```
114 pub fn value(seed: impl Seed) -> Value<D> {
115 Value::new(seed)
116 }
117
118 /// Create a generator which produces n-dimensional perlin noise.
119 ///
120 /// The created generator returns n-dimensional perlin noise. Perlin noise is a commonly used
121 /// type of gradient noise. It is computed by dividing the input space into a grid lattice with
122 /// each point being assigned a pseudorandom n-dimensional gradient. This randomness is solely
123 /// derived from the value of `seed`. The actual noise value is determined from the relative
124 /// position of the input point in the hypercube it resides in as well as the gradients assigned
125 /// to the hypercube corners.
126 ///
127 /// <p style="background:rgba(122,186,255,0.16);padding:0.75em;">
128 /// <strong>Note:</strong>
129 /// Perlin noise is expected to return a value in the range [-1, 1].
130 /// </p>
131 ///
132 /// # Examples
133 ///
134 /// Basic usage:
135 ///
136 /// ```
137 /// # use libnoise::{Source, Generator};
138 /// let generator = Source::perlin(42);
139 /// let value = generator.sample([0.2, 0.5]);
140 /// ```
141 pub fn perlin(seed: impl Seed) -> Perlin<D> {
142 Perlin::new(seed)
143 }
144
145 /// Create a generator which produces n-dimensional improved perlin noise.
146 ///
147 /// The created generator returns n-dimensional improved perlin noise. Improved perlin noise is a
148 /// commonly used type of gradient noise. It is computed by dividing the input space into a grid
149 /// lattice with each point being assigned a pseudorandom n-dimensional gradient. This randomness
150 /// is solely derived from the value of `seed`. The actual noise value is determined from the
151 /// relative position of the input point in the hypercube it resides in as well as the gradients
152 /// assigned to the hypercube corners.
153 ///
154 /// The changes to normal perlin noise are twofold: First, the smoothing function used for
155 /// interpolation is replaced by a C2-continuous function. Second, the set of possible gradients
156 /// for lattice points is modified to make the noise output appear more natural.
157 ///
158 /// <p style="background:rgba(122,186,255,0.16);padding:0.75em;">
159 /// <strong>Note:</strong>
160 /// Improved perlin noise is expected to return a value in the range [-1, 1].
161 /// </p>
162 ///
163 /// # Examples
164 ///
165 /// Basic usage:
166 ///
167 /// ```
168 /// # use libnoise::{Source, Generator};
169 /// let generator = Source::improved_perlin(42);
170 /// let value = generator.sample([0.2, 0.5]);
171 /// ```
172 pub fn improved_perlin(seed: impl Seed) -> ImprovedPerlin<D> {
173 ImprovedPerlin::new(seed)
174 }
175
176 /// Create a generator which produces n-dimensional worley noise.
177 ///
178 /// The created generator returns n-dimensional worley noise (also called cell noise, cellular
179 /// noise, voronoi noise). The noise is computed by dividing the input space into a grid lattice.
180 /// Each hypercube is assigned a pseudorandom point that lies within it. This randomness is solely
181 /// derived from the value of `seed`. For a given input point, the noise value is determined by
182 /// computing the euclidean (L2) distance to the nearest such point.
183 ///
184 /// <p style="background:rgba(122,186,255,0.16);padding:0.75em;">
185 /// <strong>Note:</strong>
186 /// Worley noise is expected to return a value in the range [-1, 1].
187 /// </p>
188 ///
189 /// <p style="background:rgba(122,186,255,0.16);padding:0.75em;">
190 /// <strong>Note:</strong>
191 /// This implementation employs an optimization which in rare cases causes the results to deviate
192 /// slightly from the expected value. Specifically, only the own as well as directly and diagonally
193 /// adjacent hypercubes are considered. This optimization reduces the time necessary to compute
194 /// this noise significantly without introducing noticeable artifacts in the output.
195 /// </p>
196 ///
197 /// # Examples
198 ///
199 /// Basic usage:
200 ///
201 /// ```
202 /// # use libnoise::{Source, Generator};
203 /// let generator = Source::worley(42);
204 /// let value = generator.sample([0.2, 0.5]);
205 /// ```
206 pub fn worley(seed: impl Seed) -> Worley<D> {
207 Worley::new(seed)
208 }
209
210 /// Create a generator which produces an n-dimensional checkerboard pattern.
211 ///
212 /// The created generator returns n-dimensional checkerboard pattern. That is, the input space
213 /// is divided into a grid lattice wherein each hypercube is assigned either -1 or 1 such that
214 /// no two adjacent hypercubes are assigned the same value. The noise value is determined by
215 /// returning the value assigned to the hypercube in which the input point lies.
216 ///
217 /// # Examples
218 ///
219 /// Basic usage:
220 ///
221 /// ```
222 /// # use libnoise::{Source, Generator};
223 /// let generator = Source::checkerboard();
224 /// let value = generator.sample([0.2, 0.5]);
225 /// ```
226 pub fn checkerboard() -> Checkerboard<D> {
227 Checkerboard::new()
228 }
229
230 /// Create a generator which produces n-dimensional values based on the provided closure.
231 ///
232 /// The created generator returns n-dimensional values by executing the provided closure `f`
233 /// for the input point and producing the result. This allows usage of adapters and other
234 /// library functionality without being restricted to a specific source.
235 ///
236 /// # Examples
237 ///
238 /// Basic usage:
239 ///
240 /// ```
241 /// # use libnoise::{Source, Generator};
242 /// let generator = Source::custom(|[x, y]| x % 2.0 + (1.0 - y * y) % 3.0);
243 /// let value = generator.sample([0.2, 0.5]);
244 /// ```
245 pub fn custom<F: Fn([f64; D]) -> f64>(f: F) -> Custom<D, F> {
246 Custom::new(f)
247 }
248}