noise/basis: extract basis into seperate units

This commit is contained in:
Danny Robson 2015-05-28 10:56:06 +10:00
parent c9812f7c78
commit 78f61af84c
12 changed files with 515 additions and 418 deletions

View File

@ -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 \

View File

@ -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>;
} }

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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

View File

@ -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>>;

View File

@ -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;

View File

@ -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;