n/rand: add general keyed random facility
This commit is contained in:
parent
6b712e2f57
commit
174281ce20
@ -172,6 +172,8 @@ UTIL_FILES = \
|
|||||||
noise/lut.hpp \
|
noise/lut.hpp \
|
||||||
noise/midpoint.cpp \
|
noise/midpoint.cpp \
|
||||||
noise/midpoint.hpp \
|
noise/midpoint.hpp \
|
||||||
|
noise/rand.hpp \
|
||||||
|
noise/rand.ipp \
|
||||||
noise/turbulence.hpp \
|
noise/turbulence.hpp \
|
||||||
noise/turbulence.ipp \
|
noise/turbulence.ipp \
|
||||||
pascal.cpp \
|
pascal.cpp \
|
||||||
|
@ -35,7 +35,6 @@ namespace util { namespace noise { namespace basis {
|
|||||||
seed_t seed (seed_t);
|
seed_t seed (seed_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vector<2,T> gradient (point<2,intmax_t>) const;
|
|
||||||
seed_t m_seed;
|
seed_t m_seed;
|
||||||
};
|
};
|
||||||
} } }
|
} } }
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#define __UTIL_NOISE_BASIS_PERLIN_IPP
|
#define __UTIL_NOISE_BASIS_PERLIN_IPP
|
||||||
|
|
||||||
#include "../../hash/murmur/murmur2.hpp"
|
#include "../rand.hpp"
|
||||||
|
|
||||||
namespace util { namespace noise { namespace basis {
|
namespace util { namespace noise { namespace basis {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@ -78,10 +78,10 @@ namespace util { namespace noise { namespace basis {
|
|||||||
auto p3 = p_int + util::vector<2,intmax_t> { 1, 1 };
|
auto p3 = p_int + util::vector<2,intmax_t> { 1, 1 };
|
||||||
|
|
||||||
// generate the corner gradients
|
// generate the corner gradients
|
||||||
auto g0 = gradient (p0);
|
auto g0 = noise::rand<2,T> (m_seed, p0);
|
||||||
auto g1 = gradient (p1);
|
auto g1 = noise::rand<2,T> (m_seed, p1);
|
||||||
auto g2 = gradient (p2);
|
auto g2 = noise::rand<2,T> (m_seed, p2);
|
||||||
auto g3 = gradient (p3);
|
auto g3 = noise::rand<2,T> (m_seed, p3);
|
||||||
|
|
||||||
// compute the dot products
|
// compute the dot products
|
||||||
T v0 = dot (g0, p - p0);
|
T v0 = dot (g0, p - p0);
|
||||||
@ -96,25 +96,4 @@ namespace util { namespace noise { namespace basis {
|
|||||||
|
|
||||||
return L_;
|
return L_;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T, lerp_t<T> L>
|
|
||||||
vector<2,T>
|
|
||||||
perlin<T,L>::gradient (point<2,intmax_t> 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::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;
|
|
||||||
}
|
|
||||||
} } }
|
} } }
|
||||||
|
@ -35,8 +35,6 @@ namespace util { namespace noise { namespace basis {
|
|||||||
seed_t seed (seed_t);
|
seed_t seed (seed_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T generate (point<2,intmax_t>) const;
|
|
||||||
|
|
||||||
seed_t m_seed;
|
seed_t m_seed;
|
||||||
};
|
};
|
||||||
} } }
|
} } }
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#define __UTIL_NOISE_BASIS_VALIE_IPP
|
#define __UTIL_NOISE_BASIS_VALIE_IPP
|
||||||
|
|
||||||
#include "../../hash/murmur/murmur2.hpp"
|
#include "../rand.hpp"
|
||||||
|
|
||||||
namespace util { namespace noise { namespace basis {
|
namespace util { namespace noise { namespace basis {
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@ -75,10 +75,10 @@ namespace util { namespace noise { namespace basis {
|
|||||||
auto p3 = p_int + util::vector<2,intmax_t> { 1, 1 };
|
auto p3 = p_int + util::vector<2,intmax_t> { 1, 1 };
|
||||||
|
|
||||||
// Generate the four corner values
|
// Generate the four corner values
|
||||||
T g0 = generate (p0);
|
T g0 = noise::rand<float> (m_seed, p0);
|
||||||
T g1 = generate (p1);
|
T g1 = noise::rand<float> (m_seed, p1);
|
||||||
T g2 = generate (p2);
|
T g2 = noise::rand<float> (m_seed, p2);
|
||||||
T g3 = generate (p3);
|
T g3 = noise::rand<float> (m_seed, p3);
|
||||||
|
|
||||||
// Interpolate on one dimension, then the other.
|
// Interpolate on one dimension, then the other.
|
||||||
auto l0 = L (g0, g1, p_rem.x);
|
auto l0 = L (g0, g1, p_rem.x);
|
||||||
@ -87,25 +87,4 @@ namespace util { namespace noise { namespace basis {
|
|||||||
|
|
||||||
return l_;
|
return l_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
|
||||||
// Generate a type from [-UNIT..UNIT]
|
|
||||||
template <typename T, lerp_t<T> L>
|
|
||||||
T
|
|
||||||
value<T,L>::generate (point<2,intmax_t> p) const
|
|
||||||
{
|
|
||||||
using util::hash::murmur2::mix;
|
|
||||||
|
|
||||||
T v = mix (
|
|
||||||
m_seed,
|
|
||||||
mix (
|
|
||||||
uint64_t (p.y),
|
|
||||||
uint64_t (p.x)
|
|
||||||
)
|
|
||||||
) & 0xffff;
|
|
||||||
|
|
||||||
v = v / T{0xffff} * 2 - 1;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
} } }
|
} } }
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "../../debug.hpp"
|
#include "../../debug.hpp"
|
||||||
#include "../../hash/murmur/murmur2.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace util { namespace noise { namespace basis {
|
namespace util { namespace noise { namespace basis {
|
||||||
|
@ -18,25 +18,7 @@
|
|||||||
|
|
||||||
#include "region.hpp"
|
#include "region.hpp"
|
||||||
#include "point.hpp"
|
#include "point.hpp"
|
||||||
#include "hash/murmur/murmur2.hpp"
|
#include "rand.hpp"
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
static T
|
|
||||||
gen (uint64_t seed, util::point2u p)
|
|
||||||
{
|
|
||||||
using util::hash::murmur2::mix;
|
|
||||||
|
|
||||||
uint64_t v = mix (
|
|
||||||
seed,
|
|
||||||
mix (
|
|
||||||
p.y,
|
|
||||||
p.x
|
|
||||||
)
|
|
||||||
) & 0xffff;
|
|
||||||
|
|
||||||
return v / T{0xffff} * 2 - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -78,7 +60,7 @@ fill (util::image::buffer<T> &img,
|
|||||||
// do the centre
|
// do the centre
|
||||||
{
|
{
|
||||||
const auto avg = (v0 + v1 + v2 + v3) / 4;
|
const auto avg = (v0 + v1 + v2 + v3) / 4;
|
||||||
const auto val = avg + scale * gen<T> (seed, target.centre ());
|
const auto val = avg + scale * util::noise::rand<T> (seed, target.centre ());
|
||||||
const auto pos = target.p + target.e / 2;
|
const auto pos = target.p + target.e / 2;
|
||||||
|
|
||||||
img[pos] = val;
|
img[pos] = val;
|
||||||
@ -91,10 +73,10 @@ fill (util::image::buffer<T> &img,
|
|||||||
const auto p32 = target.p + util::vector2u{w/2, h-1};
|
const auto p32 = target.p + util::vector2u{w/2, h-1};
|
||||||
const auto p20 = target.p + util::vector2u{0, h/2};
|
const auto p20 = target.p + util::vector2u{0, h/2};
|
||||||
|
|
||||||
const auto v01 = (v0 + v1) / 2 + sides * scale * gen<T> (seed, p01);
|
const auto v01 = (v0 + v1) / 2 + sides * scale * util::noise::rand<T> (seed, p01);
|
||||||
const auto v13 = (v1 + v3) / 2 + sides * scale * gen<T> (seed, p13);
|
const auto v13 = (v1 + v3) / 2 + sides * scale * util::noise::rand<T> (seed, p13);
|
||||||
const auto v32 = (v3 + v2) / 2 + sides * scale * gen<T> (seed, p32);
|
const auto v32 = (v3 + v2) / 2 + sides * scale * util::noise::rand<T> (seed, p32);
|
||||||
const auto v20 = (v2 + v0) / 2 + sides * scale * gen<T> (seed, p20);
|
const auto v20 = (v2 + v0) / 2 + sides * scale * util::noise::rand<T> (seed, p20);
|
||||||
|
|
||||||
img[p01] = v01;
|
img[p01] = v01;
|
||||||
img[p13] = v13;
|
img[p13] = v13;
|
||||||
@ -119,10 +101,15 @@ template <typename T>
|
|||||||
void
|
void
|
||||||
util::noise::midpoint (image::buffer<T> &img, uint64_t seed, float persistence, float sides)
|
util::noise::midpoint (image::buffer<T> &img, uint64_t seed, float persistence, float sides)
|
||||||
{
|
{
|
||||||
img[{0, 0}] = gen<T> (seed, { 0, 0 });
|
static const util::point2u CORNERS[] = {
|
||||||
img[{0, img.w-1}] = gen<T> (seed, { 0, img.w-1 });
|
{ 0, 0 },
|
||||||
img[{img.h-1, 0}] = gen<T> (seed, { img.h-1, 0 });
|
{ 0, img.w - 1 },
|
||||||
img[{img.h-1, img.w-1}] = gen<T> (seed, { img.h-1, img.w-1 });
|
{ img.h - 1, 0 },
|
||||||
|
{ img.h - 1, img.w - 1 }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto i: CORNERS)
|
||||||
|
img[i] = util::noise::rand<T> (seed, i);
|
||||||
|
|
||||||
fill (img, seed, { { 0, 0 }, img.extent () }, 1.f, persistence, sides);
|
fill (img, seed, { { 0, 0 }, img.extent () }, 1.f, persistence, sides);
|
||||||
}
|
}
|
||||||
|
33
noise/rand.hpp
Normal file
33
noise/rand.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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_RAND_HPP
|
||||||
|
#define __UTIL_NOISE_RAND_HPP
|
||||||
|
|
||||||
|
namespace util { namespace noise {
|
||||||
|
/// generate a uniform random floating point in the range [-1, 1] from a seed and vector
|
||||||
|
template <typename T, typename V>
|
||||||
|
T
|
||||||
|
rand (uint64_t seed, V value);
|
||||||
|
|
||||||
|
template <size_t N, typename T, typename V>
|
||||||
|
vector<N,T>
|
||||||
|
rand (uint64_t seed, V value);
|
||||||
|
} }
|
||||||
|
|
||||||
|
#include "rand.ipp"
|
||||||
|
|
||||||
|
#endif
|
60
noise/rand.ipp
Normal file
60
noise/rand.ipp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __UTIL_NOISE_RAND_IPP
|
||||||
|
#error
|
||||||
|
#endif
|
||||||
|
#define __UTIL_NOISE_RAND_IPP
|
||||||
|
|
||||||
|
#include "../hash/murmur/murmur2.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace util { namespace noise {
|
||||||
|
template <typename T, typename V>
|
||||||
|
T
|
||||||
|
rand (uint64_t seed, V value)
|
||||||
|
{
|
||||||
|
uint64_t accum = seed;
|
||||||
|
for (auto i: value)
|
||||||
|
accum = hash::murmur2::mix (accum, i);
|
||||||
|
|
||||||
|
T out = (accum & 0xFFFF) / T{0xFFFF};
|
||||||
|
|
||||||
|
out *= 2;
|
||||||
|
out -= 1;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <size_t N, typename T, typename V>
|
||||||
|
vector<N,T>
|
||||||
|
rand (uint64_t seed, V value)
|
||||||
|
{
|
||||||
|
uint64_t accum = seed;
|
||||||
|
for (auto i: value)
|
||||||
|
accum = hash::murmur2::mix (accum, i);
|
||||||
|
|
||||||
|
vector<N,T> out;
|
||||||
|
for (auto &i: out) {
|
||||||
|
i = (accum & 0xFFFF) / T{0xFFFF};
|
||||||
|
accum = hash::murmur2::mix (accum, seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out * 2 - 1;
|
||||||
|
}
|
||||||
|
} }
|
Loading…
Reference in New Issue
Block a user