Interpolacja kolorów w trójkącie

0

Witam.

Mam problem przy interpolacji kolorów z wierzchołków na cały trójkąt.
Prawa krawędź jest "poszarpana".
Czy ktoś dopatrzył się może jakiegoś błędu, który powoduje nieprawidłowe wypełnienie trójkąta?

Oto kod z przykładem działania:

public static void drawTriangle(BufferedImage image,int p1X,int p1Y,int p2X,int p2Y,int p3X,int p3Y,Color a,Color b, Color c, int ox, int oy)
	{
		if(a.equals(b) && b.equals(c))
		{
			Polygon pol = new Polygon();
			pol.addPoint(p1X, p1Y);
			pol.addPoint(p2X, p2Y);
			pol.addPoint(p3X, p3Y);
			Graphics2D g2d = (Graphics2D)image.getGraphics();
			g2d.setColor(a);
			g2d.fillPolygon(pol);
		}
		else
		{
		float p1x,p1y,p2x,p2y,p3x,p3y;//współrzedne wierzcholków
		Color c1,c2,c3;//kolory w wierzchołkach
		float dx1,dx2,dx3;//delty używane przy interpolacji x-ów
		float dr1,dr2,dr3, dg1,dg2,dg3, db1,db2,db3;//delty używane przy interpolacji kolorów
		
		float c1r,c2r,c3r,c1g,c2g,c3g,c1b,c2b,c3b;
		float scr,scg,scb,ecr,ecg,ecb;
		c1r=c2r=c3r=c1g=c2g=c3g=c1b=c2b=c3b=0;
		scr=scg=scb=ecr=ecg=ecb=0;
		c1 = c2 = c3 = null;
		p1x=p1y=p2x=p2y=p3x=p3y=0;
		dx1=dx2=dx3=0;
		dr1=dr2=dr3=dg1=dg2=dg3=db1=db2=db3=0;
		float dr,dg,db;
		dr = dg = db = 0;
		
		float sx,sy,ex,ey;
		Color sc, ec;
		sc=ec=null;
		sx=sy=ex=ey = 0;
		
		float px = 0;
		float py = 0;
		Color pc = null;
		float pcr,pcg,pcb;
		pcr=pcg=pcb=0;
		//sortowanie p1y <= p2y <= p3y
		if(p1Y <= p2Y)
		{
			if(p2Y <= p3Y)
			{
				p1x = p1X;
				p1y = p1Y;
				p2x = p2X;
				p2y = p2Y;
				p3x = p3X;
				p3y = p3Y;
				c1r=a.getRed();
				c2r=b.getRed();
				c3r=c.getRed();
				c1g=a.getGreen();
				c2g=b.getGreen();
				c3g=c.getGreen();
				c1b=a.getBlue();
				c2b=b.getBlue();
				c3b=c.getBlue();
				/*
				c1 = a;
				c2 = b;
				c3 = c;
				*/
			}
			else
			{
				p1x = p1X;
				p1y = p1Y;
				p2x = p3X;
				p2y = p3Y;
				p3x = p2X;
				p3y = p2Y;
				/*
				c1 = a;
				c2 = c;
				c3 = b;
				*/
				c1r=a.getRed();
				c2r=c.getRed();
				c3r=b.getRed();
				c1g=a.getGreen();
				c2g=c.getGreen();
				c3g=b.getGreen();
				c1b=a.getBlue();
				c2b=c.getBlue();
				c3b=b.getBlue();
			}
		}
		else if(p2Y<=p1Y)
		{
			if(p1Y <= p3Y)
			{
				p1x = p2X;
				p1y = p2Y;
				p2x = p1X;
				p2y = p1Y;
				p3x = p3X;
				p3y = p3Y;
				/*
				c1 = b;
				c2 = a;
				c3 = c;
				*/
				c1r=b.getRed();
				c2r=a.getRed();
				c3r=c.getRed();
				c1g=b.getGreen();
				c2g=a.getGreen();
				c3g=c.getGreen();
				c1b=b.getBlue();
				c2b=a.getBlue();
				c3b=c.getBlue();
			}
			else
			{
				p1x = p2X;
				p1y = p2Y;
				p2x = p3X;
				p2y = p3Y;
				p3x = p1X;
				p3y = p1Y;
				/*
				c1 = b;
				c2 = c;
				c3 = a;
				*/
				c1r=b.getRed();
				c2r=c.getRed();
				c3r=a.getRed();
				c1g=b.getGreen();
				c2g=c.getGreen();
				c3g=a.getGreen();
				c1b=b.getBlue();
				c2b=c.getBlue();
				c3b=a.getBlue();
			}
		}
		else if(p3Y <= p1Y)
		{
			if(p1Y <= p2Y)
			{
				p1x = p3X;
				p1y = p3Y;
				p2x = p1X;
				p2y = p1Y;
				p3x = p2X;
				p3y = p2Y;
				/*
				c1 = c;
				c2 = a;
				c3 = b;
				*/
				c1r=c.getRed();
				c2r=a.getRed();
				c3r=b.getRed();
				c1g=c.getGreen();
				c2g=a.getGreen();
				c3g=b.getGreen();
				c1b=c.getBlue();
				c2b=a.getBlue();
				c3b=b.getBlue();
			}
			else
			{
				p1x = p3X;
				p1y = p3Y;
				p2x = p2X;
				p2y = p2Y;
				p3x = p1X;
				p3y = p1Y;
				/*
				c1 = c;
				c2 = b;
				c3 = a;
				*/
				c1r=c.getRed();
				c2r=b.getRed();
				c3r=a.getRed();
				c1g=c.getGreen();
				c2g=b.getGreen();
				c3g=a.getGreen();
				c1b=c.getBlue();
				c2b=b.getBlue();
				c3b=a.getBlue();
			}
		}
		
		p1x+=ox;
		p2x+=ox;
		p3x+=ox;
		p1y-=oy;
		p2y-=oy;
		p3y-=oy;
		
		//wyliczanie delt dla składowych koloru
		if (p2y-p1y > 0) 
		{
			dx1=(p2x-p1x)/(p2y-p1y);
			/*
			dr1=(c2.getRed()-c1.getRed())/(p2y-p1y);
			dg1=(c2.getGreen()-c1.getGreen())/(p2y-p1y);
			db1=(c2.getBlue()-c1.getBlue())/(p2y-p1y);
			*/
			dr1=(c2r-c1r)/(p2y-p1y);
			dg1=(c2g-c1g)/(p2y-p1y);
			db1=(c2b-c1b)/(p2y-p1y);
		} 
		else 
			dx1=dr1=dg1=db1=0;

		if (p3y-p1y > 0) 
		{
			dx2=(p3x-p1x)/(p3y-p1y);
			/*
			dr2=(c3.getRed()-c1.getRed())/(p3y-p1y);
			dg2=(c3.getGreen()-c1.getGreen())/(p3y-p1y);
			db2=(c3.getBlue()-c1.getBlue())/(p3y-p1y);
			*/
			dr2=(c3r-c1r)/(p3y-p1y);
			dg2=(c3g-c1g)/(p3y-p1y);
			db2=(c3b-c1b)/(p3y-p1y);
		} 
		else 
			dx2=dr2=dg2=db2=0;

		if (p3y-p2y > 0) 
		{
			dx3=(p3x-p2x)/(p3y-p2y);
			/*
			dr3=(c3.getRed()-c2.getRed())/(p3y-p2y);
			dg3=(c3.getGreen()-c2.getGreen())/(p3y-p2y);
			db3=(c3.getBlue()-c2.getBlue())/(p3y-p2y);
			*/
			dr3=(c3r-c2r)/(p3y-p2y);
			dg3=(c3g-c2g)/(p3y-p2y);
			db3=(c3b-c2b)/(p3y-p2y);
		} 
		else 
			dx3=dr3=dg3=db3=0;
		
		sx = ex = p1x;
		sy = ey = p1y;
		/*
		sc = new Color(c1.getRed(),c1.getGreen(),c1.getBlue());
		ec = new Color(c1.getRed(),c1.getGreen(),c1.getBlue());
		*/
		scr=ecr=c1r;
		scg=ecg=c1g;
		scb=ecb=c1b;
		
		if(dx1 > dx2)
		{
			for(;sy <= p2y;sy++,ey++)
			{
				if(ex-ex > 0) 
				{
					/*
					dr=(ec.getRed()-sc.getRed())/(ex-sx);
					dg=(ec.getGreen()-sc.getGreen())/(ex-sx);
					db=(ec.getBlue()-sc.getBlue())/(ex-sx);
					*/
					dr=(ecr-scr)/(ex-sx);
					dg=(ecg-scg)/(ex-sx);
					db=(ecb-scb)/(ex-sx);
				} 
				else 
					dr=dg=db=0;
				
				
				px = sx;
				py = sy;
				pcr = scr;
				pcg = scg;
				pcb = scb;
				
				
				for(;px < ex;px++) 
				{
					try{
						image.setRGB(Math.round(px), Math.round(py), RGBToInt(new Color(Math.round(pcr),Math.round(pcg),Math.round(pcb))));
					}
					catch(Exception e)
					{
						System.out.println("1");
					}
					/*
					pc = new Color((int)(pc.getRed()+dr),(int)(pc.getGreen()+dg),(int)(pc.getBlue()+db));
					*/
					pcr+=dr;
					pcg+=dg;
					pcb+=db;
				}
				sx+=dx2;
				ex+=dx1;
				
				/*
				sc = new Color((int)(sc.getRed()+dr2),(int)(sc.getGreen()+dg2),(int)(sc.getBlue()+db2));
				ec = new Color((int)(ec.getRed()+dr1),(int)(ec.getGreen()+dg1),(int)(ec.getBlue()+db1));
				*/
				
				scr+=dr2;
				scg+=dg2;
				scb+=db2;
				
				ecr+=dr1;
				ecg+=dg1;
				ecb +=db1;
				
			}
			
			ex = p2x;
			ey = p2y;
			/*
			ec = new Color(c2.getRed(),c2.getGreen(),c2.getBlue());
			*/
			ecr = c2r;
			ecg = c2g;
			ecb = c2b;
			
			
			for(;sy<=p3y;sy++,ey++) 
			{
				if(ex-sx > 0) {
					/*
					dr=(ec.getRed()-sc.getRed())/(ex-sx);
					dg=(ec.getGreen()-sc.getGreen())/(ex-sx);
					db=(ec.getBlue()-sc.getBlue())/(ex-sx);
					*/
					dr=(ecr-scr)/(ex-sx);
					dg=(ecg-scg)/(ex-sx);
					db=(ecb-scb)/(ex-sx);
				} 
				else 
					dr=dg=db=0;
				
				px = sx;
				py = sy;
				/*
				pc = new Color(sc.getRed(),sc.getGreen(),sc.getBlue());;
				*/
				pcr = scr;
				pcg = scg;
				pcb = scb;
				
				for(;px < ex;px++) 
				{
					
						try
						{
							image.setRGB(Math.round(px), Math.round(py), RGBToInt(new Color(Math.round(pcr),Math.round(pcg),Math.round(pcb))));
						}
						catch(Exception e)
						{
							System.out.println("2");
						}
					/*
					pc = new Color((int)(pc.getRed()+dr),(int)(pc.getGreen()+dg),(int)(pc.getBlue()+db));
					*/
					pcr+=dr;
					pcg+=dg;
					pcb+=db;
					
				}
				/*
				sx+=dx2; sc = new Color((int)(sc.getRed()+dr2),(int)(sc.getGreen()+dg2),(int)(sc.getBlue()+db2));
				ex+=dx3; ec = new Color((int)(ec.getRed()+dr3),(int)(ec.getGreen()+dg3),(int)(ec.getBlue()+db3));
				*/
				sx+=dx2;
				ex+=dx3;
				
				scr+=dr2;
				scg+=dg2;
				scb+=db2;
				
				ecr+=dr3;
				ecg+=dg3;
				ecb+=db3;
			}
		}
		else 
		{
			for(;sy<=p2y;sy++,ey++) 
			{
				
				
				
				if(ex-sx > 0) {
					/*
					dr=(ec.getRed()-sc.getRed())/(ex-sx);
					dg=(ec.getGreen()-sc.getGreen())/(ex-sx);
					db=(ec.getBlue()-sc.getBlue())/(ex-sx);
					*/
					dr=(ecr-scr)/(ex-sx);
					dg=(ecg-scg)/(ex-sx);
					db=(ecb-scb)/(ex-sx);
				} 
				else 
					dr=dg=db=0;

				px = sx;
				py = sy;
				/*
				pc = new Color(sc.getRed(),sc.getGreen(),sc.getBlue());;
				*/
				pcr=scr;;
				pcg=scg;
				pcb=scb;
				
				
				for(;px < ex;px++) 
				{
					
					try
					{
						image.setRGB(Math.round(px), Math.round(py), RGBToInt(new Color(Math.round(pcr),Math.round(pcg),Math.round(pcb))));
					}
					catch(Exception e)
					{
						System.out.println("3");
					}
					/*
					pc = new Color((int)(pc.getRed()+dr),(int)(pc.getGreen()+dg),(int)(pc.getBlue()+db));
					*/
					pcr+=dr;
					pcg+=dg;
					pcb+=db;
					
				}
				/*
				sx+=dx1; sc = new Color((int)(sc.getRed()+dr1),(int)(sc.getGreen()+dg1),(int)(sc.getBlue()+db1));
				ex+=dx2; ec = new Color((int)(ec.getRed()+dr2),(int)(ec.getGreen()+dg2),(int)(ec.getBlue()+db2));
				*/
				sx+=dx1;
				ex+=dx2;
				
				scr+=dr1;
				scg+=dg1;
				scb+=db1;
				
				ecr+=dr2;
				ecg+=dg2;
				ecb+=db2;
			}


			sx = p2x;
			sy = p2y;
			/*
			sc = new Color(c2.getRed(),c2.getGreen(),c2.getBlue());
			*/
			scr = c2r;
			scg = c2g;
			scb = c2b;
			
			
			for(;sy<=p3y;sy++,ey++) {
				if(ex-sx > 0) {
					/*
					dr=(ec.getRed()-sc.getRed())/(ex-sx);
					dg=(ec.getGreen()-sc.getGreen())/(ex-sx);
					db=(ec.getBlue()-sc.getBlue())/(ex-sx);
					*/
					dr=(ecr-scr)/(ex-sx);
					dg=(ecg-scg)/(ex-sx);
					db=(ecb-scb)/(ex-sx);
				} 
				else 
					dr=dg=db=0;
				
				px = sx;
				py = sy;
				/*
				pc = new Color(sc.getRed(),sc.getGreen(),sc.getBlue());;
				*/
				pcr = scr;
				pcg = scg;
				pcb = scb;
				
				for(;px < ex;px++) {
					
					try{
						image.setRGB(Math.round(px), Math.round(py), RGBToInt(new Color(Math.round(pcr),Math.round(pcg),Math.round(pcb))));
						}
						catch(Exception e)
						{
							System.out.println("4");
						}
					/*
					pc = new Color((int)(pc.getRed()+dr),(int)(pc.getGreen()+dg),(int)(pc.getBlue()+db));
					*/
					
						pcr += dr;
					
						pcg+=dg;
					
						pcb+=db;
					
				}
				/*
				sx+=dx3; sc = new Color((int)(sc.getRed()+dr3),(int)(sc.getGreen()+dg3),(int)(sc.getBlue()+db3));
				ex+=dx2; ec = new Color((int)(ec.getRed()+dr2),(int)(ec.getGreen()+dg2),(int)(ec.getBlue()+db2));'
				*/
				sx+=dx3;
				ex+=dx2;
				
				scr+=dr3;
				scg+=dg3;
				scb+=db3;
				
				ecr+=dr2;
				ecg+=dg2;
				ecb+=db2;
			}
		}
		}
	}

<image>http://fotoo.pl/show.php/47390_nnn.bmp.html"]przykład</image>

0

Strasznie zagmatwany ten kod i ciężko się to czyta strasznie. Obstawiał bym jednak, że winny jest brak ustawionego anty aliasingu przy tworzeniu i/lub wyświetlaniu obrazka.

g2.setRenderingHints(RenderingHints.KEY_ANTIALIASING , RenderingHints.VALUE_ANTIALIAS_ON);
0

Faktycznie kod trochę zagmatwany, ale problem udało mi się rozwiązać.
Zostaje tylko jeden problem: nie rysuje trójkątów obróconych o 180 st.
tj. user image

Zamieszczam pseudokod aby ułatwić zrozumienie problemu:

 
the coordinates of vertices are (A.x,A.y), (B.x,B.y), (C.x,C.y) we assume that A.y<=B.y<=C.y (you should sort them first)
vertex A has color (A.r,A.g,A.b), B (B.r,B.g,B.b), C (C.r,C.g,C.b), where X.r is color's red component, X.g is color's green component and X.b is color's blue component
dx1,dx2,dx3 are deltas used in interpolation of x-coordinate
dr1,dr2,dr3, dg1,dg2,dg3, db1,db2,db3 are deltas used in interpolation of color's components
putpixel(P) plots a pixel with coordinates (P.x,P.y) and color (P.r,P.g,P.b)
S=A means that S.x=A.x; S.y=A.y; S.r=A.r; S.g=A.g; S.b=A.b;
*** begin gouraud triangle filler ***

	if (B.y-A.y > 0) {
		dx1=(B.x-A.x)/(B.y-A.y);
		dr1=(B.r-A.r)/(B.y-A.y);
		dg1=(B.g-A.g)/(B.y-A.y);
		db1=(B.b-A.b)/(B.y-A.y);
	} else 
		dx1=dr1=dg1=db1=0;

	if (C.y-A.y > 0) {
		dx2=(C.x-A.x)/(C.y-A.y);
		dr2=(C.r-A.r)/(C.y-A.y);
		dg2=(C.g-A.g)/(C.y-A.y);
		db2=(C.b-A.b)/(C.y-A.y);
	} else 
		dx2=dr2=dg2=db2=0;

	if (C.y-B.y > 0) {
		dx3=(C.x-B.x)/(C.y-B.y);
		dr3=(C.r-B.r)/(C.y-B.y);
		dg3=(C.g-B.g)/(C.y-B.y);
		db3=(C.b-B.b)/(C.y-B.y);
	} else 
		dx3=dr3=dg3=db3=0;

	S=E=A;
	if(dx1 > dx2) {
		for(;S.y<=B.y;S.y++,E.y++) {
			if(E.x-S.x > 0) {
				dr=(E.r-S.r)/(E.x-S.x);
				dg=(E.g-S.g)/(E.x-S.x);
				db=(E.b-S.b)/(E.x-S.x);
			} else 
				dr=dg=db=0;
			P=S;
			for(;P.x < E.x;P.x++) {
				putpixel(P);
				P.r+=dr; P.g+=dg; P.b+=db;
			}
			S.x+=dx2; S.r+=dr2; S.g+=dg2; S.b+=db2;
			E.x+=dx1; E.r+=dr1; E.g+=dg1; E.b+=db1;
		}

		E=B;
		for(;S.y<=C.y;S.y++,E.y++) {
			if(E.x-S.x > 0) {
				dr=(E.r-S.r)/(E.x-S.x);
				dg=(E.g-S.g)/(E.x-S.x);
				db=(E.b-S.b)/(E.x-S.x);
			} else 
				dr=dg=db=0;
			P=S;
			for(;P.x < E.x;P.x++) {
				putpixel(P);
				P.r+=dr; P.g+=dg; P.b+=db;
			}
			S.x+=dx2; S.r+=dr2; S.g+=dg2; S.b+=db2;
			E.x+=dx3; E.r+=dr3; E.g+=dg3; E.b+=db3;
		}
	} else {
		for(;S.y<=B.y;S.y++,E.y++) {
			if(E.x-S.x > 0) {
				dr=(E.r-S.r)/(E.x-S.x);
				dg=(E.g-S.g)/(E.x-S.x);
				db=(E.b-S.b)/(E.x-S.x);
			} else 
				dr=dg=db=0;

			P=S;
			for(;P.x < E.x;P.x++) {
				putpixel(P);
				P.r+=dr; P.g+=dg; P.b+=db;
			}
			S.x+=dx1; S.r+=dr1; S.g+=dg1; S.b+=db1;
			E.x+=dx2; E.r+=dr2; E.g+=dg2; E.b+=db2;
		}

		S=B;
		for(;S.y<=C.y;S.y++,E.y++) {
			if(E.x-S.x > 0) {
				dr=(E.r-S.r)/(E.x-S.x);
				dg=(E.g-S.g)/(E.x-S.x);
				db=(E.b-S.b)/(E.x-S.x);
			} else 
				dr=dg=db=0;

			P=S;
			for(;P.x < E.x;P.x++) {
				putpixel(P);
				P.r+=dr; P.g+=dg; P.b+=db;
			}
			S.x+=dx3; S.r+=dr3; S.g+=dg3; S.b+=db3;
			E.x+=dx2; E.r+=dr2; E.g+=dg2; E.b+=db2;
		}
	}

1 użytkowników online, w tym zalogowanych: 0, gości: 1