/* $VER: WBStars_plot.c 2.09 (28 Feb 99)
*/

#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];
long		dx[10];
long		dy[10];
long		dz[10];
long		dxw[10]; /* linewarp */
long		dyw[10];
long		dzw[10];
double		aadd;
double		badd;
double		cadd;
double		aaddd;
double		baddd;
double		caddd;
int		rotcnt	=0;
int		x0;
int		y0;
int		z0;
int		kaz=0;
int		khe=0;
int		grad;
void		*pool		= NULL;

struct Star	*Stars		= NULL;

void	InitObjects()
{
	double	pi2=PI/180.0;
	int	i;
	aadd	= 0.0;
	badd	= 0.0;
	cadd	= 0.0;
	aaddd	= 0.0;
	baddd	= 0.0;
	caddd	= 0.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];
	}

	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;
	double	length;
	double	sina,sinb,sinc;
	double	cosa,cosb,cosc;
	double	a,b;

	if(Rotate)
	{
		if((rotcnt=((++rotcnt)%Frames))==0)
		{
			aaddd	= ((double)(RangeRand(5)-2))/(10*Frames*Frames);
			baddd	= ((double)(RangeRand(5)-2))/(25*Frames*Frames);
			caddd	= ((double)(RangeRand(5)-2))/(25*Frames*Frames);
		}
		aadd	= MAX(MIN(aadd+aaddd,0.4/Frames),-0.4/Frames);
		badd	= MAX(MIN(badd+baddd,0.1/Frames),-0.1/Frames);
		cadd	= MAX(MIN(cadd+caddd,0.1/Frames),-0.1/Frames);
		sina	= sin(aadd);
		sinb	= sin(badd);
		sinc	= sin(cadd);
		cosa	= cos(aadd);
		cosb	= cos(badd);
		cosc	= cos(cadd);
	}

	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];

			if(Rotate)
			{
				if(badd!=0.0)
				{
						a		= (double) Stars[s].x3;
						b		= (double) Stars[s].z3;
						Stars[s].x3	= (int)(a*cosb - b*sinb);
						Stars[s].z3	= (int)(b*cosb + a*sinb);
				}
				if(cadd!=0.0)
				{
						a		= (double) Stars[s].y3;
						b		= (double) Stars[s].z3;
						Stars[s].y3	= (int)(a*cosc - b*sinc);
						Stars[s].z3	= (int)(b*cosc + a*sinc);
				}
				if(aadd!=0.0)
				{
						a		= (double) Stars[s].x3;
						b		= (double) Stars[s].y3;
						Stars[s].x3	= (int)(a*cosa - b*sina);
						Stars[s].y3	= (int)(b*cosa + a*sina);
				}
			}

			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);
			}
		}
	}
}
