
import java.applet.*;
import java.awt.*;
import java.awt.image.*;

public class MainClass extends Applet
{
	final int 	W=320,
				H=240;
	Image 				img 	= null;
	MemoryImageSource 	mis 	= null;
	Image				texture	= null;
	MediaTracker		mt		= null;
	
	public void init()
	{
		this.setSize(W,H);
		this.setBackground(Color.GRAY);
		
		mt = new MediaTracker(this);				
		texture = this.getImage(this.getCodeBase(),"texture.jpg");	
		mt.addImage(texture,0);
		try {
			mt.waitForAll();
		} catch (InterruptedException ie) {
			System.err.println("MediaTracker : Interrupted!");
			return;
		}
		
		int texturePixels[] = new int[W*H];
		PixelGrabber pg = new PixelGrabber(texture, 0, 0, W, H, texturePixels, 0, W);
		try {
		    pg.grabPixels();
		} catch (InterruptedException e) {
		    System.err.println("PixelGrabber : Interrupted!");
		    return;
		}		
		
		int pixels[] = new int[W*H];		
		for (int i=0; i < W*H; i++)
			pixels[i] =  255 << 24 | 255 << 16 | 255 << 8 | 255;			
	
		pixels = this.texturePolygon(	new Point(50,50), 
										new Point(150,50),
										new Point(150,150),
										new Point(0,0), 
										new Point(W,H),
										new Point(W,0),
										W,H, 
										texturePixels,
										pixels);

		mis = new MemoryImageSource(W, H, pixels, 0, W);		
	    img = createImage(mis);		    	    
	}
	
	public void paint (Graphics g)
	{		
		g.drawImage(img,0,0,this);
	}
	

	//-----------------------------------------------------------------------
	// Draw texture polygon
	//-----------------------------------------------------------------------
	public int[] texturePolygon(	Point fpP1, Point fpP2, Point fpP3,
									Point fpUV1, Point fpUV2, Point fpUV3,
									int textureW, int textureH,
									int fpTexturePixels[], int fpPixels[])
	{		
		if (fpP1.y > fpP2.y)
		{			
			Point tempPoint = fpP1;
			fpP1 = fpP2;
			fpP2 = tempPoint;
			tempPoint = fpUV1;
			fpUV1 = fpUV2;
			fpUV2 = tempPoint;
		}		
		if (fpP2.y > fpP3.y)
		{
			Point tempPoint = fpP2;
			fpP2 = fpP3;
			fpP3 = tempPoint;
			tempPoint = fpUV2;
			fpUV2 = fpUV3;
			fpUV3 = tempPoint;			
		}		
		if (fpP1.y > fpP3.y)
		{
			Point tempPoint = fpP1;
			fpP1 = fpP3;
			fpP3 = tempPoint;
			tempPoint = fpUV1;
			fpUV1 = fpUV3;
			fpUV3 = tempPoint;			
		}
		
		float CEdgeX = fpP1.x;
		float CEdgeDeltaY = fpP3.y - fpP1.y;
		float CEdgeDeltaX = fpP3.x - fpP1.x;
		float CEdgeStep = CEdgeDeltaX/CEdgeDeltaY;
		float CU = fpUV1.x;
		float CV = fpUV1.y;
		float CDeltaU = fpUV3.x - fpUV1.x;
		float CDeltaV = fpUV3.y - fpUV1.y;
		float CStepU = CDeltaU/CEdgeDeltaY;
		float CStepV = CDeltaV/CEdgeDeltaY;
		
		// Polygon top
		if (fpP1.y != fpP2.y)
		{
			float AEdgeX = fpP1.x;
			float AEdgeDeltaY = fpP2.y-fpP1.y;
			float AEdgeDeltaX = fpP2.x-fpP1.x;
			float AEdgeStep = AEdgeDeltaX/AEdgeDeltaY;
			float AU = fpUV1.x;
			float AV = fpUV1.y;
			float ADeltaU = fpUV2.x - fpUV1.x;
			float ADeltaV = fpUV2.y - fpUV1.y;
			float AStepU = ADeltaU/AEdgeDeltaY;
			float AStepV = ADeltaV/AEdgeDeltaY;			
			
			for (int i=fpP1.y; i < fpP2.y; i++)
			{
				AEdgeX += AEdgeStep;
				CEdgeX += CEdgeStep;				
				AU += AStepU;
				AV += AStepV;
				CU += CStepU;
				CV += CStepV;
				
				int x1 = (int)AEdgeX;
				int x2 = (int)CEdgeX;
				fpPixels = textureScanLine (	new Point(x1,i),
												new Point(x2,i),
												new Point((int)AU, (int)AV),
												new Point((int)CU, (int)CV),
												320,240,
												fpTexturePixels,
												fpPixels);
			}
		}
		
		// Polygon bottom
		if (fpP2.y != fpP3.y)
		{
			float BEdgeX = fpP2.x;
			float BEdgeDeltaY = fpP3.y-fpP2.y;
			float BEdgeDeltaX = fpP3.x-fpP2.x;
			float BEdgeStep = BEdgeDeltaX/BEdgeDeltaY;
			float BU = fpUV2.x;
			float BV = fpUV2.y;
			float BDeltaU = fpUV3.x - fpUV2.x;
			float BDeltaV = fpUV3.y - fpUV2.y;
			float BStepU = BDeltaU/BEdgeDeltaY;
			float BStepV = BDeltaV/BEdgeDeltaY;						
						
			for (int i=fpP2.y; i < fpP3.y; i++)
			{
				BEdgeX += BEdgeStep;
				CEdgeX += CEdgeStep;
				BU += BStepU;
				BV += BStepV;
				CU += CStepU;
				CV += CStepV;				
				
				int x1 = (int)BEdgeX;
				int x2 = (int)CEdgeX;
			
				fpPixels = textureScanLine (	new Point(x1,i),
												new Point(x2,i),
												new Point((int)BU, (int)BV),
												new Point((int)CU, (int)CV),
												320,240,
												fpTexturePixels,
												fpPixels);
												
			}
		}		

		return fpPixels;
	}
	//-----------------------------------------------------------------------	
	
	//-----------------------------------------------------------------------
	// Draw texture scanline
	//-----------------------------------------------------------------------	
	public int[] textureScanLine(	Point fpP1, Point fpP2,
									Point fpUV1, Point fpUV2,
									int fpTextureW, int fpTextureH,
									int fpTexturePixels[],
									int fpPixels[])
	{
		if (fpP1.x > fpP2.x)
		{
			Point tempPoint = fpP1;
			fpP1 = fpP2;
			fpP2 = tempPoint;

			Point tUV = fpUV1;
			fpUV1 = fpUV2;
			fpUV2 = tUV;
		}
		
		int delta = fpP2.x - fpP1.x;
		int deltaU = fpUV2.x - fpUV1.x;
		int deltaV = fpUV2.y - fpUV1.y;
		float stepU = 0.0f;
		float stepV = 0.0f;
		if (delta != 0)
		{
			stepU = deltaU/delta;
			stepV = deltaV/delta;
		}
		float U = fpUV1.x;
		float V = fpUV1.y;
		
		if (delta != 0)
		{							
			for (int i=fpP1.x; i < fpP2.x; i++)
			{
				U += stepU;
				V += stepV;
				int tPixel = 0;
				if (U > 0.0 && U < fpTextureW)				
					if (V > 0.0 && V < fpTextureH)					
						tPixel = fpTexturePixels[(int)((int)V*fpTextureW+(int)U)];
				
				fpPixels[fpP1.y * W + i] = tPixel;
			}
		}		
		return fpPixels;
	}
	//-----------------------------------------------------------------------
	
}