Blame c++/perspective/src/generator.cpp

531f67
#include <ctime></ctime>
531f67
531f67
#include "generator.h"
531f67
531f67
531f67
Generator::Generator(): Generator(random(time(NULL))) { }
531f67
531f67
Generator::Generator(ULongInt seed):
531f67
	one(1ull << 32),
531f67
	max_cache_count(8*1024*1024)
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
	
4dc49c
	Vector2 p = bounds.p0;
4dc49c
	for(int r = 0; r < target.height(); ++r, p.x = bounds.p0.x, p.y += d.y) {
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
}