/* $VER: WBStars_plot.c 2.0b8 (19 Mai 98)
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <math.h>
#include <proto/exec.h>
#include <clib/alib_protos.h>
#include <clib/macros.h>

#include <stdio.h>

#include "WBStars_plot.h"

#ifndef M_PI
#define	M_PI		3.14159265358979323846	/* pi */
#endif


struct Star
{
	long		x3;
	long		y3;
	long		z3;
	int		x2;
	int		y2;
	int		lx2;
	int		ly2;
	char		drawn;
	int		warp;
	struct Line	*line;
};

void	NewStar( int star );

const long	maxd0		= 2147483647;	/* 2^31 - 1 */
const long	maxd		= 46340;	/* ca. sqrt(2^31) */
const int	maxd2		= 215;		/* ca. sqrt(sqrt(2^31)) */
const long	maxd16		= 2896;		/* maxd/16 */
int		SIN[360];
int		COS[360];
int far		SIN2[3600];
int far		COS2[3600];
int		ASIN[2001];
long		dx[10];
long		dy[10];
long		dz[10];
long		dxw[10]; /* linewarp */
long		dyw[10];
long		dzw[10];
int		aadd;
int		badd;
int		cadd;
int		rotcnt	=0;
int		x0;
int		y0;
int		z0;
int		kaz=0;
int		khe=0;
int		grad;
	double	pi2=PI/180.0;
void		*pool		= NULL;

struct Star	*Stars		= NULL;

void	InitObjects()
{
	int	i;
	aadd	= 0;
	badd	= 0;
	cadd	= 0;

	pool=CreatePool(MEMF_ANY,10000,10000);

	for(i=0;i<360;i++)
	{
		SIN[i]	= (int)(sin(pi2*(double)i)*(double)maxd2);
		COS[(i+270)%360]= SIN[i];
	}
	for(i=0;i<3600;i++)
	{
		SIN2[i]	= (int)(sin((pi2*(double)i)/10.0)*1000.0);
		COS2[(i+2700)%3600]= SIN2[i];
	}
	for(i=0;i<2001;i++)
	{
		ASIN[i]	= (int)((asin(((double)(i-1000))/1000.0)*10.0)/pi2);
	}

	x0=width/2;
	y0=height/2;
	z0=MAX(x0,y0)*COS[v]/SIN[v];

/*	for(i=0;i<10;i++)
	{
		dx[i]	= 0;
		dy[i]	= 0;
		dz[i]	= -3000*i/Frames;
		dxw[i]	= dx[i]*i*Frames/40;
		dyw[i]	= dy[i]*i*Frames/40;
		dzw[i]	= dz[i]*i*Frames/40;
	}
*/
	for(i=1;i<10;i++)
	{
		dxw[i]	= -75*i*i*SIN[kaz]*COS[khe]/maxd;
		dyw[i]	= -75*i*i*SIN[khe]/maxd2;
		dzw[i]	= -75*i*i*COS[kaz]*COS[khe]/maxd;
		dx[i]	= dxw[i]*40/(i*Frames);
		dy[i]	= dyw[i]*40/(i*Frames);
		dz[i]	= dzw[i]*40/(i*Frames);
	}

	grad=(int)(sin(pi2)*(double)maxd);

	Stars=(struct Star*)AllocMem(sizeof(struct Star)*Max_Objects,MEMF_ANY);
	for(i=0;i<Max_Objects;i++)
	{
		Stars[i].line=AllocPooled(pool,sizeof(struct Line));
		Stars[i].line->mempoints=0;
		Stars[i].line->npoints=0;
		NewStar(i);
		Stars[i].z3=RangeRand(maxd);
	}
}

void	NewStar(int s)
{
	int	az,az1;
	int	he,he1;

/*	while(TRUE)
	{
		az1	= RangeRand(v*2)-v;
		he1	= RangeRand(v*2)-v;
		az	= (az1+360)%360;
		he	= (he1+360)%360;
		Stars[s].x3	= SIN[az]*COS[he]+RangeRand(grad);
		Stars[s].y3	= SIN[he]*maxd2+RangeRand(grad);

		if( (Stars[s].x3!=0) || (Stars[s].y3!=0) ) break;
	}
	Stars[s].z3	= maxd;
*/
	while(TRUE)
	{
		az1	= RangeRand(360)-180;
		he1	= RangeRand(180)-90;
		az	= (az1+360)%360;
		he	= (he1+360)%360;
		Stars[s].x3	= SIN[az]*COS[he]+RangeRand(grad);
		Stars[s].y3	= SIN[he]*maxd2+RangeRand(grad);
		Stars[s].z3	= COS[az]*COS[he]+RangeRand(grad);

		if( ((Stars[s].y3!=SIN[khe]*maxd2) || (Stars[s].x3!=SIN[kaz]*SIN[khe])) && (COS[he]>RangeRand(maxd2)) ) break;
	}

	Stars[s].lx2	= x0;
	Stars[s].ly2	= y0;

	Stars[s].drawn	= FALSE;
	Stars[s].warp	= RangeRand(Warp)+1;
/*	Stars[s].warp	= RangeRand(Warp-Warp*(MAX(abs(az1),abs(he1)))/(1+v))+1;
*/}

void	ClearObjects()
{
	int s;

	for(s=0; s<Max_Objects; s++)
	{
		ClearLine(Stars[s].line);
	}

	FreeMem(Stars,sizeof(struct Star)*Max_Objects);
	DeletePool(pool);
}

void	PlotObjects()
{
	int		s;
	int		lx3,ly3,lz3;
	long		length,a;

	if((rotcnt=((++rotcnt)%Frames))==0)
	{
		aadd	= MAX(MIN(aadd+(RangeRand(3)-1),2),-2);
		badd	= MAX(MIN(badd+(RangeRand(5)-2),3),-3);
		cadd	= MAX(MIN(cadd+(RangeRand(5)-2),3),-3);
	}

	for(s=0; s<Max_Objects; s++)
	{
		if(s<Plot_Objects)
		{
			Stars[s].x3+=dx[Stars[s].warp];
			Stars[s].y3+=dy[Stars[s].warp];
			Stars[s].z3+=dz[Stars[s].warp];

			/* rotate */
/*			if(badd!=0)
			{
				length	= Stars[s].x3*Stars[s].x3+Stars[s].z3*Stars[s].z3;
				if(length>0.0)
				{
					length	= (long) sqrt((double)length);
					a	= ASIN[((1000*Stars[s].z3)/length)+1000];
					if(Stars[s].x3<0.0)
					{
						a	= 180 - a;
					}
					a	+= badd;
					Stars[s].x3	= (COS2[a] * length)/maxd2;
					Stars[s].z3	= (SIN2[a] * length)/maxd2;
				}
			}
			if(cadd!=0)
			{
				length	= Stars[s].y3*Stars[s].y3+Stars[s].z3*Stars[s].z3;
				if(length>0.0)
				{
					length	= (long) sqrt((double)length);
					a	= ASIN[((1000*Stars[s].z3)/length)+1000];
					if(Stars[s].x3<0.0)
					{
						a	= 180 - a;
					}
					a	+= cadd;
					Stars[s].y3	= (COS[a] * length)/maxd2;
					Stars[s].z3	= (SIN[a] * length)/maxd2;
				}
			}
*/			if(aadd!=0)
			{
				length	= Stars[s].x3*Stars[s].x3+Stars[s].y3*Stars[s].y3;
				if(length>0.0)
				{
					length	= (long) sqrt((double)length);
/*					a	= ASIN[((1000*Stars[s].y3)/length)+1000];
*/					a	= (int)((asin((double)(Stars[s].y3*1000/length)/1000.0)*10.0)/pi2);
					if(Stars[s].x3<0.0)
					{
						a	= 1800 - a;
					}
					a	= (a+aadd)%3600;
					Stars[s].x3	= (COS2[a] * length)/1000;
					Stars[s].y3	= (SIN2[a] * length)/1000;
				}
			}

			if( (Stars[s].z3>maxd) || (abs(Stars[s].x3)>maxd) || (abs(Stars[s].y3)>maxd) )
			{
				if(Stars[s].drawn)
					ClearLine(Stars[s].line);

				NewStar(s);
			}
			else
			{
				if(Stars[s].z3>0)
				{
					Stars[s].x2=Stars[s].x3*z0/Stars[s].z3+x0;
					Stars[s].y2=Stars[s].y3*z0/Stars[s].z3+y0;
					lz3=Stars[s].z3+dzw[Stars[s].warp];

					if( lz3>0 )
					{
						lx3=Stars[s].x3+dxw[Stars[s].warp];
						ly3=Stars[s].y3+dyw[Stars[s].warp];
						Stars[s].lx2=lx3*z0/lz3+x0;
						Stars[s].ly2=ly3*z0/lz3+y0;
					}

					if( Stars[s].x2>0 && Stars[s].x2<width && Stars[s].y2>0 && Stars[s].y2<height)
					{
						ChangeLine(Stars[s].line,Stars[s].x2,Stars[s].y2,Stars[s].lx2,Stars[s].ly2,&coltable[(maxd-Stars[s].z3)/maxd16][0],16);
						Stars[s].drawn=TRUE;
					}
					else
					{
						if(Stars[s].drawn)
							ClearLine(Stars[s].line);

						NewStar(s);
					}
				}
				else
				{
					if(Stars[s].drawn)
						ClearLine(Stars[s].line);

					NewStar(s);
				}
			}
		}
		else
		{
			if(Stars[s].drawn)
			{
				ClearLine(Stars[s].line);
				NewStar(s);
			}
		}
	}
}
