#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <GL/glew.h>
#include <string.h>

#include "matrixMath.h"

void lookAt(GLfloat* out, GLfloat* eye, GLfloat* look, GLfloat* up) {


	GLfloat n[3];
	vec3Subtract(n, eye, look);

	GLfloat u[3];
	vec3Cross(u, up, n);

	GLfloat v[3];
	vec3Cross(v, n, u);


	vec3Normalise(n, n);
	vec3Normalise(u, u);
	vec3Normalise(v, v);


	GLfloat Mr[16];
	identity(Mr);

	memcpy(&Mr[0], u, sizeof(GLfloat) * 3);
	memcpy(&Mr[4], v, sizeof(GLfloat) * 3);
	memcpy(&Mr[8], n, sizeof(GLfloat) * 3);
	transpose(Mr, Mr);


	GLfloat t[3];
	vec3Multiply(u, u, -1);
	vec3Multiply(v, v, -1);
	vec3Multiply(n, n, -1);



	t[0] = vec3Dot(u, eye);
	t[1] = vec3Dot(v, eye);
	t[2] = vec3Dot(n, eye);


	memcpy(&Mr[12], t, sizeof(GLfloat) * 3);

	memcpy(out, Mr, sizeof(GLfloat) * 16);
}

void perspectiveProjection(GLfloat* out, GLfloat near, GLfloat far) {
	identity(out);
	
	out[10] = 1 + (far / near);
	out[11] = - 1.0f / near;
	out[14] = far;
}

void normalisedDeviceCoordinates(GLfloat* out, GLfloat r, GLfloat l, GLfloat t, GLfloat b, GLfloat n, GLfloat f) {
	identity(out);

	out[0] = 2 / (r - l);
	out[5] = 2 / (t - b);
	out[10] = -2 / (f - n);

	out[12] = - (r + l) / (r - l);
	out[13] = - (t + b) / (t - b);
	out[14] = - (f + n) / (f - n);
}

void normalisedPerspective(GLfloat* out, GLfloat near, GLfloat far, GLfloat r, GLfloat l, GLfloat t, GLfloat b) {
	GLfloat ndc[16];

	perspectiveProjection(out, near, far);
	normalisedDeviceCoordinates(ndc, r, l, t, b, near, far);

	multiply(out, ndc, out);
}