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

#include "matrixMath.h"
#include "transformation.h"

void lookAt(mat4* out, vec3* eye, vec3* look, vec3* up) {


	vec3 n;
	vec3Subtract(&n, eye, look);

	vec3 u;
	vec3Cross(&u, up, &n);

	vec3 v;
	vec3Cross(&v, &n, &u);


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


	mat4 Mr;
	identity(&Mr);

	memcpy(&Mr.m00, &u, sizeof(vec3));
	memcpy(&Mr.m01, &v, sizeof(vec3));
	memcpy(&Mr.m02, &n, sizeof(vec3));
	transpose(&Mr, &Mr);


	vec3 t;
	vec3Multiply(&u, &u, -1);
	vec3Multiply(&v, &v, -1);
	vec3Multiply(&n, &n, -1);



	t.x = vec3Dot(&u, eye);
	t.y = vec3Dot(&v, eye);
	t.z = vec3Dot(&n, eye);


	memcpy(&Mr.m03, &t, sizeof(vec3));

	memcpy(out, &Mr, sizeof(mat4));
}

void perspectiveProjection(mat4* out, GLfloat near, GLfloat far) {
	identity(out);
	
	out->m22 = 1 + (far / near);
	out->m32 = - 1.0f / near;
	out->m23 = far;
	out->m33 = 0;
}

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

	out->m00 = 2 / (r - l);
	out->m11 = 2 / (t - b);
	out->m22 = -2 / (f - n);

	out->m03 = - (r + l) / (r - l);
	out->m13 = - (t + b) / (t - b);
	out->m23 = - (f + n) / (f - n);
}

void normalisedDeviceCoordinatesFov(mat4* out, GLfloat fovy, GLfloat aspectRatio, GLfloat n, GLfloat f) {
	GLfloat t = tan(fovy / 2) * n;
	GLfloat r = t * aspectRatio;
	normalisedDeviceCoordinates(out, r, -r, t, -t, n, f);
}