-
Notifications
You must be signed in to change notification settings - Fork 8
/
noise-worley.R
102 lines (100 loc) · 4.89 KB
/
noise-worley.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#' Worley (cell) noise generator
#'
#' Worley noise, sometimes called cell (or cellular) noise, is quite distinct
#' due to it's kinship to voronoi tesselation. It is created by sampling random
#' points in space and then for any point in space measure the distance to the
#' closest point. The noise can be modified further by changing either the
#' distance measure or by combining multiple distances. The noise algorithm was
#' developed by Steven Worley in 1996 and has been used to simulated water and
#' stone textures among other things.
#'
#' @inheritParams noise_perlin
#' @param distance The distance measure to use, either `'euclidean'` (default),
#' `'manhattan'`, or `'natural'` (a mix of the two)
#' @param value The noise value to return. Either
#' - `'value'` (default) A random value associated with the closest point
#' - `'distance'` The distance to the closest point
#' - `'distance2'` The distance to the nth closest point (n given by
#' `distance_ind[1]`)
#' - `'distance2add'` Addition of the distance to the nth and mth closest point given in `distance_ind`
#' - `'distance2sub'` Substraction of the distance to the nth and mth closest point given in `distance_ind`
#' - `'distance2mul'` Multiplication of the distance to the nth and mth closest point given in `distance_ind`
#' - `'distance2div'` Division of the distance to the nth and mth closest point given in `distance_ind`
#' @param distance_ind Reference to the nth and mth closest points that should
#' be used when calculating `value`.
#' @param jitter The maximum distance a point can move from its start position
#' during sampling of cell points.
#'
#' @return For `noise_worley()` a matrix if `length(dim) == 2` or an array if
#' `length(dim) == 3`. For `gen_worley()` a numeric vector matching the length of
#' the input.
#'
#' @references Worley, Steven (1996). *A cellular texture basis function*. Proceedings of the 23rd annual conference on computer graphics and interactive techniques. pp. 291–294. ISBN 0-89791-746-4
#'
#' @export
#'
#' @examples
#' # Basic use
#' noise <- noise_worley(c(100, 100))
#'
#' plot(as.raster(normalise(noise)))
#'
#' # Using the generator and another value metric
#' grid <- long_grid(seq(1, 10, length.out = 1000), seq(1, 10, length.out = 1000))
#' grid$noise <- gen_worley(grid$x, grid$y, value = 'distance')
#' plot(grid, noise)
#'
noise_worley <- function(dim, frequency = 0.01, distance = 'euclidean',
fractal = 'none', octaves = 3, lacunarity = 2, gain = 0.5,
value = 'cell', distance_ind = c(1, 2), jitter = 0.45,
pertubation = 'none', pertubation_amplitude = 1) {
distance <- match.arg(distance, distances)
distance <- match(distance, distances) - 1L
distance_ind <- as.integer(distance_ind) - 1L
value <- match.arg(value, values)
value <- match(value, values) - 1L
fractal <- match.arg(fractal, fractals)
fractal <- match(fractal, fractals) - 1L
pertubation <- match.arg(pertubation, pertubations)
pertubation <- match(pertubation, pertubations) - 1L
if (length(dim) == 2) {
noise <- worley_2d_c(dim[1], dim[2], seed = sample(.Machine$integer.max, size = 1),
freq = frequency, fractal = fractal, octaves = octaves,
lacunarity = lacunarity, gain = gain,dist = distance,
value = value, dist2ind = distance_ind, jitter = jitter,
pertube = pertubation, pertube_amp = pertubation_amplitude)
} else if (length(dim) == 3) {
noise <- worley_3d_c(dim[1], dim[2], dim[3], seed = sample(.Machine$integer.max, size = 1),
freq = frequency, fractal = fractal, octaves = octaves,
lacunarity = lacunarity, gain = gain,dist = distance,
value = value, dist2ind = distance_ind, jitter = jitter,
pertube = pertubation, pertube_amp = pertubation_amplitude)
noise <- array(noise, dim)
} else {
stop('Worley noise only supports two or three dimensions', call. = FALSE)
}
noise
}
#' @rdname noise_worley
#' @param x,y,z Coordinates to get noise value from
#' @export
gen_worley <- function(x, y = NULL, z = NULL, frequency = 1, seed = NULL,
distance = 'euclidean', value = 'cell',
distance_ind = c(1, 2), jitter = 0.45, ...) {
dims <- check_dims(x, y, z)
distance <- match.arg(distance, distances)
distance <- match(distance, distances) - 1L
distance_ind <- as.integer(distance_ind) - 1L
value <- match.arg(value, values)
value <- match(value, values) - 1L
if (is.null(seed)) seed <- random_seed()
frequency <- as.numeric(frequency)
seed <- as.integer(seed)
if (is.null(z)) {
gen_worley2d_c(dims$x, dims$y, frequency, seed, distance, value,
distance_ind, jitter)
} else {
gen_worley3d_c(dims$x, dims$y, dims$z, frequency, seed, distance, value,
distance_ind, jitter)
}
}