/*==================================
	"pr.c" v3.0 l10 sbj: 3d(up down)
==================================*/
#include <stdlib.h>
#include <memory.h>
#include "prdef.h"

extern int    *_cos,*_sin;
extern short  polmax;
extern poly   *mapdata;
extern poly   cardata[];
extern pol2d  *poldat;
extern short  rd;
extern rdata  *road;
extern poly   car[3], ecar[3];

extern void polygon( pol2d *pd );

int	comp_f( pol2d *item1, pol2d *item2 )
{
	if( item1->y < item2->y ) 
		return (-1);
	else
		return ( 1);
}

typedef struct {
	int	px[8],py[8],pz[8];
//	int	type;
	int	n;
} ipoly;

#define	distance(pol)	(pol.py[0])
//#define innerCp(i)	((pol.px[i]-x0)*kx+(pol.py[i]-y0)*ky)
#define innerCp(i)		(pol.py[i]-100)
int	clipping( ipoly *pl )	//, int x0,int y0, int kx, int ky )
{
	int	ni=pl->n,no=0,i,li,ci,p,q;
	ipoly pol=*pl;
	if( ni>= 8 ) return 0;
	pol.px[ni]=pol.px[0];
	pol.py[ni]=pol.py[0];
	pol.pz[ni]=pol.pz[0];
	li = innerCp(0);
	for(i=1; i<=ni; ++i){
		ci = innerCp(i);
		if( li*ci < 0 ){
			p=_abs(li);
			q=_abs(ci);
			pl->px[no]=(q*pol.px[i-1]+p*pol.px[i])/(p+q);
			pl->py[no]=(q*pol.py[i-1]+p*pol.py[i])/(p+q);
			pl->pz[no]=(q*pol.pz[i-1]+p*pol.pz[i])/(p+q);
			no++;
		}
		if(ci>=0){
			pl->px[no]=pol.px[i];
			pl->py[no]=pol.py[i];
			pl->pz[no]=pol.pz[i];
			no++;
		}
		li = ci;
	}
	pl->n=no;
	return no;
}

#define inner(a) (a.x*lx+a.y*ly+a.z*lz)
void	putmap( int x0,int y0,int z0, vect ex,vect ey,vect ez )
{
	int	pn,i,j,n,yn,clpy,clpr,clpl;
	int	p[11]={4};
	int x,y,z,lx,ly,lz;
	poly *pl;
	ipoly pol ;
	n=0;
	for(pn=0; pn<polmax; ++pn)
	{
		lx = mapdata[pn].px[0]*10 - x0;
		ly = mapdata[pn].py[0]*10 - y0;
		lz = mapdata[pn].pz[0]    - z0;
		y = inner(ey);
		if( y > VIEW*10000 || y < -400*10000 )
			continue;
		x = inner(ex);
		if( x*2+y+1000*10000<0 || x*-2+y+1000*10000<0 )
			continue;
		z = inner(ez);
		if( z*3/2+y+1000*10000<0 || z*-3/2+y+1000*10000<0 )
			continue;

		pl = mapdata+pn;
		pol.n = pl->n;
		clpy = clpr = clpl = 0;
		yn = 0; //VIEW*10;
		for(i=0; i<4; ++i)
		{
			lx = pl->px[i]*10 - x0 ;
			ly = pl->py[i]*10 - y0 ;
			lz = pl->pz[i]    - z0 ;
			pol.py[i] = y = inner(ey)/1000;
			pol.px[i] = x = inner(ex)/1000;
			pol.pz[i] = inner(ez)/1000;
			if( y<=100 )	clpy++;
			if( x*-2+y<0 )	clpr++;
			if( x*2+y<0 )	clpl++;
			yn += y;// _min( yn, y );
		}
		if( clpy==4 || clpr==4 || clpl==4 )
			continue;
		j=4;
		if( clpy )
			j=clipping( &pol );
		if( j==0 )
			continue;
		for( i=0; i<j; ++i ){
		//	p[i*2+1] = 160+pol.px[i]*240/1000;
		//	p[i*2+2] = 240-pol.py[i]*240/1000;
			p[i*2+1] = VramX/2 + Mag*pol.px[i]/pol.py[i];
			p[i*2+2] = SbjY    - Mag*pol.pz[i]/pol.py[i];
		}
		p[0] = j;
		memcpy( &poldat[n], p, sizeof(int)*11 );
		poldat[n].y = yn;
		poldat[n].col = pl->type;
		++n;
	}
	qsort( poldat, n, sizeof(pol2d), comp_f);
	n = _min( n, PUTPOL );

	for(i=n-1; i>=0; --i)
		polygon( &poldat[i] );
}

void	putcar( int x0,int y0,int z0, vect ex,vect ey,vect ez, int cpol )
{
	int	pn,i,n,yn;
	int	p[9]={4};
	int x,y,z,lx,ly,lz;
	poly *pl;
	n=0;
	for(pn=cpol-1; pn>=0; --pn)
	{
//		lx = cardata[pn].px[0]*10 - x0;
//		ly = cardata[pn].py[0]*10 - y0;
//		lz = cardata[pn].pz[0]    - z0;
//		y = inner(ey)/1000;
//		if( y > VIEW*10 || y < -200*10 )
//			continue;
//		x = inner(ex)/1000;
//		if( x*2+y+400*10<0 || x*-2+y+400*10<0 )
//			continue;

		pl = cardata+pn;
		yn = VIEW*10;
		for(i=0; i<4; ++i)
		{
			lx = pl->px[i]*10 - x0 ;
			ly = pl->py[i]*10 - y0 ;
			lz = pl->pz[i]    - z0 ;
			y = inner(ey)/1000;
			x = inner(ex)/1000;
			z = inner(ez)/1000;

			if( y<=100 || y>VIEW*10 || x*-2+y+4000<0 || x*2+y+4000<0 )
				goto lab1;
			yn = _min( yn, y );
			p[i*2+1] = VramX/2 + Mag*x/y;
			p[i*2+2] = SbjY    - Mag*z/y;
		}
		p[0] = 4;//pl->n;
		memcpy( &poldat[n], p, sizeof(int)*9 );
		poldat[n].y = yn;
		poldat[n].col = pl->type;
		++n;
		lab1:;
	}
	qsort( poldat, n, sizeof(pol2d), comp_f);
	for(i=n-1; i>=0; --i)
		polygon( &poldat[i] );
}

int	mycar( short x,short y,short z, int ang, vect kv )
{
	int i,j;
	int	cs=_cos[ang],sn=_sin[ang];
	for(i=0; i<3; ++i)
	{
		for(j=0; j<4; ++j)
		{
			cardata[i].px[j] = car[i].px[j]*sn/50 -
							   car[i].py[j]*cs/50 + x;
			cardata[i].py[j] =-car[i].px[j]*cs/50 -
							   car[i].py[j]*sn/50 + y;
			cardata[i].pz[j] = car[i].pz[j]*10 + z;
		}
		cardata[i].type =  car[i].type;
	}
	return 3;
}
int	encar( short x,short y,short z, int ang, vect kv, int col, int pol )
{
	int i,j;
	int	cs=_cos[ang],sn=_sin[ang];
	for(i=0; i<3; ++i){
		for(j=0; j<4; ++j){
			cardata[pol+i].px[j] =  ecar[i].px[j]*sn/50 -
									ecar[i].py[j]*cs/50 + x;
			cardata[pol+i].py[j] = -ecar[i].px[j]*cs/50 -
									ecar[i].py[j]*sn/50 + y;
			cardata[pol+i].pz[j] =  ecar[i].pz[j]*10 + z;
		}
		cardata[pol+i].type =  ecar[i].type*col;
	}
	return pol+3;
}

int		onRoad( int x, int y, int n )
{
	int	i,j,ax,ay,bx,by,cx,cy,dx,dy;
	for(j=0; j<rd; ++j){
		i=(j+n)%rd;
		ax = road[i].px[0];	bx = road[i].px[1];
		cx = road[i].px[2];	dx = road[i].px[3];
		if( x < _min(ax,bx,cx,dx)*100 ) continue;
		if( x > _max(ax,bx,cx,dx)*100 ) continue;
		ay = road[i].py[0];	by = road[i].py[1];
		cy = road[i].py[2];	dy = road[i].py[3];
		if( y < _min(ay,by,cy,dy)*100 ) continue;
		if( y > _max(ay,by,cy,dy)*100 ) continue;

		if( (bx-ax)*(y-ay*100)-(by-ay)*(x-ax*100) <0 ) continue;
		if( (cx-bx)*(y-by*100)-(cy-by)*(x-bx*100) <0 ) continue;
		if( (dx-cx)*(y-cy*100)-(dy-cy)*(x-cx*100) <0 ) continue;
		if( (ax-dx)*(y-dy*100)-(ay-dy)*(x-dx*100) <0 ) continue;
		return i;
	}
	return -1;
}

