/*
   3dutils.c
   (c)2000 Dan Potter and Jordan DeLong

   Some 3D utils
   Based on example code by Marcus Comstedt
*/

static char id[] = "TRYP $Id: 3dutils.c,v 1.1 2000/12/29 03:37:20 bard Exp $";

#include <stdio.h>
#include "3dutils.h"

/* Sin lookup table for fixed-degree fsin() and fcos() */
#include "sintab.h"

/* Matrices for transforming world coordinates to screen
   coordinates (with perspective) */
#define XCENTER 320.0f
#define YCENTER 240.0f

/* 
  This is calculated as:
  1.0 / tan(FOV/2)
 */
//#define COT_FOVY_2 	1.73f	/* 60' */
#define COT_FOVY_2	1.0f	/* 90' */

/* Screen view matrix (used to transform to screen space) */
matrix_t screenview_matrix = {
	{ YCENTER,    0.0f,   0.0f,  0.0f },
	{    0.0f, YCENTER,   0.0f,  0.0f },
	{    0.0f,    0.0f,   1.0f,  0.0f },
	{ XCENTER, YCENTER,   0.0f,  1.0f }
};

/* Projection matrix (does perspective) */
matrix_t projection_matrix = {
	{ COT_FOVY_2,       0.0f,                      0.0f,  0.0f },
	{       0.0f, COT_FOVY_2,                      0.0f,  0.0f },
	{       0.0f,       0.0f, (ZFAR+ZNEAR)/(ZNEAR-ZFAR), -1.0f },
	{       0.0f,       0.0f, 2*ZFAR*ZNEAR/(ZNEAR-ZFAR),  1.0f }
};

void td_reset() {
	mat_identity();
}

void td_translate(float x, float y, float z) {
	matrix_t m = {
		{ 1.0f, 0.0f, 0.0f, 0.0f },
		{ 0.0f, 1.0f, 0.0f, 0.0f },
		{ 0.0f, 0.0f, 1.0f, 0.0f },
		{    x,    y,    z, 1.0f }
	};
	mat_apply(&m);
}

void td_scale(float xs, float ys, float zs) {
	matrix_t m = {
		{   xs, 0.0f, 0.0f, 0.0f },
		{ 0.0f,   ys, 0.0f, 0.0f },
		{ 0.0f, 0.0f,   zs, 0.0f },
		{ 0.0f, 0.0f, 0.0f, 1.0f }
	};
	mat_apply(&m);
}

void td_rotate_x(int r) {
	matrix_t m = {
		{ 1.0f,    0.0f,    0.0f, 0.0f },
		{ 0.0f, fcos(r),-fsin(r), 0.0f },
		{ 0.0f, fsin(r), fcos(r), 0.0f },
		{ 0.0f,    0.0f,    0.0f, 1.0f }
	};
	mat_apply(&m);
}

void td_rotate_y(int r) {
	matrix_t m = {
		{ fcos(r), 0.0f, fsin(r), 0.0f },
		{    0.0f, 1.0f,    0.0f, 0.0f },
		{-fsin(r), 0.0f, fcos(r), 0.0f },
		{    0.0f, 0.0f,    0.0f, 1.0f }
	};
	mat_apply(&m);
}

void td_rotate_z(int r) {
	matrix_t m = {
		{ fcos(r),-fsin(r), 0.0f, 0.0f },
		{ fsin(r), fcos(r), 0.0f, 0.0f },
		{    0.0f,    0.0f, 1.0f, 0.0f },
		{    0.0f,    0.0f, 0.0f, 1.0f }
	};
	mat_apply(&m);
}

void td_rotate(int xr, int yr, int zr) {
	td_rotate_x(xr);
	td_rotate_y(yr);
	td_rotate_z(zr);
}

void td_project() {
	mat_apply(&screenview_matrix);
	mat_apply(&projection_matrix);
}

void td_transform_vectors(vector_t *vi, vector_t *vo, int cnt, int skip) {
	mat_transform(vi, vo, cnt, skip);
}

