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}