n/midpoint: extract midpoint displacement funcs
This commit is contained in:
parent
ddf9f0a22a
commit
6b712e2f57
@ -170,6 +170,8 @@ UTIL_FILES = \
|
|||||||
noise/lerp.hpp \
|
noise/lerp.hpp \
|
||||||
noise/lut.cpp \
|
noise/lut.cpp \
|
||||||
noise/lut.hpp \
|
noise/lut.hpp \
|
||||||
|
noise/midpoint.cpp \
|
||||||
|
noise/midpoint.hpp \
|
||||||
noise/turbulence.hpp \
|
noise/turbulence.hpp \
|
||||||
noise/turbulence.ipp \
|
noise/turbulence.ipp \
|
||||||
pascal.cpp \
|
pascal.cpp \
|
||||||
|
132
noise/midpoint.cpp
Normal file
132
noise/midpoint.cpp
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* 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>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "midpoint.hpp"
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// assumes corner points have been assigned their weights
|
||||||
|
template <typename T>
|
||||||
|
static void
|
||||||
|
fill (util::image::buffer<T> &img,
|
||||||
|
uint64_t seed,
|
||||||
|
util::region2u target,
|
||||||
|
float scale,
|
||||||
|
float persistence,
|
||||||
|
float sides)
|
||||||
|
{
|
||||||
|
CHECK_EQ (target.e.w % 2, 1);
|
||||||
|
CHECK_EQ (target.e.h % 2, 1);
|
||||||
|
CHECK_GE (target.area (), 9);
|
||||||
|
|
||||||
|
CHECK_GT (scale, 0);
|
||||||
|
CHECK_GT (persistence, 0);
|
||||||
|
CHECK_GE (sides, 0);
|
||||||
|
|
||||||
|
const auto w = target.w;
|
||||||
|
const auto h = target.h;
|
||||||
|
|
||||||
|
// 0--1
|
||||||
|
// | |
|
||||||
|
// 2--3
|
||||||
|
|
||||||
|
const auto p0 = target.p + util::vector2u {0, 0 };
|
||||||
|
const auto p1 = target.p + util::vector2u {w-1, 0 };
|
||||||
|
const auto p2 = target.p + util::vector2u {0, h-1};
|
||||||
|
const auto p3 = target.p + util::vector2u {w-1, h-1};
|
||||||
|
|
||||||
|
const auto v0 = img[p0];
|
||||||
|
const auto v1 = img[p1];
|
||||||
|
const auto v2 = img[p2];
|
||||||
|
const auto v3 = img[p3];
|
||||||
|
|
||||||
|
// do the centre
|
||||||
|
{
|
||||||
|
const auto avg = (v0 + v1 + v2 + v3) / 4;
|
||||||
|
const auto val = avg + scale * gen<T> (seed, target.centre ());
|
||||||
|
const auto pos = target.p + target.e / 2;
|
||||||
|
|
||||||
|
img[pos] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// average the sides
|
||||||
|
{
|
||||||
|
const auto p01 = target.p + util::vector2u{w/2, 0};
|
||||||
|
const auto p13 = target.p + util::vector2u{w-1, h/2};
|
||||||
|
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);
|
||||||
|
|
||||||
|
img[p01] = v01;
|
||||||
|
img[p13] = v13;
|
||||||
|
img[p32] = v32;
|
||||||
|
img[p20] = v20;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recurse
|
||||||
|
if (target.area () > 9) {
|
||||||
|
auto e = target.e / 2 + 1;
|
||||||
|
|
||||||
|
fill (img, seed, {target.p + util::vector2u{ 0, 0 }, e}, scale * persistence, persistence, sides);
|
||||||
|
fill (img, seed, {target.p + util::vector2u{ w/2, 0 }, e}, scale * persistence, persistence, sides);
|
||||||
|
fill (img, seed, {target.p + util::vector2u{ 0, h/2 }, e}, scale * persistence, persistence, sides);
|
||||||
|
fill (img, seed, {target.p + util::vector2u{ w/2, h/2 }, e}, scale * persistence, persistence, sides);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
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 });
|
||||||
|
|
||||||
|
fill (img, seed, { { 0, 0 }, img.extent () }, 1.f, persistence, sides);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template void util::noise::midpoint (image::buffer<float>&, uint64_t, float, float);
|
30
noise/midpoint.hpp
Normal file
30
noise/midpoint.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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_MIDPOINT_HPP
|
||||||
|
#define __UTIL_NOISE_MIDPOINT_HPP
|
||||||
|
|
||||||
|
#include "image.hpp"
|
||||||
|
|
||||||
|
namespace util { namespace noise {
|
||||||
|
template <typename T>
|
||||||
|
void
|
||||||
|
midpoint (image::buffer<T>&, uint64_t seed, float persistence = 0.65f, float sides = 0.25f);
|
||||||
|
} }
|
||||||
|
|
||||||
|
#include "midpoint.ipp"
|
||||||
|
|
||||||
|
#endif
|
124
tools/noise.cpp
124
tools/noise.cpp
@ -13,15 +13,14 @@
|
|||||||
#include "noise/basis/worley.hpp"
|
#include "noise/basis/worley.hpp"
|
||||||
#include "noise/turbulence.hpp"
|
#include "noise/turbulence.hpp"
|
||||||
#include "noise/basis/runtime.hpp"
|
#include "noise/basis/runtime.hpp"
|
||||||
|
#include "noise/midpoint.hpp"
|
||||||
#include "extent.hpp"
|
#include "extent.hpp"
|
||||||
#include "colour.hpp"
|
#include "colour.hpp"
|
||||||
#include "netpbm.hpp"
|
#include "netpbm.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
#include "cmdopt.hpp"
|
#include "cmdopt.hpp"
|
||||||
#include "hash/murmur/murmur2.hpp"
|
|
||||||
|
|
||||||
#include "region.hpp"
|
#include "region.hpp"
|
||||||
#include "random.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -157,120 +156,29 @@ operator<< (std::ostream &os, lerp_t &l)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
diamond (util::image::buffer<float> &img, util::region2u target, float scale, float persistence)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static float
|
|
||||||
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 / float{0xffff} * 2 - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// perturb the centre point by at most scale-units
|
|
||||||
// average the side points (optionally perturb by sides-units)
|
|
||||||
//
|
|
||||||
void
|
|
||||||
midpoint (util::image::buffer<float> &img, uint64_t seed, util::region2u target, float scale, float persistence, float sides = 0.f)
|
|
||||||
{
|
|
||||||
CHECK_EQ (target.e.w % 2, 1);
|
|
||||||
CHECK_EQ (target.e.h % 2, 1);
|
|
||||||
CHECK_GE (target.area (), 9);
|
|
||||||
|
|
||||||
CHECK_GT (scale, 0);
|
|
||||||
CHECK_GT (persistence, 0);
|
|
||||||
CHECK_GE (sides, 0);
|
|
||||||
|
|
||||||
auto w = target.w;
|
|
||||||
auto h = target.h;
|
|
||||||
|
|
||||||
// 0--1
|
|
||||||
// | |
|
|
||||||
// 2--3
|
|
||||||
|
|
||||||
auto p0 = target.p+util::vector2u{0, 0 };
|
|
||||||
auto p1 = target.p+util::vector2u{w-1,0 };
|
|
||||||
auto p2 = target.p+util::vector2u{0, h-1};
|
|
||||||
auto p3 = target.p+util::vector2u{w-1,h-1};
|
|
||||||
|
|
||||||
auto v0 = img[p0];
|
|
||||||
auto v1 = img[p1];
|
|
||||||
auto v2 = img[p2];
|
|
||||||
auto v3 = img[p3];
|
|
||||||
|
|
||||||
// do the centre
|
|
||||||
auto avg = (v0 + v1 + v2 + v3) / 4;
|
|
||||||
auto val = avg + scale * gen (seed, target.centre ());
|
|
||||||
auto pos = target.p + target.e / 2;
|
|
||||||
|
|
||||||
img[pos] = val;
|
|
||||||
|
|
||||||
// average the sides
|
|
||||||
auto p01 = target.p + util::vector2u{w/2, 0};
|
|
||||||
auto p13 = target.p + util::vector2u{w-1, h/2};
|
|
||||||
auto p32 = target.p + util::vector2u{w/2, h-1};
|
|
||||||
auto p20 = target.p + util::vector2u{0, h/2};
|
|
||||||
|
|
||||||
auto v01 = (v0 + v1) / 2 + sides * scale * gen (seed, p01);
|
|
||||||
auto v13 = (v1 + v3) / 2 + sides * scale * gen (seed, p13);
|
|
||||||
auto v32 = (v3 + v2) / 2 + sides * scale * gen (seed, p32);
|
|
||||||
auto v20 = (v2 + v0) / 2 + sides * scale * gen (seed, p20);
|
|
||||||
|
|
||||||
img[p01] = v01;
|
|
||||||
img[p13] = v13;
|
|
||||||
img[p32] = v32;
|
|
||||||
img[p20] = v20;
|
|
||||||
|
|
||||||
// recurse
|
|
||||||
if (target.area () > 9) {
|
|
||||||
auto e = target.e / 2 + 1;
|
|
||||||
|
|
||||||
midpoint (img, seed, {target.p + util::vector2u{ 0, 0 }, e}, scale * persistence, persistence, sides);
|
|
||||||
midpoint (img, seed, {target.p + util::vector2u{ w/2, 0 }, e}, scale * persistence, persistence, sides);
|
|
||||||
midpoint (img, seed, {target.p + util::vector2u{ 0, h/2 }, e}, scale * persistence, persistence, sides);
|
|
||||||
midpoint (img, seed, {target.p + util::vector2u{ w/2, h/2 }, e}, scale * persistence, persistence, sides);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
int
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
//{
|
#if 0
|
||||||
// util::extent2u size { 1025 };
|
{
|
||||||
// util::image::buffer<float> img (size);
|
srand (time (nullptr));
|
||||||
|
|
||||||
// img[{0, 0}] = 0.7f;
|
util::extent2u size { 1025 };
|
||||||
// img[{0, size.w-1}] = 0.1f;
|
util::image::buffer<float> img (size);
|
||||||
// img[{size.h-1, 0}] = 0.5f;
|
util::noise::midpoint (img, time (nullptr));
|
||||||
// img[{size.h-1, size.w-1}] = 0.2f;
|
|
||||||
// midpoint (img, { {0, 0}, size }, 1, 0.65f);
|
|
||||||
|
|
||||||
// auto range = std::minmax_element (img.begin (), img.end ());
|
auto range = std::minmax_element (img.begin (), img.end ());
|
||||||
// auto offset = *range.first;
|
auto offset = *range.first;
|
||||||
// auto div = *range.second - *range.first;
|
auto div = *range.second - *range.first;
|
||||||
// std::cerr << "range: [" << *range.first << ", " << *range.second << "]\n";
|
std::cerr << "range: [" << *range.first << ", " << *range.second << "]\n";
|
||||||
|
|
||||||
// std::transform (img.begin (), img.end (), img.begin (), [offset,div] (auto i) { return (i - offset) / div; });
|
std::transform (img.begin (), img.end (), img.begin (), [offset,div] (auto i) { return (i - offset) / div; });
|
||||||
// util::pgm::write (img.cast<uint8_t> (), std::cout);
|
util::pgm::write (img.cast<uint8_t> (), std::cout);
|
||||||
//}
|
}
|
||||||
|
|
||||||
//return 0;
|
return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef ENABLE_DEBUGGING
|
#ifndef ENABLE_DEBUGGING
|
||||||
|
Loading…
Reference in New Issue
Block a user