noise/basis: extract basis into seperate units
This commit is contained in:
parent
c9812f7c78
commit
78f61af84c
@ -133,8 +133,13 @@ UTIL_FILES = \
|
||||
net/types.cpp \
|
||||
net/types.hpp \
|
||||
nocopy.hpp \
|
||||
noise/basis.cpp \
|
||||
noise/basis.hpp \
|
||||
noise/basis/value.cpp \
|
||||
noise/basis/value.hpp \
|
||||
noise/basis/perlin.cpp \
|
||||
noise/basis/perlin.hpp \
|
||||
noise/basis/worley.cpp \
|
||||
noise/basis/worley.hpp \
|
||||
noise.cpp \
|
||||
noise/fractal.cpp \
|
||||
noise/fractal.hpp \
|
||||
|
311
noise/basis.cpp
311
noise/basis.cpp
@ -1,311 +0,0 @@
|
||||
/*
|
||||
* 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 2012-2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "noise/basis.hpp"
|
||||
#include "noise/lut.hpp"
|
||||
|
||||
#include "../debug.hpp"
|
||||
#include "../point.hpp"
|
||||
#include "../random.hpp"
|
||||
#include "../vector.hpp"
|
||||
#include "../hash/murmur/murmur2.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using util::noise::basis;
|
||||
using util::noise::value;
|
||||
using util::noise::gradient;
|
||||
using util::noise::cellular;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Generate a type from [-UNIT..UNIT]
|
||||
template <typename T>
|
||||
T
|
||||
gen_scalar (util::point<2,T> p, uint64_t seed)
|
||||
{
|
||||
using util::hash::murmur2::mix;
|
||||
|
||||
T v = mix (seed, mix (uint64_t (p.y), uint64_t (p.x))) & 0xffff;
|
||||
v = v / T{0xffff} * 2 - 1;
|
||||
|
||||
CHECK_GE (v, T{0});
|
||||
CHECK_LE (v, T{1});
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
util::vector<2,T>
|
||||
gen_vector (util::point<2,T> p, uint64_t seed)
|
||||
{
|
||||
using util::hash::murmur2::mix;
|
||||
|
||||
auto u = mix (seed, mix (uint64_t (p.x), uint64_t (p.y)));
|
||||
auto v = mix (u, seed);
|
||||
|
||||
auto r = util::vector<2,T> {
|
||||
(u & 0xffff) / T{0xffff},
|
||||
(v & 0xffff) / T{0xffff}
|
||||
} * 2 - 1;
|
||||
|
||||
CHECK_GE (r, T{-1});
|
||||
CHECK_LE (r, T{ 1});
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
basis<T>::basis (seed_t _seed):
|
||||
seed (_seed)
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
basis<T>::basis ():
|
||||
seed (util::random<seed_t> ())
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
basis<T>::~basis ()
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
T
|
||||
basis<T>::operator() (util::point<2,T>) const
|
||||
{
|
||||
unreachable ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace util { namespace noise {
|
||||
template struct basis<float>;
|
||||
template struct basis<double>;
|
||||
} }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
value<T,L>::value (seed_t _seed):
|
||||
basis<T> (_seed)
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
value<T,L>::value ()
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
util::range<T>
|
||||
value<T,L>::bounds (void) const
|
||||
{
|
||||
return { -1, 1 };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
T
|
||||
value<T,L>::operator() (util::point<2,T> p) const
|
||||
{
|
||||
auto p_int = p.template cast<intmax_t> ();
|
||||
auto p_rem = p - p_int;
|
||||
|
||||
// Shift the coordinate system down a little to ensure we get unit weights
|
||||
// for the lerp. It's better to do this than abs the fractional portion so
|
||||
// we don't get reflections along the origin.
|
||||
if (p.x < 0) { p_rem.x = 1 + p_rem.x; p_int.x -= 1; }
|
||||
if (p.y < 0) { p_rem.y = 1 + p_rem.y; p_int.y -= 1; }
|
||||
|
||||
// Generate the four corner values
|
||||
T p0 = gen_scalar<T> (p_int + util::vector<2,T>{ 0, 0 }, this->seed);
|
||||
T p1 = gen_scalar<T> (p_int + util::vector<2,T>{ 1, 0 }, this->seed);
|
||||
T p2 = gen_scalar<T> (p_int + util::vector<2,T>{ 0, 0 }, this->seed);
|
||||
T p3 = gen_scalar<T> (p_int + util::vector<2,T>{ 1, 1 }, this->seed);
|
||||
|
||||
// Interpolate on one dimension, then the other.
|
||||
return L (L (p0, p1, p_rem.x),
|
||||
L (p2, p3, p_rem.x),
|
||||
p_rem.y);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace util { namespace noise {
|
||||
template struct value<float, lerp::trunc>;
|
||||
template struct value<float, lerp::linear>;
|
||||
template struct value<float, lerp::cubic>;
|
||||
template struct value<float, lerp::quintic>;
|
||||
|
||||
template struct value<double, lerp::trunc>;
|
||||
template struct value<double, lerp::linear>;
|
||||
template struct value<double, lerp::cubic>;
|
||||
template struct value<double, lerp::quintic>;
|
||||
} }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
gradient<T,L>::gradient (seed_t _seed):
|
||||
basis<T> (_seed)
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
gradient<T,L>::gradient ()
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
util::range<T>
|
||||
gradient<T,L>::bounds (void) const
|
||||
{ return { -std::sqrt(T{2}) / 2, std::sqrt (T{2}) / 2 }; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
T
|
||||
gradient<T,L>::operator() (util::point<2,T> p) const
|
||||
{
|
||||
auto p_int = p.template cast<intmax_t> ();
|
||||
auto p_rem = p - p_int;
|
||||
|
||||
// Shift the coordinate system down a little to ensure we get unit weights
|
||||
// for the lerp. It's better to do this than abs the fractional portion so
|
||||
// we don't get reflections along the origin.
|
||||
if (p.x < 0) { p_rem.x = 1 + p_rem.x; p_int.x -= 1; }
|
||||
if (p.y < 0) { p_rem.y = 1 + p_rem.y; p_int.y -= 1; }
|
||||
|
||||
// Generate the four corner values. It's not strictly necessary to
|
||||
// normalise the values, but we get a more consistent and visually
|
||||
// appealing range of outputs with normalised values.
|
||||
auto p0 = gen_vector<T> (p_int + util::vector<2,T> { 0, 0 }, this->seed).normalise ();
|
||||
auto p1 = gen_vector<T> (p_int + util::vector<2,T> { 1, 0 }, this->seed).normalise ();
|
||||
auto p2 = gen_vector<T> (p_int + util::vector<2,T> { 0, 1 }, this->seed).normalise ();
|
||||
auto p3 = gen_vector<T> (p_int + util::vector<2,T> { 1, 1 }, this->seed).normalise ();
|
||||
|
||||
T v0 = p0.x * p_rem.x + p0.y * p_rem.y;
|
||||
T v1 = p1.x * (p_rem.x - 1) + p1.y * p_rem.y;
|
||||
T v2 = p2.x * p_rem.x + p2.y * (p_rem.y - 1);
|
||||
T v3 = p3.x * (p_rem.x - 1) + p3.y * (p_rem.y - 1);
|
||||
|
||||
auto L0 = L (v0, v1, p_rem.x);
|
||||
auto L1 = L (v2, v3, p_rem.x);
|
||||
auto L_ = L (L0, L1, p_rem.y);
|
||||
return L_;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace util {
|
||||
namespace noise {
|
||||
template struct gradient<float, lerp::linear>;
|
||||
template struct gradient<float, lerp::cubic>;
|
||||
template struct gradient<float, lerp::quintic>;
|
||||
|
||||
template struct gradient<double, lerp::linear>;
|
||||
template struct gradient<double, lerp::cubic>;
|
||||
template struct gradient<double, lerp::quintic>;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
cellular<T>::cellular (seed_t _seed):
|
||||
basis<T> (_seed)
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
cellular<T>::cellular ()
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
util::range<T>
|
||||
cellular<T>::bounds (void) const
|
||||
{ return { 0.0, 1.5 }; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
T
|
||||
cellular<T>::operator() (util::point<2,T> p) const
|
||||
{
|
||||
auto p_int = p.template cast<intmax_t> ();
|
||||
auto p_rem = p - p_int;
|
||||
|
||||
// Generate the four corner values. It's not strictly necessary to
|
||||
// normalise the values, but we get a more consistent and visually
|
||||
// appealing range of outputs with normalised values.
|
||||
if (p.x < 0) { p_rem.x = 1 + p_rem.x; p_int.x -= 1; }
|
||||
if (p.y < 0) { p_rem.y = 1 + p_rem.y; p_int.y -= 1; }
|
||||
|
||||
// +---+---+---+
|
||||
// | 0 | 1 | 2 |
|
||||
// +---+---+---+
|
||||
// | 3 | 4 | 5 |
|
||||
// +---+-------+
|
||||
// | 6 | 7 | 8 |
|
||||
// +---+---+---+
|
||||
|
||||
T distances[9] = { std::numeric_limits<T>::quiet_NaN () };
|
||||
T *cursor = distances;
|
||||
|
||||
for (signed y_off = -1; y_off <= 1 ; ++y_off)
|
||||
for (signed x_off = -1; x_off <= 1; ++x_off) {
|
||||
auto pos = vector<2,T> (T (x_off), T (y_off));
|
||||
auto off = gen_vector<T> (p_int + pos, this->seed);
|
||||
off += T{1};
|
||||
off /= T{2};
|
||||
|
||||
CHECK (off.x >= 0 && off.x <= 1);
|
||||
CHECK (off.y >= 0 && off.y <= 1);
|
||||
|
||||
pos += off;
|
||||
*cursor++ = pos.difference2 (p_rem);
|
||||
}
|
||||
|
||||
std::sort (std::begin (distances), std::end (distances));
|
||||
CHECK_GE (distances[0], 0);
|
||||
CHECK (bounds ().contains (distances[0]));
|
||||
return distances[0];
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace util { namespace noise {
|
||||
template struct cellular<float>;
|
||||
template struct cellular<double>;
|
||||
} }
|
@ -17,67 +17,11 @@
|
||||
#ifndef __UTIL_NOISE_BASIS_HPP
|
||||
#define __UTIL_NOISE_BASIS_HPP
|
||||
|
||||
#include <cstdlib>
|
||||
#include "lerp.hpp"
|
||||
#include "../point.hpp"
|
||||
#include "../range.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
namespace util { namespace noise {
|
||||
template <typename T> using lerp_t = T (*)(T,T,T);
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct basis {
|
||||
typedef uint64_t seed_t;
|
||||
|
||||
basis (seed_t);
|
||||
basis ();
|
||||
virtual ~basis ();
|
||||
|
||||
seed_t seed;
|
||||
|
||||
virtual range<T> bounds (void) const = 0;
|
||||
virtual T operator() (util::point<2,T>) const = 0;
|
||||
};
|
||||
|
||||
|
||||
/// Single value per grid space
|
||||
template <typename T, lerp_t<T>>
|
||||
struct value : public basis<T> {
|
||||
using seed_t = typename basis<T>::seed_t;
|
||||
|
||||
value (seed_t);
|
||||
value ();
|
||||
|
||||
virtual range<T> bounds (void) const final;
|
||||
virtual T operator() (util::point<2,T>) const final;
|
||||
};
|
||||
|
||||
|
||||
/// Perlin: interpolated value across each grid space
|
||||
template <typename T, lerp_t<T> L>
|
||||
struct gradient : public basis<T> {
|
||||
using seed_t = typename basis<T>::seed_t;
|
||||
|
||||
gradient (seed_t);
|
||||
gradient ();
|
||||
|
||||
virtual range<T> bounds (void) const final;
|
||||
virtual T operator() (util::point<2,T>) const final;
|
||||
};
|
||||
|
||||
|
||||
/// Cellular/Worley/Vornoi of order-1
|
||||
template <typename T>
|
||||
struct cellular : public basis<T> {
|
||||
using seed_t = typename basis<T>::seed_t;
|
||||
|
||||
cellular (seed_t);
|
||||
cellular ();
|
||||
|
||||
virtual range<T> bounds (void) const final;
|
||||
virtual T operator() (util::point<2,T>) const final;
|
||||
};
|
||||
typedef uint64_t seed_t;
|
||||
} }
|
||||
|
||||
#endif
|
||||
|
118
noise/basis/perlin.cpp
Normal file
118
noise/basis/perlin.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 2012-2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "perlin.hpp"
|
||||
|
||||
#include "../../hash/murmur/murmur2.hpp"
|
||||
|
||||
using util::noise::basis::perlin;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
util::vector<2,T>
|
||||
generate (util::point<2,T> p, uint64_t seed)
|
||||
{
|
||||
using util::hash::murmur2::mix;
|
||||
|
||||
auto u = mix (seed, mix (uint64_t (p.x), uint64_t (p.y)));
|
||||
auto v = mix (u, seed);
|
||||
|
||||
auto r = util::vector<2,T> {
|
||||
(u & 0xffff) / T{0xffff},
|
||||
(v & 0xffff) / T{0xffff}
|
||||
} * 2 - 1;
|
||||
|
||||
CHECK_GE (r, T{-1});
|
||||
CHECK_LE (r, T{ 1});
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
perlin<T,L>::perlin (seed_t _seed):
|
||||
seed (_seed)
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
perlin<T,L>::perlin ():
|
||||
seed (time (nullptr))
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
util::range<T>
|
||||
perlin<T,L>::bounds (void) const
|
||||
{
|
||||
return {
|
||||
-std::sqrt (T{2}) / 2,
|
||||
std::sqrt (T{2}) / 2
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
T
|
||||
perlin<T,L>::operator() (util::point<2,T> p) const
|
||||
{
|
||||
auto p_int = p.template cast<intmax_t> ();
|
||||
auto p_rem = p - p_int;
|
||||
|
||||
// Shift the coordinate system down a little to ensure we get unit weights
|
||||
// for the lerp. It's better to do this than abs the fractional portion so
|
||||
// we don't get reflections along the origin.
|
||||
if (p.x < 0) { p_rem.x = 1 + p_rem.x; p_int.x -= 1; }
|
||||
if (p.y < 0) { p_rem.y = 1 + p_rem.y; p_int.y -= 1; }
|
||||
|
||||
// Generate the four corner values. It's not strictly necessary to
|
||||
// normalise the values, but we get a more consistent and visually
|
||||
// appealing range of outputs with normalised values.
|
||||
auto p0 = generate<T> (p_int + util::vector<2,T> { 0, 0 }, this->seed).normalise ();
|
||||
auto p1 = generate<T> (p_int + util::vector<2,T> { 1, 0 }, this->seed).normalise ();
|
||||
auto p2 = generate<T> (p_int + util::vector<2,T> { 0, 1 }, this->seed).normalise ();
|
||||
auto p3 = generate<T> (p_int + util::vector<2,T> { 1, 1 }, this->seed).normalise ();
|
||||
|
||||
T v0 = p0.x * p_rem.x + p0.y * p_rem.y;
|
||||
T v1 = p1.x * (p_rem.x - 1) + p1.y * p_rem.y;
|
||||
T v2 = p2.x * p_rem.x + p2.y * (p_rem.y - 1);
|
||||
T v3 = p3.x * (p_rem.x - 1) + p3.y * (p_rem.y - 1);
|
||||
|
||||
auto L0 = L (v0, v1, p_rem.x);
|
||||
auto L1 = L (v2, v3, p_rem.x);
|
||||
auto L_ = L (L0, L1, p_rem.y);
|
||||
return L_;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include "../lerp.hpp"
|
||||
|
||||
namespace util { namespace noise { namespace basis {
|
||||
template struct perlin<float, lerp::linear>;
|
||||
template struct perlin<float, lerp::cubic>;
|
||||
template struct perlin<float, lerp::quintic>;
|
||||
|
||||
template struct perlin<double, lerp::linear>;
|
||||
template struct perlin<double, lerp::cubic>;
|
||||
template struct perlin<double, lerp::quintic>;
|
||||
} } }
|
39
noise/basis/perlin.hpp
Normal file
39
noise/basis/perlin.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 2012-2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UTIL_NOISE_BASIS_PERLIN_HPP
|
||||
#define __UTIL_NOISE_BASIS_PERLIN_HPP
|
||||
|
||||
#include "../basis.hpp"
|
||||
#include "../../point.hpp"
|
||||
#include "../../range.hpp"
|
||||
|
||||
namespace util { namespace noise { namespace basis {
|
||||
/// Perlin: interpolated value across each grid space
|
||||
template <typename T, lerp_t<T> L>
|
||||
struct perlin {
|
||||
perlin (seed_t);
|
||||
perlin ();
|
||||
|
||||
range<T> bounds (void) const;
|
||||
T operator() (util::point<2,T>) const;
|
||||
|
||||
seed_t seed;
|
||||
};
|
||||
} } }
|
||||
|
||||
#endif
|
105
noise/basis/value.cpp
Normal file
105
noise/basis/value.cpp
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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 2012-2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "value.hpp"
|
||||
|
||||
#include "../../hash/murmur/murmur2.hpp"
|
||||
|
||||
using util::noise::basis::value;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Generate a type from [-UNIT..UNIT]
|
||||
template <typename T>
|
||||
T
|
||||
generate (util::point<2,T> p, uint64_t seed)
|
||||
{
|
||||
using util::hash::murmur2::mix;
|
||||
|
||||
T v = mix (seed, mix (uint64_t (p.y), uint64_t (p.x))) & 0xffff;
|
||||
v = v / T{0xffff} * 2 - 1;
|
||||
|
||||
CHECK_GE (v, T{0});
|
||||
CHECK_LE (v, T{1});
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
value<T,L>::value (seed_t _seed):
|
||||
seed (_seed)
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
value<T,L>::value ():
|
||||
seed (time (nullptr))
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
util::range<T>
|
||||
value<T,L>::bounds (void) const
|
||||
{
|
||||
return { -1, 1 };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T, util::noise::lerp_t<T> L>
|
||||
T
|
||||
value<T,L>::operator() (util::point<2,T> p) const
|
||||
{
|
||||
auto p_int = p.template cast<intmax_t> ();
|
||||
auto p_rem = p - p_int;
|
||||
|
||||
// Shift the coordinate system down a little to ensure we get unit weights
|
||||
// for the lerp. It's better to do this than abs the fractional portion so
|
||||
// we don't get reflections along the origin.
|
||||
if (p.x < 0) { p_rem.x = 1 + p_rem.x; p_int.x -= 1; }
|
||||
if (p.y < 0) { p_rem.y = 1 + p_rem.y; p_int.y -= 1; }
|
||||
|
||||
// Generate the four corner values
|
||||
T p0 = generate<T> (p_int + util::vector<2,T>{ 0, 0 }, this->seed);
|
||||
T p1 = generate<T> (p_int + util::vector<2,T>{ 1, 0 }, this->seed);
|
||||
T p2 = generate<T> (p_int + util::vector<2,T>{ 0, 0 }, this->seed);
|
||||
T p3 = generate<T> (p_int + util::vector<2,T>{ 1, 1 }, this->seed);
|
||||
|
||||
// Interpolate on one dimension, then the other.
|
||||
return L (L (p0, p1, p_rem.x),
|
||||
L (p2, p3, p_rem.x),
|
||||
p_rem.y);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include "../lerp.hpp"
|
||||
|
||||
namespace util { namespace noise { namespace basis {
|
||||
template struct value<float, lerp::trunc>;
|
||||
template struct value<float, lerp::linear>;
|
||||
template struct value<float, lerp::cubic>;
|
||||
template struct value<float, lerp::quintic>;
|
||||
|
||||
template struct value<double, lerp::trunc>;
|
||||
template struct value<double, lerp::linear>;
|
||||
template struct value<double, lerp::cubic>;
|
||||
template struct value<double, lerp::quintic>;
|
||||
} } }
|
39
noise/basis/value.hpp
Normal file
39
noise/basis/value.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 2012-2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UTIL_NOISE_BASIS_VALUE_HPP
|
||||
#define __UTIL_NOISE_BASIS_VALUE_HPP
|
||||
|
||||
#include "../basis.hpp"
|
||||
#include "../../range.hpp"
|
||||
#include "../../point.hpp"
|
||||
|
||||
namespace util { namespace noise { namespace basis {
|
||||
/// Single value per grid space
|
||||
template <typename T, lerp_t<T>>
|
||||
struct value {
|
||||
value (seed_t);
|
||||
value ();
|
||||
|
||||
range<T> bounds (void) const;
|
||||
T operator() (util::point<2,T>) const;
|
||||
|
||||
seed_t seed;
|
||||
};
|
||||
} } }
|
||||
|
||||
#endif
|
121
noise/basis/worley.cpp
Normal file
121
noise/basis/worley.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 2012-2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "worley.hpp"
|
||||
|
||||
#include "../../hash/murmur/murmur2.hpp"
|
||||
|
||||
using util::noise::basis::worley;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
util::vector<2,T>
|
||||
generate (util::point<2,T> p, uint64_t seed)
|
||||
{
|
||||
using util::hash::murmur2::mix;
|
||||
|
||||
auto u = mix (seed, mix (uint64_t (p.x), uint64_t (p.y)));
|
||||
auto v = mix (u, seed);
|
||||
|
||||
auto r = util::vector<2,T> {
|
||||
(u & 0xffff) / T{0xffff},
|
||||
(v & 0xffff) / T{0xffff}
|
||||
} * 2 - 1;
|
||||
|
||||
CHECK_GE (r, T{-1});
|
||||
CHECK_LE (r, T{ 1});
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
worley<T>::worley (seed_t _seed):
|
||||
seed (_seed)
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
worley<T>::worley ():
|
||||
seed (time (nullptr))
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
util::range<T>
|
||||
worley<T>::bounds (void) const
|
||||
{
|
||||
return { 0.0, 1.5 };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
T
|
||||
worley<T>::operator() (util::point<2,T> p) const
|
||||
{
|
||||
auto p_int = p.template cast<intmax_t> ();
|
||||
auto p_rem = p - p_int;
|
||||
|
||||
// Generate the four corner values. It's not strictly necessary to
|
||||
// normalise the values, but we get a more consistent and visually
|
||||
// appealing range of outputs with normalised values.
|
||||
if (p.x < 0) { p_rem.x = 1 + p_rem.x; p_int.x -= 1; }
|
||||
if (p.y < 0) { p_rem.y = 1 + p_rem.y; p_int.y -= 1; }
|
||||
|
||||
// +---+---+---+
|
||||
// | 0 | 1 | 2 |
|
||||
// +---+---+---+
|
||||
// | 3 | 4 | 5 |
|
||||
// +---+-------+
|
||||
// | 6 | 7 | 8 |
|
||||
// +---+---+---+
|
||||
|
||||
T distances[9] = { std::numeric_limits<T>::quiet_NaN () };
|
||||
T *cursor = distances;
|
||||
|
||||
for (signed y_off = -1; y_off <= 1 ; ++y_off)
|
||||
for (signed x_off = -1; x_off <= 1; ++x_off) {
|
||||
auto pos = vector<2,T> (T (x_off), T (y_off));
|
||||
auto off = generate<T> (p_int + pos, this->seed);
|
||||
off += T{1};
|
||||
off /= T{2};
|
||||
|
||||
CHECK (off.x >= 0 && off.x <= 1);
|
||||
CHECK (off.y >= 0 && off.y <= 1);
|
||||
|
||||
pos += off;
|
||||
*cursor++ = pos.difference2 (p_rem);
|
||||
}
|
||||
|
||||
std::sort (std::begin (distances), std::end (distances));
|
||||
CHECK_GE (distances[0], 0);
|
||||
CHECK (bounds ().contains (distances[0]));
|
||||
return distances[0];
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#include "../lerp.hpp"
|
||||
|
||||
namespace util { namespace noise { namespace basis {
|
||||
template struct worley<float>;
|
||||
template struct worley<double>;
|
||||
} } }
|
37
noise/basis/worley.hpp
Normal file
37
noise/basis/worley.hpp
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 2012-2015 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __UTIL_NOISE_BASIS_WORLEY_HPP
|
||||
#define __UTIL_NOISE_BASIS_WORLEY_HPP
|
||||
|
||||
#include "../basis.hpp"
|
||||
#include "../../point.hpp"
|
||||
#include "../../range.hpp"
|
||||
|
||||
namespace util { namespace noise { namespace basis {
|
||||
template <typename T>
|
||||
struct worley {
|
||||
worley (seed_t);
|
||||
worley ();
|
||||
|
||||
range<T> bounds (void) const;
|
||||
T operator() (util::point<2,T>) const;
|
||||
|
||||
seed_t seed;
|
||||
};
|
||||
} } }
|
||||
#endif
|
@ -14,9 +14,14 @@
|
||||
* Copyright 2012 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#include "noise/fractal.hpp"
|
||||
#include "fractal.hpp"
|
||||
|
||||
#include "debug.hpp"
|
||||
#include "basis/value.hpp"
|
||||
#include "basis/perlin.hpp"
|
||||
#include "basis/worley.hpp"
|
||||
#include "lerp.hpp"
|
||||
|
||||
#include "../debug.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@ -119,19 +124,19 @@ fbm<T,B>::operator() (util::point<2,T> p) const {
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template struct util::noise::fbm<float, util::noise::cellular<float>>;
|
||||
template struct util::noise::fbm<float, util::noise::gradient<float,util::lerp::linear>>;
|
||||
template struct util::noise::fbm<float, util::noise::gradient<float,util::lerp::quintic>>;
|
||||
template struct util::noise::fbm<float, util::noise::value<float,util::lerp::trunc>>;
|
||||
template struct util::noise::fbm<float, util::noise::value<float,util::lerp::linear>>;
|
||||
template struct util::noise::fbm<float, util::noise::value<float,util::lerp::quintic>>;
|
||||
template struct util::noise::fbm<float, util::noise::basis::worley<float>>;
|
||||
template struct util::noise::fbm<float, util::noise::basis::perlin<float,util::lerp::linear>>;
|
||||
template struct util::noise::fbm<float, util::noise::basis::perlin<float,util::lerp::quintic>>;
|
||||
template struct util::noise::fbm<float, util::noise::basis::value<float,util::lerp::trunc>>;
|
||||
template struct util::noise::fbm<float, util::noise::basis::value<float,util::lerp::linear>>;
|
||||
template struct util::noise::fbm<float, util::noise::basis::value<float,util::lerp::quintic>>;
|
||||
|
||||
template struct util::noise::fbm<double, util::noise::cellular<double>>;
|
||||
template struct util::noise::fbm<double, util::noise::gradient<double,util::lerp::linear>>;
|
||||
template struct util::noise::fbm<double, util::noise::gradient<double,util::lerp::quintic>>;
|
||||
template struct util::noise::fbm<double, util::noise::value<double,util::lerp::trunc>>;
|
||||
template struct util::noise::fbm<double, util::noise::value<double,util::lerp::linear>>;
|
||||
template struct util::noise::fbm<double, util::noise::value<double,util::lerp::quintic>>;
|
||||
template struct util::noise::fbm<double, util::noise::basis::worley<double>>;
|
||||
template struct util::noise::fbm<double, util::noise::basis::perlin<double,util::lerp::linear>>;
|
||||
template struct util::noise::fbm<double, util::noise::basis::perlin<double,util::lerp::quintic>>;
|
||||
template struct util::noise::fbm<double, util::noise::basis::value<double,util::lerp::trunc>>;
|
||||
template struct util::noise::fbm<double, util::noise::basis::value<double,util::lerp::linear>>;
|
||||
template struct util::noise::fbm<double, util::noise::basis::value<double,util::lerp::quintic>>;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -208,17 +213,17 @@ rmf<T,B>::operator() (util::point<2,T> p) const {
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template struct util::noise::rmf<float, util::noise::cellular<float>>;
|
||||
template struct util::noise::rmf<float, util::noise::gradient<float,util::lerp::linear>>;
|
||||
template struct util::noise::rmf<float, util::noise::gradient<float,util::lerp::quintic>>;
|
||||
template struct util::noise::rmf<float, util::noise::value<float,util::lerp::linear>>;
|
||||
template struct util::noise::rmf<float, util::noise::value<float,util::lerp::quintic>>;
|
||||
template struct util::noise::rmf<float, util::noise::basis::worley<float>>;
|
||||
template struct util::noise::rmf<float, util::noise::basis::perlin<float,util::lerp::linear>>;
|
||||
template struct util::noise::rmf<float, util::noise::basis::perlin<float,util::lerp::quintic>>;
|
||||
template struct util::noise::rmf<float, util::noise::basis::value<float,util::lerp::linear>>;
|
||||
template struct util::noise::rmf<float, util::noise::basis::value<float,util::lerp::quintic>>;
|
||||
|
||||
template struct util::noise::rmf<double, util::noise::cellular<double>>;
|
||||
template struct util::noise::rmf<double, util::noise::gradient<double,util::lerp::linear>>;
|
||||
template struct util::noise::rmf<double, util::noise::gradient<double,util::lerp::quintic>>;
|
||||
template struct util::noise::rmf<double, util::noise::value<double,util::lerp::linear>>;
|
||||
template struct util::noise::rmf<double, util::noise::value<double,util::lerp::quintic>>;
|
||||
template struct util::noise::rmf<double, util::noise::basis::worley<double>>;
|
||||
template struct util::noise::rmf<double, util::noise::basis::perlin<double,util::lerp::linear>>;
|
||||
template struct util::noise::rmf<double, util::noise::basis::perlin<double,util::lerp::quintic>>;
|
||||
template struct util::noise::rmf<double, util::noise::basis::value<double,util::lerp::linear>>;
|
||||
template struct util::noise::rmf<double, util::noise::basis::value<double,util::lerp::quintic>>;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -264,11 +269,11 @@ hmf<T,B>::operator() (util::point<2,T> p) const
|
||||
}
|
||||
|
||||
|
||||
template struct util::noise::hmf<float, util::noise::cellular<float>>;
|
||||
template struct util::noise::hmf<float, util::noise::gradient<float,util::lerp::linear>>;
|
||||
template struct util::noise::hmf<float, util::noise::gradient<float,util::lerp::quintic>>;
|
||||
template struct util::noise::hmf<float, util::noise::value<float,util::lerp::linear>>;
|
||||
template struct util::noise::hmf<float, util::noise::value<float,util::lerp::quintic>>;
|
||||
template struct util::noise::hmf<float, util::noise::basis::worley<float>>;
|
||||
template struct util::noise::hmf<float, util::noise::basis::perlin<float,util::lerp::linear>>;
|
||||
template struct util::noise::hmf<float, util::noise::basis::perlin<float,util::lerp::quintic>>;
|
||||
template struct util::noise::hmf<float, util::noise::basis::value<float,util::lerp::linear>>;
|
||||
template struct util::noise::hmf<float, util::noise::basis::value<float,util::lerp::quintic>>;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -314,8 +319,8 @@ hetero<T,B>::operator() (util::point<2,T> p) const
|
||||
}
|
||||
|
||||
|
||||
template struct util::noise::hetero<float, util::noise::cellular<float>>;
|
||||
template struct util::noise::hetero<float, util::noise::gradient<float,util::lerp::linear>>;
|
||||
template struct util::noise::hetero<float, util::noise::gradient<float,util::lerp::quintic>>;
|
||||
template struct util::noise::hetero<float, util::noise::value<float,util::lerp::linear>>;
|
||||
template struct util::noise::hetero<float, util::noise::value<float,util::lerp::quintic>>;
|
||||
template struct util::noise::hetero<float, util::noise::basis::worley<float>>;
|
||||
template struct util::noise::hetero<float, util::noise::basis::perlin<float,util::lerp::linear>>;
|
||||
template struct util::noise::hetero<float, util::noise::basis::perlin<float,util::lerp::quintic>>;
|
||||
template struct util::noise::hetero<float, util::noise::basis::value<float,util::lerp::linear>>;
|
||||
template struct util::noise::hetero<float, util::noise::basis::value<float,util::lerp::quintic>>;
|
||||
|
@ -19,13 +19,13 @@
|
||||
|
||||
#include "basis.hpp"
|
||||
|
||||
#include "../point.hpp"
|
||||
|
||||
namespace util {
|
||||
namespace noise {
|
||||
/// Base noise summation
|
||||
template <typename T>
|
||||
struct fractal {
|
||||
using seed_t = uint64_t;
|
||||
|
||||
fractal (seed_t);
|
||||
fractal ();
|
||||
virtual ~fractal ();
|
||||
@ -48,8 +48,6 @@ namespace util {
|
||||
/// gain: per octave amplitude scaling factor. typically 1/f.
|
||||
template <typename T, typename B>
|
||||
struct fbm : public fractal<T> {
|
||||
using seed_t = typename basis<T>::seed_t;
|
||||
|
||||
static constexpr unsigned DEFAULT_OCTAVES = 8;
|
||||
static constexpr T DEFAULT_FREQUENCY = T(0.1);
|
||||
static constexpr T DEFAULT_LACUNARITY = 2;
|
||||
@ -84,8 +82,6 @@ namespace util {
|
||||
/// lacunarity: per octave frequency scaling factor
|
||||
template <typename T, typename B>
|
||||
struct rmf : public fractal<T> {
|
||||
using seed_t = typename basis<T>::seed_t;
|
||||
|
||||
static constexpr unsigned DEFAULT_OCTAVES = 5;
|
||||
static constexpr T DEFAULT_FREQUENCY = T(1);
|
||||
static constexpr T DEFAULT_LACUNARITY = 2;
|
||||
@ -116,8 +112,6 @@ namespace util {
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <typename T, typename B>
|
||||
struct hmf : public fractal<T> {
|
||||
using seed_t = typename basis<T>::seed_t;
|
||||
|
||||
hmf ();
|
||||
|
||||
T H;
|
||||
@ -141,8 +135,6 @@ namespace util {
|
||||
/// Heterogeneous procedural terrain fucntion: stats by altitude method
|
||||
template <typename T, typename B>
|
||||
struct hetero : public fractal<T> {
|
||||
using seed_t = typename basis<T>::seed_t;
|
||||
|
||||
hetero ();
|
||||
|
||||
T H;
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "image.hpp"
|
||||
#include "noise.hpp"
|
||||
#include "noise/lerp.hpp"
|
||||
#include "noise/basis/value.hpp"
|
||||
#include "noise/basis/perlin.hpp"
|
||||
#include "noise/basis/worley.hpp"
|
||||
#include "extent.hpp"
|
||||
|
||||
int
|
||||
@ -11,10 +14,10 @@ main (void)
|
||||
util::image::buffer<float> img (size);
|
||||
|
||||
// setup the noise generator
|
||||
//util::noise::fbm<float, util::noise::cellular<float>> b;
|
||||
//util::noise::rmf<float, util::noise::cellular<float>> b;
|
||||
//util::noise::hmf<float, util::noise::gradient<float,util::lerp::quintic>> b;
|
||||
util::noise::hetero<float, util::noise::gradient<float,util::lerp::quintic>> b;
|
||||
//util::noise::fbm<float, util::noise::basis::worley<float>> b;
|
||||
//util::noise::rmf<float, util::noise::basis::worley<float>> b;
|
||||
//util::noise::hmf<float, util::noise::basis::perlin<float,util::lerp::quintic>> b;
|
||||
util::noise::hetero<float, util::noise::basis::perlin<float,util::lerp::quintic>> b;
|
||||
//b.octaves = 3;
|
||||
b.frequency = 10.f / size.w;
|
||||
b.lacunarity = 2;
|
||||
|
Loading…
Reference in New Issue
Block a user