20 #ifndef ANTKEEPER_MATH_NOISE_SIMPLEX_HPP
21 #define ANTKEEPER_MATH_NOISE_SIMPLEX_HPP
37 template <std::
size_t N>
38 constexpr std::size_t simplex_corner_count = std::size_t(2) << std::max<std::size_t>(0, N - 1);
45 template <std::
size_t N>
46 constexpr std::size_t simplex_edge_count = (N > 1) ? N * simplex_corner_count<N - 1> : 2;
53 template <
class T, std::size_t N, std::size_t... I>
54 [[nodiscard]] constexpr vector<T, N> make_simplex_corner(std::size_t i, std::index_sequence<I...>)
56 return {((
i >> I) % 2) * T{2} - T{1}...};
64 template <
class T, std::size_t N, std::size_t... I>
65 [[nodiscard]] constexpr std::array<vector<T, N>, simplex_corner_count<N>> make_simplex_corners(std::index_sequence<I...>)
67 return {make_simplex_corner<T, N>(I, std::make_index_sequence<N>{})...};
75 template <
class T, std::
size_t N>
76 constexpr
auto simplex_corners = make_simplex_corners<T, N>(std::make_index_sequence<simplex_corner_count<N>>{});
83 template <
class T, std::size_t N, std::size_t... I>
84 [[nodiscard]] constexpr vector<T, N> make_simplex_edge(std::size_t i, std::index_sequence<I...>)
86 std::size_t
j =
i / (simplex_edge_count<N> / N);
91 simplex_corners<T, N - 1>[
i % simplex_corner_count<N - 1>][I]
94 simplex_corners<T, N - 1>[
i % simplex_corner_count<N - 1>][I - 1]
106 template <
class T, std::size_t N, std::size_t... I>
107 [[nodiscard]] constexpr std::array<vector<T, N>, simplex_edge_count<N>> make_simplex_edges(std::index_sequence<I...>)
109 if constexpr (N == 1)
110 return std::array<vector<T, N>, simplex_edge_count<N>>{vector<T, N>{T{1}}, vector<T, N>{T{-1}}};
112 return {make_simplex_edge<T, N>(I, std::make_index_sequence<N>{})...};
120 template <
class T, std::
size_t N>
121 constexpr
auto simplex_edges = make_simplex_edges<T, N>(std::make_index_sequence<simplex_edge_count<N>>{});
140 template <
class T, std::
size_t N>
148 static const T f = (
std::sqrt(
static_cast<T
>(N + 1)) - T{1}) /
static_cast<T
>(N);
149 static const T g = f / (T{1} + f *
static_cast<T
>(N));
152 constexpr T sqr_kernel_radius = T{0.5};
161 auto falloff = [sqr_kernel_radius](T
sqr_distance) constexpr
169 static const T corner_normalization = T{1} / ((
static_cast<T
>(N) /
std::sqrt(
static_cast<T
>(N + 1))) * falloff(
static_cast<T
>(N) / (T{4} *
static_cast<T
>(N + 1))));
172 static const T edge_normalization = corner_normalization * (
std::sqrt(
static_cast<T
>(N)) /
length(simplex_edges<T, N>[0]));
182 for (std::size_t i = 0; i < N; ++i)
188 [&dx](std::size_t lhs, std::size_t rhs)
190 return dx[lhs] > dx[rhs];
196 for (std::size_t i = 0; i <= N; ++i)
199 ++current_vertex[axis_order[i - 1]];
202 const vector<T, N> d = dx - (current_vertex - origin_vertex) + g *
static_cast<T
>(i);
209 const vector<T, N>& gradient = simplex_edges<T, N>[gradient_index];
211 n +=
dot(d, gradient) * t;
216 return n * edge_normalization;
typename make_uint< T >::type make_uint_t
Helper type for make_uint.
T simplex(const vector< T, N > &position, vector< hash::make_uint_t< T >, N >(*hash)(const vector< T, N > &)=&hash::pcg< T, N >)
n-dimensional simplex noise.
Mathematical functions and data types.
constexpr T sqr_distance(const vector< T, N > &p0, const vector< T, N > &p1) noexcept
Calculates the square distance between two points.
constexpr vector< T, N > floor(const vector< T, N > &x)
Performs a element-wise floor operation.
T length(const quaternion< T > &q)
Calculates the length of a quaternion.
constexpr T sqr_length(const quaternion< T > &q) noexcept
Calculates the square length of a quaternion.
vector< T, N > sqrt(const vector< T, N > &x)
Takes the square root of each element.
constexpr T dot(const quaternion< T > &a, const quaternion< T > &b) noexcept
Calculates the dot product of two quaternions.
constexpr T sum(const vector< T, N > &x) noexcept
Calculates the sum of all elements in a vector.
@ position
Vertex position (vec3)
constexpr element_type * begin() noexcept
Returns an iterator to the first element.
constexpr element_type * end() noexcept
Returns an iterator to the element following the last element.