
#include <math.h>

#include "jlfilm.h"


JLFilm::JLFilm() {

	_c00.Set(-1, -1, -1);
	_c10.Set(1, -1, -1);
	_c01.Set(-1, 1, -1);
	_c11.Set(1, 1, -1);

	_x_pixels = 400;
	_y_pixels = 400;

	_pic = NULL;
}

JLFilm::~JLFilm() {

	delete _pic;
}

JLFilm& JLFilm::CopyFrom(const JLFilm &J) {

	_c00 = J._c00;
	_c10 = J._c10;
	_c01 = J._c01;
	_c11 = J._c11;

	return *this;
}

ostream& operator<<(ostream &co, const JLFilm &J) {

	co << "JLFilm:" << endl;
	co << "  c00: " << J._c00 << endl;
	co << "  c10: " << J._c10 << endl;
	co << "  c01: " << J._c01 << endl;
	co << "  c11: " << J._c11 << endl;
	co << "  resolution: " << J._x_pixels << ", " << J._y_pixels << endl;

	if (J._pic)
		co << "  picture allocated" << endl;
	else
		co << "  picture not allocated" << endl;

	return co;
}

void JLFilm::SetPosition(Vec4 &Eye, Vec4 &LookAt, Vec4 &Up,
			 float x_degrees, float y_degrees) {

	Vec4 Dir(LookAt, Eye);
	Vec4 Right;

	Vec4FastCross3(Right, Dir, Up);
	Vec4FastCross3(Up, Right, Dir);

	Right.MakeUnit();
	Up.MakeUnit();

	float x_radians = x_degrees * M_PI / 180.0f;
	float y_radians = y_degrees * M_PI / 180.0f;
	float dir_length = Dir.Length();

	Right *= (tanf(x_radians * 0.5f) * dir_length);
	Up *= (tanf(y_radians * 0.5f) * dir_length);

	Vec4FastSub(_c00, LookAt, Right);
	Vec4FastAdd(_c10, LookAt, Right);

	Vec4FastAdd(_c01, _c00, Up);
	Vec4FastAdd(_c11, _c10, Up);

	Vec4FastSub(_c00, _c00, Up);
	Vec4FastSub(_c10, _c10, Up);
}

void JLFilm::CalcSamplePoint(float s, float t, Vec4 &v) {

	Vec4 v0, v1;

	Vec3_FastWeightedSum(v0, _c00, (1.0f - s), _c10, s);
	Vec3_FastWeightedSum(v1, _c01, (1.0f - s), _c11, s);

	Vec3_FastWeightedSum(v, v0, (1.0f - t), v1, t);
}

void JLFilm::CalcPixelPoint(int x, int y, Vec4 &v) {

	if ((x < 0) || (x >= _x_pixels) || (y < 0) || (y >= _y_pixels)) {
		cerr << "Error in JLFilm::CalcPixelPoint(): out of bounds!" << endl;
		exit(-1);
	}

	float s = (float(x) + 0.5f) / float(_x_pixels);
	float t = (float(y) + 0.5f) / float(_y_pixels);

	CalcSamplePoint(s, t, v);
}

void JLFilm::CalcPixelPointWithJitter(int x, int y, Vec4 &v) {

	if ((x < 0) || (x >= _x_pixels) || (y < 0) || (y >= _y_pixels)) {
		cerr << "Error in JLFilm::CalcPixelPoint(): out of bounds!" << endl;
		exit(-1);
	}

	float s = (float(x) + drand48()) / float(_x_pixels);
	float t = (float(y) + drand48()) / float(_y_pixels);

	CalcSamplePoint(s, t, v);
}

