#include "world_terrain_lod.h"
#include "world_chunk.h"
WorldChunk WorldChunk::create(const Vector3i &loc, const Vector<Vector3> &points)
{
	int i;
	WorldChunk ret;
	ret.loc = loc;
	ret.aabb.position = loc.to_vec3();
	ret.aabb.size = Vector3();
	ret.points.append_array(points);
	for (i = 0; i < ret.points.size(); i++) {
		ret.aabb.expand_to(ret.points[i]);
	}
	ret.lod = 0;
	ret.dirty = true;
	return ret;
}
AABB WorldChunk::get_aabb() const
{
	return aabb;
}
void WorldChunk::update_lod(const Transform &vxform, const List<WorldTerrainLod> &lod_list)
{
	float d = loc.to_vec3().distance_to(vxform.origin);
	const List<WorldTerrainLod>::Element *e = lod_list.front();
	int i = 0;
	int prev_lod = lod;
	bool ok = false;
	while(e) {
		const WorldTerrainLod *l = &e->get();
		if (l->in_range(d)) {
			lod = i;
			ok = true;
			break;
		}
		i++;
		e = e->next();
	}
	if (!ok)
		lod = lod_list.size() - 1;
	if (prev_lod != lod) {
		dirty = true;
		printf("lod changed %d -> %d\n", prev_lod, lod);
	}
}

void WorldChunk::randomize_transforms(Ref<OpenSimplexNoise> dnoise,
			Ref<OpenSimplexNoise> vnoise,
			Ref<RandomNumberGenerator> rnd_offset,
			float density_scaler)
{
	int i, j;
	int max_transforms = (int)(points.size() * density_scaler / 4);
	transforms.resize(max_transforms);
	variance.resize(max_transforms);
	int count = 0;
	float tpx = vnoise->get_period() * 0.1f;
	float dtpx = dnoise->get_period() * 0.15f;
	for (i = 0; i < points.size(); i += 4) {
		Vector3 u = points[i + 1];
		Vector3 v = points[i + 2];
		Vector3 w = points[i + 3];
		Vector3 pt = points[i];
		float density = dnoise->get_noise_3d(pt.x * dtpx, pt.y * dtpx, pt.z * dtpx) * 0.5 + 0.5f;
		int mul = (int)(density * density_scaler);
		mul += (mul == 0);
		for (j = 0; j < mul; j++) {
			float r1 = rnd_offset->randf() * 0.5f;
			float r2 = rnd_offset->randf() * 0.5f;
			float r3 = rnd_offset->randf() * 0.5f;
			Vector3 tops = points[i] + r1 * u + r2 * v + r3 * w;
			float rot = rnd_offset->randf() * 2.0 * M_PI;
			Transform xform = Transform().rotated(Vector3(0, 1, 0), rot);
			xform.origin = tops;
			transforms.write[count] = xform;
			variance.write[count] = vnoise->get_noise_3d(tops.x * tpx, tops.y * tpx, tops.z * tpx) * 0.5 + 0.5f;
			count++;
		}
	}
	transforms.resize(count);
	variance.resize(count);
}

