#include <stdio.h>
#include <stdlib.h>
#include <mffp.h>

#include <exec/types.h>
#include <proto/exec.h>
#include <exec/memory.h>
#include "/Shared/SH_view.h"
#include "TM_structures.h"
#include "cntrl.h"
#include "TM_precalc.h"
#include "TM_render.h"
#include "/Tools.h"

#ifndef _MATH_H
#define PI      3.14159265358979323846
#define PID2    1.57079632679489661923       /*  PI/2  */
#endif

WORD RotateTable[230400];
ULONG PerspectiveTable[1124];
LONG ArcSineTable[256];

#define ANGLESTEP (DOUBLE)((2.0 * PI) / (DOUBLE)180)
#define MINVALUE (-1024/2)
#define MAXVALUE (-MINVALUE-1)
#define TOTALANGLES (180+(180/4))

#ifndef __DISK_TABLES__
VOID TM_PrecalcRotateTable(VOID)
{
DOUBLE tmpSine;
LONG i, j;

  TM_RotateTable = RotateTable;

	for(i=0; i<TOTALANGLES; i++)
	{
		tmpSine = sin((DOUBLE)i*ANGLESTEP);
		for(j=MINVALUE; j<=MAXVALUE; j++)
			TM_RotateTable[i*1024+j-MINVALUE] = (WORD)(tmpSine*(DOUBLE)j);
	}

  Progress();
}


VOID TM_PrecalcPerspectiveTable(VOID)
{
ULONG i;
ULONG tmp;

	TM_PerspectiveTable = PerspectiveTable;

	for(i=1; i<=1124; i++)
	{
		tmp = (300<<16)/i;
		if(tmp > 0x00150000)
			tmp = 0x00150000;

		TM_PerspectiveTable[i-1] = tmp;
	}

  Progress();
}


VOID TM_PrecalcArcSineTable(VOID)
{
LONG i;

  TM_ArcSineTable = ArcSineTable;

	for(i=0; i<256; i++)
		TM_ArcSineTable[i] = (LONG)((asin((DOUBLE)(127-i)/128.0)+PID2)*256.0/PI);

	Progress();
}

#endif
#ifdef __DISK_TABLES__

BOOL TM_PrecalcRotateTable(LONG AnglesNumber, LONG ValuesNumber)
{
char RotateTableName[256];
FILE *File;
LONG TotalAngles, Size, MinValue, MaxValue;
DOUBLE AngleStep, tmpSine;
LONG i, j;

	TotalAngles = AnglesNumber+(AnglesNumber/4);
	Size = TotalAngles * ValuesNumber;

	if((TM_RotateTable = AllocVec(Size * sizeof(WORD),MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
		return FALSE;

// init table file name

	sprintf(RotateTableName, "Productions:TextureMapping/Data/RotateTable %d %d", AnglesNumber, ValuesNumber);

// if file exist then read

	if((File = fopen(RotateTableName, "r")) != NULL)
		if(fread(TM_RotateTable, sizeof(WORD), Size, File) == Size)
		{
			fclose(File);
     	Progress();
			return TRUE;
		}
		else
			fclose(File);

// else calculate and write

	printf("Precalculate rotate table ...\n");
	
	AngleStep = (DOUBLE)(2.0 * PI) / (DOUBLE)AnglesNumber;
	MinValue = -ValuesNumber/2;
	MaxValue = -MinValue-1;

	for(i=0; i<TotalAngles; i++)
	{
		tmpSine = sin((DOUBLE)i*AngleStep);
		for(j=MinValue; j<=MaxValue; j++)
			TM_RotateTable[i*ValuesNumber+j-MinValue] = (WORD)(tmpSine*(DOUBLE)j);
	}

	if((File = fopen(RotateTableName, "w")) == NULL)
	{
		FreeVec(TM_RotateTable);
		return FALSE;
	}

	if(fwrite(TM_RotateTable, sizeof(WORD), Size, File) != Size)
	{
		fclose(File);
		FreeVec(TM_RotateTable);
		return FALSE;
	}

	fclose(File);

	Progress();
	return TRUE;
}


BOOL TM_PrecalcPerspectiveTable(ULONG CameraDist, ULONG MaxZ)
{
char PerspectiveTableName[256];
FILE *File;
ULONG i;
ULONG tmp;

	if((TM_PerspectiveTable = AllocVec(MaxZ * sizeof(ULONG),MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
		return FALSE;

// init table file name

	sprintf(PerspectiveTableName, "Productions:TextureMapping/Data/PerspectiveTable %d %d", CameraDist, MaxZ);

// if file exist then read

	if((File = fopen(PerspectiveTableName, "r")) != NULL)
		if(fread(TM_PerspectiveTable, sizeof(ULONG), MaxZ, File) == MaxZ)
		{
			fclose(File);
     	Progress();
			return TRUE;
		}
		else
			fclose(File);

// else calculate and write

	printf("Precalculate perspective table ...\n");

	for(i=1; i<=MaxZ; i++)
	{
		tmp = (CameraDist<<16)/i;
		if(tmp > 0x00150000)
			tmp = 0x00150000;

		TM_PerspectiveTable[i-1] = tmp;
	}

	if((File = fopen(PerspectiveTableName, "w")) == NULL)
	{
		FreeVec(TM_PerspectiveTable);
		return FALSE;
	}

	if(fwrite(TM_PerspectiveTable, sizeof(ULONG), MaxZ, File) != MaxZ)
	{
		fclose(File);
		FreeVec(TM_PerspectiveTable);
		return FALSE;
	}

	fclose(File);

  Progress();
	return TRUE;
}

BOOL TM_PrecalcArcSineTable(VOID)
{
char ArcSineTableName[] = "Productions:TextureMapping/Data/ArcSineTable";
FILE *File;
LONG i;

	if((TM_ArcSineTable = AllocVec(256 * sizeof(LONG),MEMF_PUBLIC|MEMF_CLEAR)) == NULL)
		return FALSE;

// if file exist then read

	if((File = fopen(ArcSineTableName, "r")) != NULL)
		if(fread(TM_ArcSineTable, sizeof(LONG), 256, File) == 256)
		{
			fclose(File);
     	Progress();
			return TRUE;
		}
		else
			fclose(File);

// else calculate and write

	printf("Precalculate arcus sine table ...\n");

	for(i=0; i<256; i++)
//		TM_ArcSineTable[i] = (LONG)((asin((DOUBLE)(127-i)/128.0)+PID2)*256.0/PI);
		TM_ArcSineTable[i] = (LONG)((asin((DOUBLE)(127-i)/170.0)+PID2)*256.0/PI);

	if((File = fopen(ArcSineTableName, "w")) == NULL)
	{
		FreeVec(TM_ArcSineTable);
		return FALSE;
	}

	if(fwrite(TM_ArcSineTable, sizeof(LONG), 256, File) != 256)
	{
		fclose(File);
		FreeVec(TM_ArcSineTable);
		return FALSE;
	}

	fclose(File);

  Progress();
	return TRUE;
}

#endif