2015-05-18 14:11:08 +10:00
|
|
|
#include "image.hpp"
|
|
|
|
#include "noise.hpp"
|
2015-06-01 16:20:50 +10:00
|
|
|
|
|
|
|
#include "noise/fractal/fbm.hpp"
|
|
|
|
#include "noise/fractal/rmf.hpp"
|
|
|
|
#include "noise/fractal/hmf.hpp"
|
|
|
|
#include "noise/fractal/hetero.hpp"
|
2015-05-18 14:42:28 +10:00
|
|
|
#include "noise/lerp.hpp"
|
2015-05-29 15:55:36 +10:00
|
|
|
#include "noise/basis/constant.hpp"
|
2015-05-28 10:56:06 +10:00
|
|
|
#include "noise/basis/value.hpp"
|
|
|
|
#include "noise/basis/perlin.hpp"
|
|
|
|
#include "noise/basis/worley.hpp"
|
2015-06-02 20:31:25 +10:00
|
|
|
#include "noise/turbulence.hpp"
|
2015-05-26 16:37:41 +10:00
|
|
|
#include "extent.hpp"
|
2015-06-02 23:00:12 +10:00
|
|
|
#include "colour.hpp"
|
2015-06-03 23:24:26 +10:00
|
|
|
#include "netpbm.hpp"
|
2015-06-04 14:40:47 +10:00
|
|
|
#include "types.hpp"
|
2015-06-01 18:57:00 +10:00
|
|
|
|
|
|
|
template struct util::noise::fractal::fbm<float, util::noise::basis::perlin<float,util::lerp::cubic>>;
|
|
|
|
template struct util::noise::fractal::hmf<float, util::noise::basis::value<float,util::lerp::cubic>>;
|
|
|
|
template struct util::noise::fractal::rmf<float, util::noise::basis::constant<float>>;
|
|
|
|
template struct util::noise::fractal::hetero<float, util::noise::basis::worley<float,2>>;
|
|
|
|
|
2015-06-04 14:40:47 +10:00
|
|
|
|
|
|
|
// create a coloured map with this gradient (from libnoise tut3)
|
|
|
|
static const struct {
|
|
|
|
float scale;
|
|
|
|
util::colour3u value;
|
|
|
|
} GRADPOINT[] = {
|
|
|
|
{-1000000.f, { 0, 0, 128 } },
|
|
|
|
{ 0 / 32.f, { 0, 0, 128 } }, // deeps
|
|
|
|
{ 12 / 32.f, { 0, 0, 255 } }, // shallow
|
|
|
|
{ 16 / 32.f, { 0, 128, 255 } }, // shore
|
|
|
|
{ 17 / 32.f, { 240, 240, 64 } }, // sand
|
|
|
|
{ 18 / 32.f, { 32, 160, 0 } }, // grass
|
|
|
|
{ 22 / 32.f, { 224, 224, 0 } }, // dirt
|
|
|
|
{ 28 / 32.f, { 128, 128, 128 } }, // rock
|
|
|
|
{ 32 / 32.f, { 255, 255, 255 } }, // snow
|
|
|
|
{ 1000000.f, { 255, 255, 255 } },
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
write_map (const util::image::buffer<float> &map, boost::filesystem::path name)
|
|
|
|
{
|
|
|
|
std::unique_ptr<uint8_t[]> coloured (new uint8_t[map.w * map.h * 3]);
|
|
|
|
for (size_t i = 0; i < map.w * map.h; ++i) {
|
|
|
|
auto v = map[i] + 0/32.f;
|
|
|
|
auto c1 = std::upper_bound (std::begin (GRADPOINT),
|
|
|
|
std::end (GRADPOINT),
|
|
|
|
v,
|
|
|
|
[] (auto a, auto b) { return a < b.scale; });
|
|
|
|
auto c0 = c1-1;
|
|
|
|
|
|
|
|
CHECK_GE (v, c0->scale);
|
|
|
|
CHECK_LT (v, c1->scale);
|
|
|
|
float t = (v - c0->scale) / (c1->scale - c0->scale);
|
|
|
|
CHECK_LIMIT (t, 0, 1);
|
|
|
|
auto c = (
|
|
|
|
(1 - t) * c0->value.template cast<float> () +
|
|
|
|
( t) * c1->value.template cast<float> ()
|
|
|
|
).template cast<uint8_t> ();
|
|
|
|
|
|
|
|
coloured[i*3+0] = c[0];
|
|
|
|
coloured[i*3+1] = c[1];
|
|
|
|
coloured[i*3+2] = c[2];
|
|
|
|
}
|
|
|
|
|
|
|
|
name.replace_extension (".ppm");
|
|
|
|
util::ppm::write (coloured.get (), map.w, map.h, map.w*3, name);
|
|
|
|
|
|
|
|
// write the image to disk
|
|
|
|
auto grey = map.clone<uint8_t> ();
|
|
|
|
name.replace_extension (".pgm");
|
|
|
|
util::pgm::write (grey, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-18 14:11:08 +10:00
|
|
|
int
|
|
|
|
main (void)
|
|
|
|
{
|
2015-05-26 16:37:41 +10:00
|
|
|
// setup the output buffer
|
2015-06-03 23:24:26 +10:00
|
|
|
#ifdef ENABLE_DEBUGGING
|
2015-06-03 17:37:42 +10:00
|
|
|
util::extent2u size {320, 240};
|
|
|
|
#else
|
2015-06-01 17:21:51 +10:00
|
|
|
util::extent2u size {1920, 1080};
|
2015-06-03 17:37:42 +10:00
|
|
|
#endif
|
2015-05-26 16:37:41 +10:00
|
|
|
util::image::buffer<float> img (size);
|
2015-05-18 14:11:08 +10:00
|
|
|
|
2015-06-02 16:13:12 +10:00
|
|
|
uint64_t seed = time (nullptr);
|
|
|
|
|
2015-05-26 16:37:41 +10:00
|
|
|
// setup the noise generator
|
2015-06-02 20:31:25 +10:00
|
|
|
#if 0
|
2015-06-02 17:07:42 +10:00
|
|
|
//util::noise::fractal::fbm<float, util::noise::basis::worley<float>> b (seed);
|
2015-06-02 16:13:12 +10:00
|
|
|
//util::noise::fractal::rmf<float, util::noise::basis::worley<float>> b (seed);
|
|
|
|
//util::noise::fractal::fbm<float, util::noise::basis::perlin<float,util::lerp::cubic>> b (seed);
|
|
|
|
//util::noise::fractal::rmf<float, util::noise::basis::perlin<float,util::lerp::cubic>> b (seed);
|
|
|
|
//util::noise::fractal::hmf<float, util::noise::basis::perlin<float,util::lerp::cubic>> b (seed);
|
2015-06-02 17:07:42 +10:00
|
|
|
util::noise::fractal::hetero<float, util::noise::basis::value<float,util::lerp::quintic>> b (seed);
|
2015-06-01 16:20:50 +10:00
|
|
|
|
2015-06-02 16:13:12 +10:00
|
|
|
b.octaves (8);
|
|
|
|
b.frequency (10.f / size.w);
|
2015-06-02 20:31:25 +10:00
|
|
|
b.lacunarity = 2.f;
|
|
|
|
b.H = 1.0f;
|
2015-06-02 17:07:42 +10:00
|
|
|
b.seed (seed);
|
2015-06-02 20:31:25 +10:00
|
|
|
#else
|
|
|
|
util::noise::turbulence<
|
|
|
|
float,
|
2015-06-02 23:00:12 +10:00
|
|
|
//util::noise::fractal::hetero<float, util::noise::basis::worley<float>>,
|
2015-06-02 20:31:25 +10:00
|
|
|
util::noise::fractal::hetero<float, util::noise::basis::perlin<float,util::lerp::cubic>>,
|
|
|
|
util::noise::fractal::fbm<float, util::noise::basis::perlin<float,util::lerp::quintic>>
|
|
|
|
> b (seed, { 0.13f, 0.13f });
|
|
|
|
|
2015-06-03 17:36:33 +10:00
|
|
|
b.data.frequency (1.f / size.w);
|
2015-06-02 20:31:25 +10:00
|
|
|
b.perturb[0].octaves (4);
|
|
|
|
b.perturb[1].octaves (4);
|
|
|
|
b.perturb[0].frequency (10.f / size.w);
|
|
|
|
b.perturb[1].frequency (10.f / size.w);
|
|
|
|
#endif
|
2015-05-18 14:11:08 +10:00
|
|
|
|
2015-06-02 23:00:12 +10:00
|
|
|
// generate the values. offset positions slightly to observe simple axis issues with perlin basis
|
2015-05-29 15:55:36 +10:00
|
|
|
{
|
|
|
|
auto offset = util::vector2f { -100 };
|
|
|
|
|
|
|
|
for (size_t y = 0; y < size.h; ++y)
|
|
|
|
for (size_t x = 0; x < size.w; ++x) {
|
2015-06-01 16:20:50 +10:00
|
|
|
auto v = b (util::point2f {float (x), float (y)} + offset);
|
2015-05-29 15:55:36 +10:00
|
|
|
img.data ()[y * size.w + x] = v;
|
|
|
|
}
|
|
|
|
}
|
2015-05-18 14:11:08 +10:00
|
|
|
|
2015-05-26 16:37:41 +10:00
|
|
|
// rescale into the range [0, 1]
|
|
|
|
auto range = std::minmax_element (img.begin (), img.end ());
|
|
|
|
auto offset = *range.first;
|
|
|
|
auto div = *range.second - *range.first;
|
|
|
|
std::cerr << "range: [" << *range.first << ", " << *range.second << "]\n";
|
|
|
|
|
|
|
|
std::transform (img.begin (), img.end (), img.begin (), [offset,div] (auto i) { return (i - offset) / div; });
|
2015-06-01 17:21:51 +10:00
|
|
|
|
2015-06-02 23:00:12 +10:00
|
|
|
|
2015-06-04 14:40:47 +10:00
|
|
|
// write the images to disk
|
|
|
|
write_map (img, "noise");
|
2015-06-02 23:00:12 +10:00
|
|
|
|
2015-05-18 14:11:08 +10:00
|
|
|
}
|