/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright 2015 Danny Robson */ #if defined(__UTIL_NOISE_BASIS_PATCH_IPP) #error #endif #define __UTIL_NOISE_BASIS_PATCH_IPP /////////////////////////////////////////////////////////////////////////////// template util::noise::basis::patch::patch (seed_t _seed): m_seed (_seed) { ; } /////////////////////////////////////////////////////////////////////////////// template util::range util::noise::basis::patch::bounds (void) const { return { T{0}, T{1} }; } /////////////////////////////////////////////////////////////////////////////// template T util::noise::basis::patch::operator () (point2 p) const { // extract integer and fractional parts. be careful to always round down // (particularly with negatives) and avoid rounding errors. auto p_int = p.template cast (); if (p.x < 0) p_int.x -= 1; if (p.y < 0) p_int.y -= 1; auto p_rem = (p - p_int).template as (); T closest = std::numeric_limits::infinity (); T value; for (signed y = -1; y <= 1; ++y) for (signed x = -1; x <= 1; ++x) { util::vector2i offset {x, y}; auto c = centroid (p_int + offset); auto d = util::distance (p_rem, c + offset); if (d < closest) { closest = d; value = generate (p_int + offset); } } return value; } /////////////////////////////////////////////////////////////////////////////// template util::noise::seed_t util::noise::basis::patch::seed (void) const { return m_seed; } //----------------------------------------------------------------------------- template util::noise::seed_t util::noise::basis::patch::seed (util::noise::seed_t _seed) { return m_seed = _seed; } /////////////////////////////////////////////////////////////////////////////// template util::point2 util::noise::basis::patch::centroid (util::point2i p) const { using util::hash::murmur2::mix; auto u = mix (m_seed, mix (uint64_t (p.x), uint64_t (p.y))); auto v = mix (u, m_seed); auto r = util::point<2,T> { (u & 0xffff) / T{0xffff}, (v & 0xffff) / T{0xffff} }; CHECK_LIMIT (r, T{0}, T{1}); return r; } //----------------------------------------------------------------------------- template T util::noise::basis::patch::generate (util::point2i p) const { using util::hash::murmur2::mix; auto u = mix (m_seed, mix (uint64_t (p.x), uint64_t (p.y))); return (u & 0xffff) / T{0xffff}; }