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/midpoint.cpp \
|
||||
noise/midpoint.hpp \
|
||||
noise/rand.hpp \
|
||||
noise/rand.ipp \
|
||||
noise/turbulence.hpp \
|
||||
noise/turbulence.ipp \
|
||||
pascal.cpp \
|
||||
|
@ -35,7 +35,6 @@ namespace util { namespace noise { namespace basis {
|
||||
seed_t seed (seed_t);
|
||||
|
||||
private:
|
||||
vector<2,T> gradient (point<2,intmax_t>) const;
|
||||
seed_t m_seed;
|
||||
};
|
||||
} } }
|
||||
|
@ -19,7 +19,7 @@
|
||||
#endif
|
||||
#define __UTIL_NOISE_BASIS_PERLIN_IPP
|
||||
|
||||
#include "../../hash/murmur/murmur2.hpp"
|
||||
#include "../rand.hpp"
|
||||
|
||||
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 };
|
||||
|
||||
// generate the corner gradients
|
||||
auto g0 = gradient (p0);
|
||||
auto g1 = gradient (p1);
|
||||
auto g2 = gradient (p2);
|
||||
auto g3 = gradient (p3);
|
||||
auto g0 = noise::rand<2,T> (m_seed, p0);
|
||||
auto g1 = noise::rand<2,T> (m_seed, p1);
|
||||
auto g2 = noise::rand<2,T> (m_seed, p2);
|
||||
auto g3 = noise::rand<2,T> (m_seed, p3);
|
||||
|
||||
// compute the dot products
|
||||
T v0 = dot (g0, p - p0);
|
||||
@ -96,25 +96,4 @@ namespace util { namespace noise { namespace basis {
|
||||
|
||||
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);
|
||||
|
||||
private:
|
||||
T generate (point<2,intmax_t>) const;
|
||||
|
||||
seed_t m_seed;
|
||||
};
|
||||
} } }
|
||||
|
@ -19,7 +19,7 @@
|
||||
#endif
|
||||
#define __UTIL_NOISE_BASIS_VALIE_IPP
|
||||
|
||||
#include "../../hash/murmur/murmur2.hpp"
|
||||
#include "../rand.hpp"
|
||||
|
||||
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 };
|
||||
|
||||
// Generate the four corner values
|
||||
T g0 = generate (p0);
|
||||
T g1 = generate (p1);
|
||||
T g2 = generate (p2);
|
||||
T g3 = generate (p3);
|
||||
T g0 = noise::rand<float> (m_seed, p0);
|
||||
T g1 = noise::rand<float> (m_seed, p1);
|
||||
T g2 = noise::rand<float> (m_seed, p2);
|
||||
T g3 = noise::rand<float> (m_seed, p3);
|
||||
|
||||
// Interpolate on one dimension, then the other.
|
||||
auto l0 = L (g0, g1, p_rem.x);
|
||||
@ -87,25 +87,4 @@ namespace util { namespace noise { namespace basis {
|
||||
|
||||
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 "../../hash/murmur/murmur2.hpp"
|
||||
|
||||
|
||||
namespace util { namespace noise { namespace basis {
|
||||
|
@ -18,25 +18,7 @@
|
||||
|
||||
#include "region.hpp"
|
||||
#include "point.hpp"
|
||||
#include "hash/murmur/murmur2.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;
|
||||
}
|
||||
#include "rand.hpp"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -78,7 +60,7 @@ fill (util::image::buffer<T> &img,
|
||||
// do the centre
|
||||
{
|
||||
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;
|
||||
|
||||
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 p20 = target.p + util::vector2u{0, h/2};
|
||||
|
||||
const auto v01 = (v0 + v1) / 2 + sides * scale * gen<T> (seed, p01);
|
||||
const auto v13 = (v1 + v3) / 2 + sides * scale * gen<T> (seed, p13);
|
||||
const auto v32 = (v3 + v2) / 2 + sides * scale * gen<T> (seed, p32);
|
||||
const auto v20 = (v2 + v0) / 2 + sides * scale * gen<T> (seed, p20);
|
||||
const auto v01 = (v0 + v1) / 2 + sides * scale * util::noise::rand<T> (seed, p01);
|
||||
const auto v13 = (v1 + v3) / 2 + sides * scale * util::noise::rand<T> (seed, p13);
|
||||
const auto v32 = (v3 + v2) / 2 + sides * scale * util::noise::rand<T> (seed, p32);
|
||||
const auto v20 = (v2 + v0) / 2 + sides * scale * util::noise::rand<T> (seed, p20);
|
||||
|
||||
img[p01] = v01;
|
||||
img[p13] = v13;
|
||||
@ -119,10 +101,15 @@ template <typename T>
|
||||
void
|
||||
util::noise::midpoint (image::buffer<T> &img, uint64_t seed, float persistence, float sides)
|
||||
{
|
||||
img[{0, 0}] = gen<T> (seed, { 0, 0 });
|
||||
img[{0, img.w-1}] = gen<T> (seed, { 0, img.w-1 });
|
||||
img[{img.h-1, 0}] = gen<T> (seed, { img.h-1, 0 });
|
||||
img[{img.h-1, img.w-1}] = gen<T> (seed, { img.h-1, img.w-1 });
|
||||
static const util::point2u CORNERS[] = {
|
||||
{ 0, 0 },
|
||||
{ 0, 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);
|
||||
}
|
||||
|
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