n/basis: add patch basis function

This commit is contained in:
Danny Robson 2015-07-24 01:37:36 +10:00
parent 57808c92b5
commit 33dece611a
4 changed files with 175 additions and 4 deletions

View File

@ -149,6 +149,8 @@ UTIL_FILES = \
noise/basis/constant.cpp \
noise/basis/constant.hpp \
noise/basis/constant.ipp \
noise/basis/patch.hpp \
noise/basis/patch.ipp \
noise/basis/perlin.hpp \
noise/basis/perlin.ipp \
noise/basis/runtime.cpp \

43
noise/basis/patch.hpp Normal file
View File

@ -0,0 +1,43 @@
/*
* 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 <danny@nerdcruft.net>
*/
#ifndef __UTIL_NOISE_BASIS_PATCH_HPP
#define __UTIL_NOISE_BASIS_PATCH_HPP
#include "point.hpp"
namespace util { namespace noise { namespace basis {
template <typename T>
struct patch {
patch (seed_t);
range<T> bounds (void) const;
T operator() (point2<T>) const;
seed_t seed (void) const;
seed_t seed (seed_t);
private:
point2<T> centroid (util::point2i) const;
T generate (util::point2i) const;
seed_t m_seed;
};
} } }
#include "patch.ipp"
#endif

117
noise/basis/patch.ipp Normal file
View File

@ -0,0 +1,117 @@
/*
* 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 <danny@nerdcruft.net>
*/
#if defined(__UTIL_NOISE_BASIS_PATCH_IPP)
#error
#endif
#define __UTIL_NOISE_BASIS_PATCH_IPP
///////////////////////////////////////////////////////////////////////////////
template <typename T>
util::noise::basis::patch<T>::patch (seed_t _seed):
m_seed (_seed)
{ ; }
///////////////////////////////////////////////////////////////////////////////
template <typename T>
util::range<T>
util::noise::basis::patch<T>::bounds (void) const
{
return { T{0}, T{1} };
}
///////////////////////////////////////////////////////////////////////////////
template <typename T>
T
util::noise::basis::patch<T>::operator () (point2<T> 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<intmax_t> ();
if (p.x < 0) p_int.x -= 1;
if (p.y < 0) p_int.y -= 1;
auto p_rem = (p - p_int).template as<point> ();
T closest = std::numeric_limits<T>::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 <typename T>
util::noise::seed_t
util::noise::basis::patch<T>::seed (void) const
{
return m_seed;
}
//-----------------------------------------------------------------------------
template <typename T>
util::noise::seed_t
util::noise::basis::patch<T>::seed (util::noise::seed_t _seed)
{
return m_seed = _seed;
}
///////////////////////////////////////////////////////////////////////////////
template <typename T>
util::point2<T>
util::noise::basis::patch<T>::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 <typename T>
T
util::noise::basis::patch<T>::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};
}

View File

@ -9,6 +9,7 @@
#include "noise/lerp.hpp"
#include "noise/basis/constant.hpp"
#include "noise/basis/value.hpp"
#include "noise/basis/patch.hpp"
#include "noise/basis/perlin.hpp"
#include "noise/basis/worley.hpp"
#include "noise/turbulence.hpp"
@ -34,7 +35,8 @@ template struct util::noise::fractal::hetero<float, util::noise::basis::worley<f
enum basis_t {
VALUE,
PERLIN,
WORLEY
WORLEY,
PATCH
};
@ -67,6 +69,7 @@ operator>> (std::istream &is, basis_t &b)
b = name == "value" ? VALUE :
name == "perlin" ? PERLIN :
name == "worley" ? WORLEY :
name == "patch" ? PATCH :
(is.setstate (std::istream::failbit), b);
return is;
@ -78,9 +81,10 @@ std::ostream&
operator<< (std::ostream &os, basis_t b)
{
switch (b) {
case VALUE: os << "value"; return os;
case PERLIN: os << "perlin"; return os;
case WORLEY: os << "worley"; return os;
case VALUE: os << "value"; return os;
case PERLIN: os << "perlin"; return os;
case WORLEY: os << "worley"; return os;
case PATCH: os << "patch"; return os;
default:
unreachable ();
@ -288,6 +292,11 @@ main (int argc, char **argv)
break;
}
case PATCH: {
b.reset<util::noise::basis::patch<float>> (seed);
break;
}
default:
unreachable ();
}