



#include "standard.h"
#include "global.h"
#include "drawprimitive.h"
#include "scanlines.h"


/*
	Function : ScanLinesTDecalAffine
	Useage	 : Decal Textured Affine 
*/

void ScanLinesTDecalAffine(GRADIENT* Gradients,EDGE* pLeft,EDGE* pRight,EDGE* StepLeft,EDGE* StepRight)
{
	int Width;
	unsigned short* pDestination;
	long u,v,du,dv;
	long yline;
	float oowidth;
	short subdivcnt;
	short texel;
	double fconv;

	yline = long(Output)+YTable[pLeft->y];
	
	while(StepLeft->height--)
	{
		Width  = pRight->x;
		Width -= pLeft->x;

		if(Width > 0)
		{
			pDestination = (unsigned short*) yline + pLeft->x;
			
			u = pLeft->uozf;
			v = pLeft->vozf;

			oowidth = WidthTable[Width];

			du = (pRight->uozf - pLeft->uozf);
			du = FTOL(float(du)*oowidth);
			
			dv = (pRight->vozf - pLeft->vozf);
			dv = FTOL(float(dv)*oowidth);
			
			subdivcnt = Width>>4;
			Width = Width-(subdivcnt<<4);

			while(subdivcnt--)
			{
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+0) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+1) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+2) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+3) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+4) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+5) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+6) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+7) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+8) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+9) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+10) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+11) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+12) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+13) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+14) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+15) = texel;
				u += du;
				v += dv;
				
				pDestination += 16;
			}

			for(int n=0;n<Width;n++)
			{
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination) = texel;
				u += du;
				v += dv;
				pDestination++;
			}
		}

		yline += bytepitch;

		StepLeft->uozf += StepLeft->uozstepf;
		StepLeft->vozf += StepLeft->vozstepf;
		StepLeft->x    += StepLeft->xstep;
		StepLeft->y++;
		StepLeft->ErrorTerm += StepLeft->Numerator;

		if(StepLeft->ErrorTerm >= StepLeft->Denominator)
		{
			StepLeft->x++;
			StepLeft->uozf += StepLeft->uozxtraf;
			StepLeft->vozf += StepLeft->vozxtraf;
			StepLeft->ErrorTerm -= StepLeft->Denominator;
		}
		
		StepRight->x    += StepRight->xstep;
		StepRight->uozf += StepRight->uozstepf;
		StepRight->vozf += StepRight->vozstepf;
		StepRight->y++;
		
		StepRight->ErrorTerm += StepRight->Numerator;

		if(StepRight->ErrorTerm >= StepRight->Denominator)
		{
			StepRight->x++;
			StepRight->uozf += StepRight->uozxtraf;
			StepRight->vozf += StepRight->vozxtraf;
			StepRight->ErrorTerm -= StepRight->Denominator;
		}
	}
}


// EOF : ScanLinesTDecalAffine




/*
	Function : ScanLinesTDecal
	Useage	 : Decal Textured Perspective Correct
*/

void ScanLinesTDecal(GRADIENT* Gradients,EDGE* pLeft,EDGE* pRight,EDGE* StepLeft,EDGE* StepRight)
{
	int Width;
	long u,v;
	long du,dv;
	unsigned short* pDestination;
	int subdivcnt;
	int pixelsleft;
	float oozr,uozr,vozr;
	float ZLeft,ULeft,VLeft;
	float ZRight,URight,VRight;
	float oozdx,uozdx,vozdx;
	float one = 1.0f;
	long yline;
	short texel;
	double fconv;

	oozdx = Gradients->dozx * float(SUBDIVSPAN);
	uozdx = Gradients->duzx * float(SUBDIVSPAN);
	vozdx = Gradients->dvzx * float(SUBDIVSPAN);

	yline = long(Output)+YTable[pLeft->y];

	while(StepLeft->height--)
	{
		ZLeft = pLeft->ooz;

		_asm
		{
			// 1.0f/pLeft->ooz
			fld  [one]
			fdiv [ZLeft]
		}
	
		
		pDestination = (unsigned short*) yline + pLeft->x;
		Width = (pRight->x - pLeft->x);

		_asm
		{
			// ZLeft = 1.0f/pLeft->ooz
			fstp [ZLeft]
		}

		oozr = pLeft->ooz+oozdx;
		uozr = pLeft->uoz+uozdx;
		vozr = pLeft->voz+vozdx;
		
		ULeft = pLeft->uoz * ZLeft;
		VLeft = pLeft->voz * ZLeft;

		if(Width > 0)
		{
			
			_asm
			{
				fld	 one
				fdiv [oozr]
			}

			subdivcnt  = Width>>SUBDIVSHIFT;				
			pixelsleft = Width-(subdivcnt<<SUBDIVSHIFT);

			_asm
			{
				fstp [ZRight]
			}
			
			while(subdivcnt-- > 0)
			{

				URight = uozr * ZRight;
				VRight = vozr * ZRight;
								
				u  = FTOLFIX(ULeft);
				v  = FTOLFIX(VLeft);
				
				du = FTOLFIX(URight - ULeft)>>SUBDIVSHIFT;
				dv = FTOLFIX(VRight - VLeft)>>SUBDIVSHIFT;
				
				oozr += oozdx;
			
				_asm
				{
					// one/oozr;
					fld	 [one]
					fdiv [oozr]
				}

				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+0) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+1) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+2) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+3) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+4) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+5) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+6) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+7) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+8) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+9) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+10) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+11) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+12) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+13) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+14) = texel;
				u += du;
				v += dv;
				texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
				if(texel != 0)
					*(pDestination+15) = texel;
				u += du;
				v += dv;

								
					
				pDestination += 16;
				
				_asm
				{
					// ZRight = one/oozr
					fstp	[ZRight]		
				}

				ULeft = URight;
				VLeft = VRight;

				vozr += vozdx;
				uozr += uozdx;

			}
			
			if(pixelsleft)
			{
				u  = FTOLFIX(ULeft);
				v  = FTOLFIX(VLeft);
			
				if(--pixelsleft)
				{
					ZRight = 1.0f/(pRight->ooz - Gradients->dozx);
	
					URight = ZRight * (pRight->uoz - Gradients->duzx);
					VRight = ZRight * (pRight->voz - Gradients->dvzx);
					
					float opixf;
					opixf = WidthTable[pixelsleft];

					du = FTOLFIX(URight - ULeft);
					dv = FTOLFIX(VRight - VLeft);

					du = FTOL(float(du)*opixf);
					dv = FTOL(float(dv)*opixf);
				}

				for(int n=0;n<=(pixelsleft);n++)
				{	
					texel = *(Texture+(u>>16)+((v>>8)&0xffffff00));
					if(texel != 0)
						*(pDestination) = texel;
					u += du;
					v += dv;
					pDestination++;
				}
			}
		}

		yline += bytepitch;

		StepLeft->x += StepLeft->xstep;
		StepLeft->y++;
		StepLeft->uoz += StepLeft->uozstep;
		StepLeft->voz += StepLeft->vozstep;
		StepLeft->ooz += StepLeft->oozstep;

		StepLeft->ErrorTerm += StepLeft->Numerator;
	
		if(StepLeft->ErrorTerm >= StepLeft->Denominator)
		{
			StepLeft->x++;
			StepLeft->ooz += StepLeft->oozxtra;
			StepLeft->uoz += StepLeft->uozxtra;
			StepLeft->voz += StepLeft->vozxtra;
			StepLeft->ErrorTerm -= StepLeft->Denominator;
		}


		StepRight->x += StepRight->xstep;
		StepRight->y++;
		StepRight->uoz += StepRight->uozstep;
		StepRight->voz += StepRight->vozstep;
		StepRight->ooz += StepRight->oozstep;

		StepRight->ErrorTerm += StepRight->Numerator;
	
		if(StepRight->ErrorTerm >= StepRight->Denominator)
		{
			StepRight->x++;
			StepRight->ooz += StepRight->oozxtra;
			StepRight->uoz += StepRight->uozxtra;
			StepRight->voz += StepRight->vozxtra;
			StepRight->ErrorTerm -= StepRight->Denominator;
		}
	}
}

// EOF : ScanLinesTDecal




#define PIXELOUT(x,r,g,b)	PIXELOUT555LOOKUP(x,r,g,b)


#define PIXELOUT555LOOKUP(x,r,g,b)  {unsigned short out;\
						texel = *(Texture + ((u>>16))+((v>>16)<<8));\
						if(texel != 0){\
						tr = ((texel>>5)&0x3e0)+r;\
						out = short(*(RGBTable+tr)<<10);\
						tg = ((texel)&0x3e0)+g;\
						out|= short(*(RGBTable+tg)<<5);\
						tb = ((texel<<5)&0x3e0)+b;\
						out|= short(*(RGBTable+tb));\
						*(pDestination+x) = (unsigned short) out;}\
						u+=du;\
						v+=dv;}


/*
	Function : ScanLinesTF
	Useage	 : Textured Flat Perspective Correct
*/

void ScanLinesTFDecal(GRADIENT* Gradients,EDGE* pLeft,EDGE* pRight,EDGE* StepLeft,EDGE* StepRight)
{
	int Width;
	long u,v;
	long du,dv;
	unsigned short* pDestination;
	int subdivcnt;
	int pixelsleft;
	float oozr,uozr,vozr;
	float ZLeft,ULeft,VLeft;
	float ZRight,URight,VRight;
	float oozdx,uozdx,vozdx;
	float one = 1.0f;
	long yline;
	short r,g,b;
	short texel,tr,tg,tb;
	double fconv;

	r = Gradients->rf>>3;
	g = Gradients->gf>>3;
	b = Gradients->bf>>3;
	
	if(r == 31 && g == 31 && b == 31)
	{	
		ScanLinesT(Gradients,pLeft,pRight,StepLeft,StepRight);
		return;
	}
	
	oozdx = Gradients->dozx * float(SUBDIVSPAN);
	uozdx = Gradients->duzx * float(SUBDIVSPAN);
	vozdx = Gradients->dvzx * float(SUBDIVSPAN);

	yline = long(Output)+YTable[pLeft->y];

	while(StepLeft->height--)
	{
		ZLeft = pLeft->ooz;

		_asm
		{
			// 1.0f/pLeft->ooz
			fld  [one]
			fdiv [ZLeft]
		}
	
		
		pDestination = (unsigned short*) yline + pLeft->x;
		Width = (pRight->x - pLeft->x);

		_asm
		{
			// ZLeft = 1.0f/pLeft->ooz
			fstp [ZLeft]
		}

		oozr = pLeft->ooz+oozdx;
		uozr = pLeft->uoz+uozdx;
		vozr = pLeft->voz+vozdx;
		
		ULeft = pLeft->uoz * ZLeft;
		VLeft = pLeft->voz * ZLeft;

		if(Width > 0)
		{
			
			_asm
			{
				fld	 one
				fdiv [oozr]
			}

			subdivcnt  = Width>>SUBDIVSHIFT;				
			pixelsleft = Width-(subdivcnt<<SUBDIVSHIFT);

			_asm
			{
				fstp [ZRight]
			}
			
			while(subdivcnt-- > 0)
			{

				URight = uozr * ZRight;
				VRight = vozr * ZRight;
								
				u  = FTOLFIX(ULeft);
				v  = FTOLFIX(VLeft);
				
				du = FTOLFIX(URight - ULeft)>>SUBDIVSHIFT;
				dv = FTOLFIX(VRight - VLeft)>>SUBDIVSHIFT;
				
				oozr += oozdx;
			
				_asm
				{
					// one/oozr;
					fld	 [one]
					fdiv [oozr]
				}

				PIXELOUT(0,r,g,b);
				PIXELOUT(1,r,g,b);
				PIXELOUT(2,r,g,b);
				PIXELOUT(3,r,g,b);
				PIXELOUT(4,r,g,b);
				PIXELOUT(5,r,g,b);
				PIXELOUT(6,r,g,b);
				PIXELOUT(7,r,g,b);
				PIXELOUT(8,r,g,b);
				PIXELOUT(9,r,g,b);
				PIXELOUT(10,r,g,b);
				PIXELOUT(11,r,g,b);
				PIXELOUT(12,r,g,b);
				PIXELOUT(13,r,g,b);
				PIXELOUT(14,r,g,b);
				PIXELOUT(15,r,g,b);
					
				pDestination += 16;
				
				_asm
				{
					// ZRight = one/oozr
					fstp	[ZRight]		
				}

				ULeft = URight;
				VLeft = VRight;

				vozr += vozdx;
				uozr += uozdx;

			}
			
			if(pixelsleft)
			{
				u  = FTOLFIX(ULeft);
				v  = FTOLFIX(VLeft);
			
				if(--pixelsleft)
				{
					ZRight = 1.0f/(pRight->ooz - Gradients->dozx);
	
					URight = ZRight * (pRight->uoz - Gradients->duzx);
					VRight = ZRight * (pRight->voz - Gradients->dvzx);
					
					float opixf;
					opixf = WidthTable[pixelsleft];

					du = FTOLFIX(URight - ULeft);
					dv = FTOLFIX(VRight - VLeft);

					du = FTOL(float(du)*opixf);
					dv = FTOL(float(dv)*opixf);
				}

				for(int n=0;n<=(pixelsleft);n++)
				{	
					PIXELOUT(0,r,g,b);
					pDestination++;
				}

  
			}
		
		}

		yline += bytepitch;

		StepLeft->x += StepLeft->xstep;
		StepLeft->y++;
		StepLeft->uoz += StepLeft->uozstep;
		StepLeft->voz += StepLeft->vozstep;
		StepLeft->ooz += StepLeft->oozstep;

		StepLeft->ErrorTerm += StepLeft->Numerator;
	
		if(StepLeft->ErrorTerm >= StepLeft->Denominator)
		{
			StepLeft->x++;
			StepLeft->ooz += StepLeft->oozxtra;
			StepLeft->uoz += StepLeft->uozxtra;
			StepLeft->voz += StepLeft->vozxtra;
			StepLeft->ErrorTerm -= StepLeft->Denominator;
		}


		StepRight->x += StepRight->xstep;
		StepRight->y++;
		StepRight->uoz += StepRight->uozstep;
		StepRight->voz += StepRight->vozstep;
		StepRight->ooz += StepRight->oozstep;

		StepRight->ErrorTerm += StepRight->Numerator;
	
		if(StepRight->ErrorTerm >= StepRight->Denominator)
		{
			StepRight->x++;
			StepRight->ooz += StepRight->oozxtra;
			StepRight->uoz += StepRight->uozxtra;
			StepRight->voz += StepRight->vozxtra;
			StepRight->ErrorTerm -= StepRight->Denominator;
		}
	}
}

// EOF : ScanLinesTFDecal








void ScanLinesTFDecalAffine(GRADIENT* Gradients,EDGE* pLeft,EDGE* pRight,EDGE* StepLeft,EDGE* StepRight)
{
	int Width;
	unsigned short* pDestination;
	long u,v,du,dv;
	long yline;
	float oowidth;
	short subdivcnt;
	short r,g,b;
	short texel,tr,tg,tb;
	double fconv;

	r = Gradients->rf>>3;
	g = Gradients->gf>>3;
	b = Gradients->bf>>3;

	if(r == 31 && g == 31 && b == 31)
	{	
		ScanLinesTAffine(Gradients,pLeft,pRight,StepLeft,StepRight);
		return;
	}

	yline = long(Output)+YTable[pLeft->y];
	
	while(StepLeft->height--)
	{
		Width  = pRight->x;
		Width -= pLeft->x;

		if(Width > 0)
		{
			pDestination = (unsigned short*) yline + pLeft->x;
			
			u = pLeft->uozf;
			v = pLeft->vozf;

			oowidth = WidthTable[Width];

			du = (pRight->uozf - pLeft->uozf);
			du = FTOL(float(du)*oowidth);
			
			dv = (pRight->vozf - pLeft->vozf);
			dv = FTOL(float(dv)*oowidth);
			
			subdivcnt = Width>>4;
			Width = Width-(subdivcnt<<4);

			while(subdivcnt--)
			{
				PIXELOUT(0,r,g,b);
				PIXELOUT(1,r,g,b);
				PIXELOUT(2,r,g,b);
				PIXELOUT(3,r,g,b);
				PIXELOUT(4,r,g,b);
				PIXELOUT(5,r,g,b);
				PIXELOUT(6,r,g,b);
				PIXELOUT(7,r,g,b);
				PIXELOUT(8,r,g,b);
				PIXELOUT(9,r,g,b);
				PIXELOUT(10,r,g,b);
				PIXELOUT(11,r,g,b);
				PIXELOUT(12,r,g,b);
				PIXELOUT(13,r,g,b);
				PIXELOUT(14,r,g,b);
				PIXELOUT(15,r,g,b);
				pDestination += 16;
			}

			for(int n=0;n<Width;n++)
			{
				PIXELOUT(0,r,g,b);
				pDestination++;
			}
		}

		yline += bytepitch;

		StepLeft->uozf += StepLeft->uozstepf;
		StepLeft->vozf += StepLeft->vozstepf;
		StepLeft->x    += StepLeft->xstep;
		StepLeft->y++;
		StepLeft->ErrorTerm += StepLeft->Numerator;

		if(StepLeft->ErrorTerm >= StepLeft->Denominator)
		{
			StepLeft->x++;
			StepLeft->uozf += StepLeft->uozxtraf;
			StepLeft->vozf += StepLeft->vozxtraf;
			StepLeft->ErrorTerm -= StepLeft->Denominator;
		}
		
		StepRight->x    += StepRight->xstep;
		StepRight->uozf += StepRight->uozstepf;
		StepRight->vozf += StepRight->vozstepf;
		StepRight->y++;
		
		StepRight->ErrorTerm += StepRight->Numerator;

		if(StepRight->ErrorTerm >= StepRight->Denominator)
		{
			StepRight->x++;
			StepRight->uozf += StepRight->uozxtraf;
			StepRight->vozf += StepRight->vozxtraf;
			StepRight->ErrorTerm -= StepRight->Denominator;
		}
	}
}


// EOF : ScanLinesTFDecalAffine

