|
|
531f67 |
#include <ctime></ctime>
|
|
|
531f67 |
|
|
|
3a6f9b |
#include <iostream></iostream>
|
|
|
3a6f9b |
|
|
|
531f67 |
#include "generator.h"
|
|
|
531f67 |
|
|
|
531f67 |
|
|
|
531f67 |
Generator::Generator(): Generator(random(time(NULL))) { }
|
|
|
531f67 |
|
|
|
531f67 |
Generator::Generator(ULongInt seed):
|
|
|
531f67 |
one(1ull << 32),
|
|
|
3a6f9b |
max_cache_count(4ll*1024*1024*1024/sizeof(CacheEntry))
|
|
|
531f67 |
{
|
|
|
531f67 |
set_seed(seed);
|
|
|
531f67 |
LongIntVector2 a(1, 2);
|
|
|
531f67 |
LongIntVector2 b(3);
|
|
|
531f67 |
m_cache[ULongIntVector2()];
|
|
|
531f67 |
m_cache_top = m_cache.begin();
|
|
|
531f67 |
m_cache_top->second.next = m_cache_top->second.previous = m_cache_top;
|
|
|
531f67 |
}
|
|
|
531f67 |
|
|
|
531f67 |
void
|
|
|
531f67 |
Generator::set_seed(ULongInt x) {
|
|
|
531f67 |
for(int i = 0; i < 2; ++i)
|
|
|
531f67 |
for(int j = 0; j < 4; ++j)
|
|
|
531f67 |
x = random( m_seeds[i][j] = x );
|
|
|
531f67 |
}
|
|
|
531f67 |
|
|
|
531f67 |
|
|
|
531f67 |
Real
|
|
|
531f67 |
Generator::random(const ULongIntVector2 &coord, int index) const {
|
|
|
077021 |
ULongInt seed = random(random(coord.x) ^ seeds_x()[index]);
|
|
|
077021 |
seed = random(seed ^ random(coord.y) ^ seeds_y()[index]);
|
|
|
a9c87c |
const ULongInt x = seed = random(seed ^ random(coord.x) ^ random(coord.y));
|
|
|
a9c87c |
const ULongInt y = seed = random(seed);
|
|
|
a9c87c |
return random_to_normal(x, y);
|
|
|
531f67 |
}
|
|
|
531f67 |
|
|
|
531f67 |
Vector4
|
|
|
531f67 |
Generator::generate(const ULongIntVector2 &coord, bool shrink_cache) const {
|
|
|
531f67 |
// search value in cache
|
|
|
531f67 |
|
|
|
531f67 |
Cache::iterator i = m_cache.find(coord);
|
|
|
531f67 |
bool found = i != m_cache.end();
|
|
|
531f67 |
if (found) {
|
|
|
531f67 |
i->second.previous->second.next = i->second.next;
|
|
|
531f67 |
i->second.next->second.previous = i->second.previous;
|
|
|
531f67 |
assert(!i->second.in_use);
|
|
|
531f67 |
if (i->second.in_use) return i->second.value;
|
|
|
531f67 |
} else {
|
|
|
531f67 |
i = m_cache.insert(Cache::value_type(coord, CacheEntry())).first;
|
|
|
531f67 |
++m_cache_count;
|
|
|
531f67 |
}
|
|
|
531f67 |
i->second.in_use = true;
|
|
|
531f67 |
i->second.previous = m_cache_top;
|
|
|
531f67 |
i->second.next = i->second.previous->second.next;
|
|
|
531f67 |
m_cache_top = i;
|
|
|
531f67 |
i->second.previous->second.next = i;
|
|
|
531f67 |
i->second.next->second.previous = i;
|
|
|
531f67 |
|
|
|
531f67 |
while (shrink_cache && m_cache_count > max_cache_count) {
|
|
|
531f67 |
Cache::iterator ri = m_cache_top->second.next;
|
|
|
531f67 |
if (ri->second.in_use) break;
|
|
|
531f67 |
ri->second.previous->second.next = ri->second.next;
|
|
|
531f67 |
ri->second.next->second.previous = ri->second.previous;
|
|
|
531f67 |
m_cache.erase(ri);
|
|
|
531f67 |
--m_cache_count;
|
|
|
531f67 |
}
|
|
|
531f67 |
|
|
|
531f67 |
Vector4 &value = i->second.value;
|
|
|
531f67 |
if (!found) {
|
|
|
531f67 |
// generate new value
|
|
|
531f67 |
|
|
|
531f67 |
for(int j = 0; j < 4; ++j)
|
|
|
531f67 |
value[j] = random(coord, j);
|
|
|
531f67 |
|
|
|
531f67 |
ULongInt x_minus_one = coord.x - 1;
|
|
|
531f67 |
ULongInt y_minus_one = coord.y - 1;
|
|
|
531f67 |
ULongInt level_x = coord.x ? (coord.x ^ x_minus_one) >> 1 : (ULongInt)-1;
|
|
|
531f67 |
ULongInt level_y = coord.y ? (coord.y ^ y_minus_one) >> 1 : (ULongInt)-1;
|
|
|
531f67 |
ULongInt level = (level_x < level_y ? level_x : level_y) + 1;
|
|
|
531f67 |
|
|
|
a1942e |
if (level && level < one) {
|
|
|
077021 |
value /= one/level;
|
|
|
531f67 |
if (level_x == level_y) {
|
|
|
531f67 |
// square corners
|
|
|
531f67 |
value += ( generate(ULongIntVector2(coord.x - level, coord.y - level))
|
|
|
077021 |
+ generate(ULongIntVector2(coord.x - level, coord.y + level))
|
|
|
077021 |
+ generate(ULongIntVector2(coord.x + level, coord.y - level))
|
|
|
077021 |
+ generate(ULongIntVector2(coord.x + level, coord.y + level)) )*0.25;
|
|
|
531f67 |
} else {
|
|
|
531f67 |
// diamond corners
|
|
|
531f67 |
value += ( generate(ULongIntVector2(coord.x - level, coord.y))
|
|
|
077021 |
+ generate(ULongIntVector2(coord.x + level, coord.y))
|
|
|
077021 |
+ generate(ULongIntVector2(coord.x, coord.y - level))
|
|
|
077021 |
+ generate(ULongIntVector2(coord.x, coord.y + level)) )*0.25;
|
|
|
531f67 |
}
|
|
|
531f67 |
}
|
|
|
a9c87c |
|
|
|
a9c87c |
for(int j = 0; j < 4; ++j)
|
|
|
a9c87c |
value[j] = mirror_repeat(value[j]);
|
|
|
531f67 |
}
|
|
|
531f67 |
i->second.in_use = false;
|
|
|
531f67 |
|
|
|
531f67 |
return value;
|
|
|
531f67 |
}
|
|
|
531f67 |
|
|
|
531f67 |
Vector4
|
|
|
531f67 |
Generator::generate(const Vector2 &coord, const Vector2 &precision) const {
|
|
|
531f67 |
const int bits = clz(ULongInt(0));
|
|
|
531f67 |
|
|
|
531f67 |
ULongIntVector2 coord_int(
|
|
|
531f67 |
(ULongInt)(LongInt)(coord.x*one),
|
|
|
531f67 |
(ULongInt)(LongInt)(coord.y*one) );
|
|
|
531f67 |
ULongIntVector2 precision_int(
|
|
|
531f67 |
(ULongInt)(LongInt)(precision.x*one),
|
|
|
531f67 |
(ULongInt)(LongInt)(precision.y*one) );
|
|
|
531f67 |
int level_x = bits - clz(precision_int.x);
|
|
|
531f67 |
int level_y = bits - clz(precision_int.y);
|
|
|
531f67 |
coord_int.x = (coord_int.x >> level_x) << level_x;
|
|
|
531f67 |
coord_int.y = (coord_int.y >> level_y) << level_y;
|
|
|
531f67 |
return generate(coord_int);
|
|
|
531f67 |
}
|
|
|
531f67 |
|
|
|
531f67 |
void
|
|
|
4dc49c |
Generator::generate(Surface &target, const Pair2 &bounds) const {
|
|
|
531f67 |
if (target.empty()) return;
|
|
|
4dc49c |
Vector2 d = bounds.distance();
|
|
|
531f67 |
d.x /= target.width();
|
|
|
531f67 |
d.y /= target.height();
|
|
|
531f67 |
Vector2 precision = d/2.0;
|
|
|
531f67 |
|
|
|
3a6f9b |
int percent = 0;
|
|
|
3a6f9b |
Real pk = Real(100)/target.height();
|
|
|
3a6f9b |
|
|
|
4dc49c |
Vector2 p = bounds.p0;
|
|
|
4dc49c |
for(int r = 0; r < target.height(); ++r, p.x = bounds.p0.x, p.y += d.y) {
|
|
|
3a6f9b |
Real pr = r*pk;
|
|
|
3a6f9b |
while(percent < pr)
|
|
|
3a6f9b |
std::cout << (++percent) << "%" << std::endl;
|
|
|
531f67 |
Color *row = target[r];
|
|
|
531f67 |
for(int c = 0; c < target.width(); ++c, p.x += d.x) {
|
|
|
531f67 |
Vector4 v = generate(p, precision);
|
|
|
531f67 |
row[c].r = flip_clamp(v.x);
|
|
|
531f67 |
row[c].g = flip_clamp(v.y);
|
|
|
531f67 |
row[c].b = flip_clamp(v.z);
|
|
|
531f67 |
row[c].a = flip_clamp(v.w);
|
|
|
531f67 |
}
|
|
|
531f67 |
}
|
|
|
531f67 |
}
|